diff --git a/gradle.properties b/gradle.properties index 55fd5c51..d1cdc916 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx2G org.gradle.daemon=false # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.20.6 -yarn_mappings=1.20.6+build.2 +minecraft_version=1.21 +yarn_mappings=1.21+build.1 loader_version=0.15.11 # Mod Properties mod_version=1.0.0 diff --git a/src/main/java/ca/spottedleaf/moonrise/common/config/MoonriseConfig.java b/src/main/java/ca/spottedleaf/moonrise/common/config/MoonriseConfig.java index 60ea7bef..ff4ee2c2 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/config/MoonriseConfig.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/config/MoonriseConfig.java @@ -36,21 +36,24 @@ public static final class ChunkLoading { public static final class Basic { @Serializable( comment = """ - The maximum number of chunks to send to any given player, per second. + The maximum rate of chunks to send to any given player, per second. If this value is <= 0, + then there is no rate limit. """ ) public double playerMaxSendRate = -1.0; @Serializable( comment = """ - The maximum number of chunks to load from disk for any given player, per second. + The maximum rate of chunks to load from disk for any given player, per second. If this value is <= 0, + then there is no rate limit. """ ) public double playerMaxLoadRate = -1.0; @Serializable( comment = """ - The maximum number of chunks to generate for any given player, per second. + The maximum rate of chunks to generate for given player, per second. If this value is <= 0, + then there is no rate limit. """ ) public double playerMaxGenRate = -1.0; @@ -78,8 +81,8 @@ public static final class Advanced { @Serializable( comment = """ The maximum amount of pending chunk loads per player. If - this value is less-than 1, then the player chunk loader will - automatically determine a value. + this value is 0, then the player chunk loader will automatically determine a value. If + this value is less-than 0, then there is no limit. This value should be used to tune the saturation of the chunk system. """ @@ -89,8 +92,8 @@ public static final class Advanced { @Serializable( comment = """ The maximum amount of pending chunk generations per player. If - this value is less-than 1, then the player chunk loader will - automatically determine a value. + this value is 0, then the player chunk loader will automatically determine a value. If + this value is less-than 0, then there is no limit. This value should be used to tune the saturation of the chunk system. """ diff --git a/src/main/java/ca/spottedleaf/moonrise/common/config/adapter/TypeAdapterRegistry.java b/src/main/java/ca/spottedleaf/moonrise/common/config/adapter/TypeAdapterRegistry.java index 05e2db31..21dc5ae3 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/config/adapter/TypeAdapterRegistry.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/config/adapter/TypeAdapterRegistry.java @@ -214,6 +214,9 @@ public T deserialize(final TypeAdapterRegistry registry, final Object input, fin final Object fieldValue = inputMap.get(field.serializedKey); if (fieldValue == null) { + if (field.required) { + throw new IllegalArgumentException("Missing required field '" + field.serializedKey + "' in " + this.constructor.getDeclaringClass()); + } continue; } diff --git a/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Adaptable.java b/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Adaptable.java index af87382c..3aa992a7 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Adaptable.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Adaptable.java @@ -7,7 +7,7 @@ /** * Annotation used on a class to indicate that its type adapter may automatically be generated. The class must have - * + * a public no-args constructor. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Serializable.java b/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Serializable.java index 37ddecdc..8ca9f50a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Serializable.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/config/annotation/Serializable.java @@ -9,7 +9,7 @@ /** * Annotation indicating that a field should be deserialized or serialized from the config. - * By default, this annotation is assumed + * By default, this annotation is not assumed. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) diff --git a/src/main/java/ca/spottedleaf/moonrise/common/config/config/YamlConfig.java b/src/main/java/ca/spottedleaf/moonrise/common/config/config/YamlConfig.java index 3e6b975c..4d3f2224 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/config/config/YamlConfig.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/config/config/YamlConfig.java @@ -67,6 +67,10 @@ public void load(final InputStream is) throws IOException { } public void save(final File file) throws IOException { + this.save(file, ""); + } + + public void save(final File file, final String header) throws IOException { if (file.isDirectory()) { throw new IOException("File is a directory"); } @@ -76,7 +80,7 @@ public void save(final File file) throws IOException { tmp.createNewFile(); try { try (final OutputStream os = new BufferedOutputStream(new FileOutputStream(tmp))) { - this.save(os); + this.save(os, header); } try { @@ -93,10 +97,30 @@ public void save(final OutputStream os) throws IOException { os.write(this.saveToString().getBytes(StandardCharsets.UTF_8)); } + public void save(final OutputStream os, final String header) throws IOException { + os.write(this.saveToString(header).getBytes(StandardCharsets.UTF_8)); + } + public String saveToString() { return this.yaml.dump(this.typeAdapters.serialize(this.config, this.clazz)); } + public String saveToString(final String header) { + if (header.isBlank()) { + return this.saveToString(); + } + + final StringBuilder ret = new StringBuilder(); + + for (final String line : header.split("\n")) { + ret.append("# ").append(line).append('\n'); + } + + ret.append('\n'); + + return ret.append(this.saveToString()).toString(); + } + private static final class YamlConstructor extends Constructor { public YamlConstructor(final LoaderOptions loadingConfig) { diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java b/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java index 41d048bf..7e033109 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java @@ -13,7 +13,7 @@ public final class MoonriseCommon { private static final Logger LOGGER = LoggerFactory.getLogger(MoonriseCommon.class); - private static final File CONFIG_FILE = new File("moonrise.yaml"); + private static final File CONFIG_FILE = new File(System.getProperty("Moonrise.ConfigFile", "moonrise.yml")); private static final YamlConfig CONFIG; static { try { @@ -22,6 +22,17 @@ public final class MoonriseCommon { throw new RuntimeException(ex); } } + private static final String CONFIG_HEADER = """ + This is the configuration file for Moonrise. + + Each configuration option is prefixed with a comment to explain what it does. Additional changes to this file + other than modifying the options, such as adding comments, will be overwritten when Moonrise loads the config. + + Below are the Moonrise startup flags. Note that startup flags must be placed in the JVM arguments, not + program arguments. + -DMoonrise.ConfigFile= - Override the config file location. Maybe useful for multiple game versions. + -DMoonrise.WorkerThreadCount= - Override the auto configured worker thread counts (worker-threads). + """; static { reloadConfig(); @@ -31,25 +42,27 @@ public static MoonriseConfig getConfig() { return CONFIG.config; } - public static void reloadConfig() { + public static boolean reloadConfig() { if (CONFIG_FILE.exists()) { try { CONFIG.load(CONFIG_FILE); } catch (final Exception ex) { LOGGER.error("Failed to load configuration, using defaults", ex); - return; + return false; } } // write back any changes, or create if needed - saveConfig(); + return saveConfig(); } - public static void saveConfig() { + public static boolean saveConfig() { try { - CONFIG.save(CONFIG_FILE); + CONFIG.save(CONFIG_FILE, CONFIG_HEADER); + return true; } catch (final Exception ex) { LOGGER.error("Failed to save configuration", ex); + return false; } } @@ -66,10 +79,8 @@ public static void saveConfig() { int workerThreads = MoonriseCommon.getConfig().workerThreads; - if (workerThreads < 0) { + if (workerThreads <= 0) { workerThreads = defaultWorkerThreads; - } else { - workerThreads = Math.max(1, workerThreads); } WORKER_POOL = new PrioritisedThreadPool( diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkGeneratorMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkGeneratorMixin.java index 0261c355..1f7199a0 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkGeneratorMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkGeneratorMixin.java @@ -22,7 +22,7 @@ public abstract class ChunkGeneratorMixin { /** - * @reason Use the provided executor, chunk system sets this to something specific + * @reason Use Runnable:run, as we schedule onto the moonrise common pool * @author Spottedleaf */ @Redirect( @@ -32,9 +32,8 @@ public abstract class ChunkGeneratorMixin { target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;" ) ) - private CompletableFuture redirectBiomesExecutor(final Supplier supplier, final Executor badExecutor, - @Local(ordinal = 0, argsOnly = true) final Executor executor) { - return CompletableFuture.supplyAsync(supplier, executor); + private CompletableFuture redirectBiomesExecutor(final Supplier supplier, final Executor badExecutor) { + return CompletableFuture.supplyAsync(supplier, Runnable::run); } /** diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java index d537dd02..51b827f5 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java @@ -12,6 +12,7 @@ import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.TicketType; import net.minecraft.world.level.ChunkPos; @@ -34,20 +35,15 @@ import java.util.concurrent.Executor; @Mixin(ChunkHolder.class) -public abstract class ChunkHolderMixin implements ChunkSystemChunkHolder { - - @Shadow - @Final - private ChunkPos pos; +public abstract class ChunkHolderMixin extends GenerationChunkHolder implements ChunkSystemChunkHolder { @Shadow @Final private ChunkHolder.PlayerProvider playerProvider; - @Shadow - @Final - public static CompletableFuture> UNLOADED_CHUNK_FUTURE; - + public ChunkHolderMixin(ChunkPos chunkPos) { + super(chunkPos); + } @Unique private NewChunkHolder newChunkHolder; @@ -126,26 +122,6 @@ private void initFields(final CallbackInfo ci) { this.playersSentChunkTo = new ReferenceList<>(EMPTY_PLAYER_ARRAY, 0); } - /** - * @reason Chunk system is not built on futures anymore, use {@link ChunkTaskScheduler} - * schedule methods to await for a chunk load - * @author Spottedleaf - */ - @Overwrite - public CompletableFuture> getFutureIfPresentUnchecked(final ChunkStatus chunkStatus) { - throw new UnsupportedOperationException(); - } - - /** - * @reason Chunk system is not built on futures anymore, use {@link ChunkTaskScheduler} - * schedule methods to await for a chunk load - * @author Spottedleaf - */ - @Overwrite - public CompletableFuture> getFutureIfPresent(final ChunkStatus chunkStatus) { - throw new UnsupportedOperationException(); - } - /** * @reason Chunk system is not built on futures anymore, use {@link ChunkTaskScheduler} * schedule methods to await for a chunk load @@ -196,7 +172,7 @@ public LevelChunk getTickingChunk() { * @author Spottedleaf */ @Overwrite - public CompletableFuture getChunkSendSyncFuture() { + public CompletableFuture getSendSyncFuture() { throw new UnsupportedOperationException(); } @@ -248,33 +224,13 @@ public LevelChunk getChunkToSend() { return null; } - /** - * @reason Route to new chunk holder - * @author Spottedleaf - */ - @Overwrite - public ChunkStatus getLastAvailableStatus() { - final NewChunkHolder.ChunkCompletion lastCompletion = this.newChunkHolder.getLastChunkCompletion(); - return lastCompletion == null ? null : lastCompletion.genStatus(); - } - - /** - * @reason Route to new chunk holder - * @author Spottedleaf - */ - @Overwrite - public ChunkAccess getLastAvailable() { - final NewChunkHolder.ChunkCompletion lastCompletion = this.newChunkHolder.getLastChunkCompletion(); - return lastCompletion == null ? null : lastCompletion.chunk(); - } - /** * @reason Chunk system is not built on futures anymore, unloading is now checked via {@link NewChunkHolder#isSafeToUnload()} * while holding chunk system locks. * @author Spottedleaf */ @Overwrite - public CompletableFuture getChunkToSave() { + public CompletableFuture getSaveSyncFuture() { throw new UnsupportedOperationException(); } @@ -296,27 +252,6 @@ private LevelChunk redirectBlockUpdate(final ChunkHolder instance) { return this.getChunkToSend(); } - /** - * @reason Need to reroute getFutureIfPresent to new chunk system call - * @author Spottedleaf - */ - @Redirect( - method = "sectionLightChanged", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ChunkHolder;getFutureIfPresent(Lnet/minecraft/world/level/chunk/status/ChunkStatus;)Ljava/util/concurrent/CompletableFuture;" - ) - ) - private CompletableFuture> redirectLightUpdate(final ChunkHolder instance, - final ChunkStatus chunkStatus) { - final NewChunkHolder.ChunkCompletion chunkCompletion = this.newChunkHolder.getLastChunkCompletion(); - if (chunkCompletion == null || !chunkCompletion.genStatus().isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) { - return UNLOADED_CHUNK_FUTURE; - } - - return CompletableFuture.completedFuture(ChunkResult.of(chunkCompletion.chunk())); - } - /** * @reason need to reroute getTickingChunk to getChunkToSend, as we do not bring all sent chunks to ticking * @author Spottedleaf @@ -347,36 +282,6 @@ private List redirectPlayerRetrieval(final ChunkHolder.PlayerProvi return this.moonrise$getPlayers(onlyOnWatchDistanceEdge); } - /** - * @reason Chunk system is not built on futures anymore, use {@link ChunkTaskScheduler} - * schedule methods to await for a chunk load - * @author Spottedleaf - */ - @Overwrite - public CompletableFuture> getOrScheduleFuture(final ChunkStatus chunkStatus, - final ChunkMap chunkMap) { - throw new UnsupportedOperationException(); - } - - /** - * @reason Chunk system is not built on futures anymore, use ticket levels to prevent chunk unloading. - * @author Spottedleaf - */ - @Overwrite - public void addSaveDependency(final String string, final CompletableFuture completableFuture) { - throw new UnsupportedOperationException(); - } - - /** - * @reason Chunk system is not built on futures anymore, use ticket levels to prevent chunk unloading. - * @author Spottedleaf - */ - @Overwrite - public void updateChunkToSave(CompletableFuture> completableFuture, - final String string) { - throw new UnsupportedOperationException(); - } - /** * @reason Chunk system is not built on futures anymore, and I am pretty sure this is a disgusting hack for a problem * that doesn't even exist. @@ -387,15 +292,6 @@ public void addSendDependency(final CompletableFuture completableFuture) { throw new UnsupportedOperationException(); } - /** - * @reason Route to new chunk holder - * @author Spottedleaf - */ - @Overwrite - public FullChunkStatus getFullStatus() { - return this.newChunkHolder.getChunkStatus(); - } - /** * @reason Route to new chunk holder * @author Spottedleaf @@ -483,22 +379,4 @@ public boolean wasAccessibleSinceLastSave() { public void refreshAccessibility() { throw new UnsupportedOperationException(); } - - /** - * @reason Chunk system is not built on futures anymore - * @author Spottedleaf - */ - @Overwrite - public void replaceProtoChunk(final ImposterProtoChunk imposterProtoChunk) { - throw new UnsupportedOperationException(); - } - - /** - * @reason Chunk system is not built on futures anymore - * @author Spottedleaf - */ - @Overwrite - public List>>> getAllFutures() { - throw new UnsupportedOperationException(); - } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java index e27baf96..0b670516 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java @@ -11,19 +11,24 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.StreamTagVisitor; +import net.minecraft.server.level.ChunkGenerationTask; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; import net.minecraft.server.level.ChunkTrackingView; +import net.minecraft.server.level.GeneratingChunkMap; +import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; +import net.minecraft.util.StaticCache2D; import net.minecraft.util.thread.ProcessorHandle; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStep; import net.minecraft.world.level.chunk.storage.ChunkScanAccess; import net.minecraft.world.level.chunk.storage.ChunkStorage; import net.minecraft.world.level.chunk.storage.RegionStorageInfo; @@ -47,7 +52,7 @@ import java.util.function.IntSupplier; @Mixin(ChunkMap.class) -public abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.PlayerProvider { +public abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.PlayerProvider, GeneratingChunkMap { @Shadow @Final @@ -244,7 +249,7 @@ public boolean promoteChunkMap() { * @author Spottedleaf */ @Overwrite - public CompletableFuture> schedule(final ChunkHolder holder, final ChunkStatus requiredStatus) { + public CompletableFuture> scheduleChunkLoad(final ChunkPos pos) { throw new UnsupportedOperationException(); } @@ -252,8 +257,9 @@ public CompletableFuture> schedule(final ChunkHolder ho * @reason Destroy old chunk system hooks * @author Spottedleaf */ + @Override @Overwrite - public CompletableFuture> scheduleChunkLoad(final ChunkPos pos) { + public GenerationChunkHolder acquireGeneration(final long pos) { throw new UnsupportedOperationException(); } @@ -261,9 +267,9 @@ public CompletableFuture> scheduleChunkLoad(final Chunk * @reason Destroy old chunk system hooks * @author Spottedleaf */ + @Override @Overwrite - public CompletableFuture> scheduleChunkGeneration(final ChunkHolder holder, - final ChunkStatus requiredStatus) { + public void releaseGeneration(final GenerationChunkHolder holder) { throw new UnsupportedOperationException(); } @@ -271,9 +277,30 @@ public CompletableFuture> scheduleChunkGeneration(final * @reason Destroy old chunk system hooks * @author Spottedleaf */ + @Override + @Overwrite + public CompletableFuture applyStep(final GenerationChunkHolder generationChunkHolder, final ChunkStep chunkStep, + final StaticCache2D staticCache2D) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Destroy old chunk system hooks + * @author Spottedleaf + */ + @Override + @Overwrite + public ChunkGenerationTask scheduleGenerationTask(final ChunkStatus chunkStatus, final ChunkPos chunkPos) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Destroy old chunk system hooks + * @author Spottedleaf + */ + @Override @Overwrite - public CompletableFuture> protoChunkToFullChunk(final ChunkHolder chunkHolder, - final ChunkAccess chunkAccess) { + public void runGenerationTasks() { throw new UnsupportedOperationException(); } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkPyramidMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkPyramidMixin.java new file mode 100644 index 00000000..929f4f53 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkPyramidMixin.java @@ -0,0 +1,45 @@ +package ca.spottedleaf.moonrise.mixin.chunk_system; + +import net.minecraft.world.level.chunk.status.ChunkPyramid; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStatusTasks; +import net.minecraft.world.level.chunk.status.ChunkStep; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import java.util.function.UnaryOperator; + +@Mixin(ChunkPyramid.class) +public abstract class ChunkPyramidMixin { + + /** + * @reason Starlight does not require loading neighbours for light data, as Starlight performs chunk edge checks on + * both light loading and light generation. As a result, we can skip loading the 8 neighbours for a basic + * chunk load - bringing the total access radius for a pure chunk load to 0. + * @author Spottedleaf + */ + @Redirect( + method = "", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/chunk/status/ChunkPyramid$Builder;step(Lnet/minecraft/world/level/chunk/status/ChunkStatus;Ljava/util/function/UnaryOperator;)Lnet/minecraft/world/level/chunk/status/ChunkPyramid$Builder;", + ordinal = 21 + ) + ) + private static ChunkPyramid.Builder removeLoadLightDependency(final ChunkPyramid.Builder instance, + final ChunkStatus chunkStatus, final UnaryOperator unaryOperator) { + if (chunkStatus != ChunkStatus.LIGHT) { + throw new RuntimeException("Redirected wrong target"); + } + if (ChunkPyramid.GENERATION_PYRAMID == null || ChunkPyramid.LOADING_PYRAMID != null) { + throw new RuntimeException("Redirected wrong target"); + } + return instance.step( + chunkStatus, + (builder -> { + return builder.setTask(ChunkStatusTasks::light); + }) + ); + } + +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStatusMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStatusMixin.java index 9349138a..b1823842 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStatusMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStatusMixin.java @@ -28,9 +28,6 @@ public abstract class ChunkStatusMixin implements ChunkSystemChunkStatus { @Unique private int writeRadius; - @Unique - private int loadRadius; - @Unique private ChunkStatus nextStatus; @@ -57,16 +54,6 @@ public abstract class ChunkStatusMixin implements ChunkSystemChunkStatus { this.writeRadius = value; } - @Override - public final int moonrise$getLoadRadius() { - return this.loadRadius; - } - - @Override - public final void moonrise$setLoadRadius(final int value) { - this.loadRadius = value; - } - @Override public final ChunkStatus moonrise$getNextStatus() { return this.nextStatus; @@ -102,12 +89,9 @@ public abstract class ChunkStatusMixin implements ChunkSystemChunkStatus { value = "RETURN" ) ) - private void initFields(ChunkStatus prevStatus, int i, boolean bl, EnumSet enumSet, ChunkType chunkType, - ChunkStatus.GenerationTask generationTask, ChunkStatus.LoadingTask loadingTask, - CallbackInfo ci) { + private void initFields(ChunkStatus prevStatus, EnumSet enumSet, ChunkType chunkType, CallbackInfo ci) { this.isParallelCapable = false; this.writeRadius = -1; - this.loadRadius = 0; this.nextStatus = (ChunkStatus)(Object)this; if (prevStatus != null) { ((ChunkStatusMixin)(Object)prevStatus).nextStatus = (ChunkStatus)(Object)this; diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStepMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStepMixin.java new file mode 100644 index 00000000..1bc35d84 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStepMixin.java @@ -0,0 +1,56 @@ +package ca.spottedleaf.moonrise.mixin.chunk_system; + +import ca.spottedleaf.moonrise.patches.chunk_system.status.ChunkSystemChunkStep; +import net.minecraft.world.level.chunk.status.ChunkDependencies; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStatusTask; +import net.minecraft.world.level.chunk.status.ChunkStep; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ChunkStep.class) +public abstract class ChunkStepMixin implements ChunkSystemChunkStep { + + @Shadow + public abstract int getAccumulatedRadiusOf(ChunkStatus chunkStatus); + + @Unique + private ChunkStatus[] byRadius; + + /** + * @reason Moonrise schedules chunks by requesting neighbours be brought up to a status, rather than scheduling + * neighbours incrementally. As a result, we need a mapping of neighbour radius -> max chunk status, which + * we build here. + * @author Spottedleaf + */ + @Inject( + method = "", + at = @At( + value = "RETURN" + ) + ) + private void init(ChunkStatus chunkStatus, ChunkDependencies chunkDependencies, ChunkDependencies chunkDependencies2, + int i, ChunkStatusTask chunkStatusTask, CallbackInfo ci) { + this.byRadius = new ChunkStatus[this.getAccumulatedRadiusOf(ChunkStatus.EMPTY) + 1]; + this.byRadius[0] = chunkStatus.getParent(); + + for (ChunkStatus status = chunkStatus.getParent(); status != ChunkStatus.EMPTY; status = status.getParent()) { + final int radius = this.getAccumulatedRadiusOf(status); + + for (int j = 0; j <= radius; ++j) { + if (this.byRadius[j] == null) { + this.byRadius[j] = status; + } + } + } + } + + @Override + public final ChunkStatus moonrise$getRequiredStatusAtRadius(final int radius) { + return this.byRadius[radius]; + } +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStorageMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStorageMixin.java index b9737f76..2273ecbd 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStorageMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkStorageMixin.java @@ -8,6 +8,7 @@ import net.minecraft.world.level.chunk.storage.ChunkStorage; import net.minecraft.world.level.chunk.storage.IOWorker; import net.minecraft.world.level.chunk.storage.RegionFileStorage; +import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Mixin; @@ -188,4 +189,13 @@ public ChunkScanAccess chunkScanner() { } }; } + + /** + * @reason Redirect to access the storage directly + * @author Spottedleaf + */ + @Overwrite + public RegionStorageInfo storageInfo() { + return this.storage.info(); + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/GenerationChunkHolderMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/GenerationChunkHolderMixin.java new file mode 100644 index 00000000..da13b469 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/GenerationChunkHolderMixin.java @@ -0,0 +1,187 @@ +package ca.spottedleaf.moonrise.mixin.chunk_system; + +import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder; +import com.mojang.datafixers.util.Pair; +import net.minecraft.server.level.ChunkGenerationTask; +import net.minecraft.server.level.ChunkLevel; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkResult; +import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.GeneratingChunkMap; +import net.minecraft.server.level.GenerationChunkHolder; +import net.minecraft.util.StaticCache2D; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ImposterProtoChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStep; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@Mixin(GenerationChunkHolder.class) +public abstract class GenerationChunkHolderMixin { + + @Shadow + public abstract int getTicketLevel(); + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public CompletableFuture> scheduleChunkGenerationTask(final ChunkStatus chunkStatus, + final ChunkMap chunkMap) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public CompletableFuture> applyStep(final ChunkStep chunkStep, final GeneratingChunkMap generatingChunkMap, + final StaticCache2D staticCache2D) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public void updateHighestAllowedStatus(final ChunkMap chunkMap) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public void replaceProtoChunk(final ImposterProtoChunk imposterProtoChunk) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public void removeTask(ChunkGenerationTask chunkGenerationTask) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public CompletableFuture> getOrCreateFuture(final ChunkStatus chunkStatus) { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public void increaseGenerationRefCount() { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public void decreaseGenerationRefCount() { + throw new UnsupportedOperationException(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public int getGenerationRefCount() { + throw new UnsupportedOperationException(); + } + + /** + * @reason Route to new chunk holder + * @author Spottedleaf + */ + @Overwrite + public ChunkAccess getChunkIfPresentUnchecked(final ChunkStatus chunkStatus) { + final NewChunkHolder.ChunkCompletion lastCompletion = ((ChunkSystemChunkHolder)(Object)this).moonrise$getRealChunkHolder().getLastChunkCompletion(); + return lastCompletion == null || !lastCompletion.genStatus().isOrAfter(chunkStatus) ? null : lastCompletion.chunk(); + } + + /** + * @reason Route to new chunk holder + * @author Spottedleaf + */ + @Overwrite + public ChunkAccess getChunkIfPresent(final ChunkStatus chunkStatus) { + final ChunkStatus maxStatus = ChunkLevel.generationStatus(this.getTicketLevel()); + + if (chunkStatus.isOrAfter(maxStatus)) { + return null; + } + + final NewChunkHolder.ChunkCompletion lastCompletion = ((ChunkSystemChunkHolder)(Object)this).moonrise$getRealChunkHolder().getLastChunkCompletion(); + return lastCompletion == null || !lastCompletion.genStatus().isOrAfter(chunkStatus) ? null : lastCompletion.chunk(); + } + + /** + * @reason Route to new chunk holder + * @author Spottedleaf + */ + @Overwrite + public ChunkAccess getLatestChunk() { + final NewChunkHolder.ChunkCompletion lastCompletion = ((ChunkSystemChunkHolder)(Object)this).moonrise$getRealChunkHolder().getLastChunkCompletion(); + return lastCompletion == null ? null : lastCompletion.chunk(); + } + + /** + * @reason Route to new chunk holder + * @author Spottedleaf + */ + @Overwrite + public ChunkStatus getPersistedStatus() { + final ChunkAccess chunk = this.getLatestChunk(); + return chunk == null ? null : chunk.getPersistedStatus(); + } + + /** + * @reason Route to new chunk holder + * @author Spottedleaf + */ + @Overwrite + public FullChunkStatus getFullStatus() { + return ((ChunkSystemChunkHolder)(Object)this).moonrise$getRealChunkHolder().getChunkStatus(); + } + + /** + * @reason Chunk system is not built on futures anymore + * @author Spottedleaf + */ + @Overwrite + public List>>> getAllFutures() { + throw new UnsupportedOperationException(); + } + + /** + * @reason Route to new chunk holder + * @author Spottedleaf + */ + @Overwrite + public ChunkStatus getLatestStatus() { + final NewChunkHolder.ChunkCompletion lastCompletion = ((ChunkSystemChunkHolder)(Object)this).moonrise$getRealChunkHolder().getLastChunkCompletion(); + return lastCompletion == null ? null : lastCompletion.genStatus(); + } +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/NoiseBasedChunkGeneratorMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/NoiseBasedChunkGeneratorMixin.java index 5297c1d5..a2b4fcb7 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/NoiseBasedChunkGeneratorMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/NoiseBasedChunkGeneratorMixin.java @@ -20,7 +20,7 @@ public abstract class NoiseBasedChunkGeneratorMixin { /** - * @reason Use the provided executor, chunk system sets this to something specific + * @reason Use Runnable:run, as we schedule onto the moonrise common pool * @author Spottedleaf */ @Redirect( @@ -30,13 +30,12 @@ public abstract class NoiseBasedChunkGeneratorMixin { target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;" ) ) - private CompletableFuture redirectBiomesExecutor(final Supplier supplier, final Executor badExecutor, - @Local(ordinal = 0, argsOnly = true) final Executor executor) { - return CompletableFuture.supplyAsync(supplier, executor); + private CompletableFuture redirectBiomesExecutor(final Supplier supplier, final Executor badExecutor) { + return CompletableFuture.supplyAsync(supplier, Runnable::run); } /** - * @reason Use the provided executor, chunk system sets this to something specific + * @reason Use Runnable:run, as we schedule onto the moonrise common pool * @author Spottedleaf */ @Redirect( @@ -46,8 +45,7 @@ private CompletableFuture redirectBiomesExecutor(final Supplier suppli target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;" ) ) - private CompletableFuture redirectNoiseExecutor(final Supplier supplier, final Executor badExecutor, - @Local(ordinal = 0, argsOnly = true) final Executor executor) { - return CompletableFuture.supplyAsync(supplier, executor); + private CompletableFuture redirectNoiseExecutor(final Supplier supplier, final Executor badExecutor) { + return CompletableFuture.supplyAsync(supplier, Runnable::run); } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/PoiManagerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/PoiManagerMixin.java index 8e9a465d..3f0c719a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/PoiManagerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/PoiManagerMixin.java @@ -22,6 +22,7 @@ import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.storage.ChunkIOErrorReporter; import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import net.minecraft.world.level.chunk.storage.SectionStorage; import net.minecraft.world.level.chunk.storage.SimpleRegionStorage; @@ -44,14 +45,15 @@ @Mixin(PoiManager.class) public abstract class PoiManagerMixin extends SectionStorage implements ChunkSystemPoiManager { + @Shadow abstract boolean isVillageCenter(long l); @Shadow public abstract void checkConsistencyWithBlocks(SectionPos sectionPos, LevelChunkSection levelChunkSection); - public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function> function, Function function2, RegistryAccess registryAccess, LevelHeightAccessor levelHeightAccessor) { - super(simpleRegionStorage, function, function2, registryAccess, levelHeightAccessor); + public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function> function, Function function2, RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor) { + super(simpleRegionStorage, function, function2, registryAccess, chunkIOErrorReporter, levelHeightAccessor); } @Unique @@ -89,7 +91,8 @@ private void updateDistanceTracking(long section) { value = "RETURN" ) ) - private void initHook(RegionStorageInfo regionStorageInfo, Path path, DataFixer dataFixer, boolean bl, RegistryAccess registryAccess, + private void initHook(RegionStorageInfo regionStorageInfo, Path path, DataFixer dataFixer, boolean bl, + RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor, CallbackInfo ci) { this.world = (ServerLevel)levelHeightAccessor; this.villageDistanceTracker = new Delayed26WayDistancePropagator3D(); diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java index f20517ba..9015a77a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java @@ -13,9 +13,9 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.enchantment.ProtectionEnchantment; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ExplosionDamageCalculator; @@ -478,7 +478,7 @@ public void explode() { final double knockbackFraction; if (entity instanceof LivingEntity livingEntity) { - knockbackFraction = ProtectionEnchantment.getExplosionKnockbackAfterDampener(livingEntity, intensityFraction); + knockbackFraction = intensityFraction * (1.0 - livingEntity.getAttributeValue(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE)); } else { knockbackFraction = intensityFraction; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/CommandsMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/command/CommandsMixin.java similarity index 85% rename from src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/CommandsMixin.java rename to src/main/java/ca/spottedleaf/moonrise/mixin/command/CommandsMixin.java index 0c4d9494..d1c17088 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/CommandsMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/command/CommandsMixin.java @@ -1,8 +1,7 @@ -package ca.spottedleaf.moonrise.mixin.chunk_system; +package ca.spottedleaf.moonrise.mixin.command; -import ca.spottedleaf.moonrise.patches.chunk_system.command.MoonriseCommand; +import ca.spottedleaf.moonrise.patches.command.MoonriseCommand; import com.mojang.brigadier.CommandDispatcher; -import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import org.spongepowered.asm.mixin.Final; diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PoiManagerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PoiManagerMixin.java index 03469cf5..d7d27604 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PoiManagerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PoiManagerMixin.java @@ -12,6 +12,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiSection; import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.chunk.storage.ChunkIOErrorReporter; import net.minecraft.world.level.chunk.storage.SectionStorage; import net.minecraft.world.level.chunk.storage.SimpleRegionStorage; import org.spongepowered.asm.mixin.Mixin; @@ -27,8 +28,8 @@ @Mixin(PoiManager.class) public abstract class PoiManagerMixin extends SectionStorage { - public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function> function, Function function2, RegistryAccess registryAccess, LevelHeightAccessor levelHeightAccessor) { - super(simpleRegionStorage, function, function2, registryAccess, levelHeightAccessor); + public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function> function, Function function2, RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor) { + super(simpleRegionStorage, function, function2, registryAccess, chunkIOErrorReporter, levelHeightAccessor); } /** diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PortalForcerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PortalForcerMixin.java index bd2dc33d..bcc1e8a8 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PortalForcerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/poi_lookup/PortalForcerMixin.java @@ -37,7 +37,7 @@ public abstract class PortalForcerMixin { * @author Spottedleaf */ @Overwrite - public Optional findPortalAround(BlockPos blockPos, boolean bl, WorldBorder worldBorder) { + public Optional findClosestPortalPosition(BlockPos blockPos, boolean bl, WorldBorder worldBorder) { PoiManager poiManager = this.level.getPoiManager(); int i = bl ? 16 : 128; List records = new ArrayList<>(); @@ -46,7 +46,7 @@ public Optional findPortalAround(BlockPos blockPos, bo (BlockPos pos) -> { ChunkAccess lowest = this.level.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.EMPTY); BelowZeroRetrogen belowZeroRetrogen; - if (!lowest.getStatus().isOrAfter(ChunkStatus.FULL) + if (!lowest.getPersistedStatus().isOrAfter(ChunkStatus.FULL) // check below zero retrogen so that pre 1.17 worlds still load portals (JMP) && ((belowZeroRetrogen = lowest.getBelowZeroRetrogen()) == null || !belowZeroRetrogen.targetStatus().isOrAfter(ChunkStatus.SPAWN))) { // why would we generate the chunk? diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java index c73ec096..bbdef641 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java @@ -51,7 +51,7 @@ private void queueTaskForSection(final int chunkX, final int chunkY, final int c final ServerLevel world = (ServerLevel)this.starlight$getLightEngine().getWorld(); final ChunkAccess center = this.starlight$getLightEngine().getAnyChunkNow(chunkX, chunkZ); - if (center == null || !center.getStatus().isOrAfter(ChunkStatus.LIGHT)) { + if (center == null || !center.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT)) { // do not accept updates in unlit chunks, unless we might be generating a chunk. thanks to the amazing // chunk scheduling, we could be lighting and generating a chunk at the same time return; diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/ChunkSerializerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/ChunkSerializerMixin.java index 18efcad6..74894015 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/ChunkSerializerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/ChunkSerializerMixin.java @@ -8,6 +8,7 @@ import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.storage.ChunkSerializer; +import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -36,7 +37,8 @@ private static void saveLightHook(final ServerLevel world, final ChunkAccess chu method = "read", at = @At("RETURN") ) - private static void loadLightHook(final ServerLevel serverLevel, final PoiManager poiManager, final ChunkPos chunkPos, + private static void loadLightHook(final ServerLevel serverLevel, final PoiManager poiManager, + final RegionStorageInfo regionStorageInfo, final ChunkPos chunkPos, final CompoundTag compoundTag, final CallbackInfoReturnable cir) { SaveUtil.loadLightHook(serverLevel, chunkPos, compoundTag, cir.getReturnValue()); } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemChunkStatus.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemChunkStatus.java index fb6a6c74..f4bc44bb 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemChunkStatus.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemChunkStatus.java @@ -13,10 +13,6 @@ public interface ChunkSystemChunkStatus { public void moonrise$setWriteRadius(final int value); - public int moonrise$getLoadRadius(); - - public void moonrise$setLoadRadius(final int value); - public ChunkStatus moonrise$getNextStatus(); public boolean moonrise$isEmptyLoadStatus(); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java index 8a4d35b0..4bc1a6f7 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java @@ -539,19 +539,19 @@ private boolean canPlayerGenerateChunks() { private double getMaxChunkLoadRate() { final double configRate = MoonriseCommon.getConfig().chunkLoading.basic.playerMaxLoadRate; - return configRate < 0.0 || configRate > (double)MAX_RATE ? (double)MAX_RATE : Math.max(1.0, configRate); + return configRate <= 0.0 || configRate > (double)MAX_RATE ? (double)MAX_RATE : Math.max(1.0, configRate); } private double getMaxChunkGenRate() { final double configRate = MoonriseCommon.getConfig().chunkLoading.basic.playerMaxGenRate; - return configRate < 0.0 || configRate > (double)MAX_RATE ? (double)MAX_RATE : Math.max(1.0, configRate); + return configRate <= 0.0 || configRate > (double)MAX_RATE ? (double)MAX_RATE : Math.max(1.0, configRate); } private double getMaxChunkSendRate() { final double configRate = MoonriseCommon.getConfig().chunkLoading.basic.playerMaxSendRate; - return configRate < 0.0 || configRate > (double)MAX_RATE ? (double)MAX_RATE : Math.max(1.0, configRate); + return configRate <= 0.0 || configRate > (double)MAX_RATE ? (double)MAX_RATE : Math.max(1.0, configRate); } private long getMaxChunkLoads() { @@ -739,7 +739,7 @@ void updateQueues(final long time) { final int chunkX = CoordinateUtils.getChunkX(chunkKey); final int chunkZ = CoordinateUtils.getChunkZ(chunkKey); final ChunkAccess chunk = ((ChunkSystemLevel)this.world).moonrise$getAnyChunkIfLoaded(chunkX, chunkZ); - if (chunk.getStatus() != ChunkStatus.FULL) { + if (chunk.getPersistedStatus() != ChunkStatus.FULL) { // only rate limit actual generations if ((ratedGensThisTick + 1L) > maxGensThisTick) { break; @@ -878,7 +878,7 @@ private boolean isLoadedChunkGeneratable(final ChunkAccess chunkAccess) { final BelowZeroRetrogen belowZeroRetrogen; // see PortalForcer#findPortalAround return chunkAccess != null && ( - chunkAccess.getStatus() == ChunkStatus.FULL || + chunkAccess.getPersistedStatus() == ChunkStatus.FULL || ((belowZeroRetrogen = chunkAccess.getBelowZeroRetrogen()) != null && belowZeroRetrogen.targetStatus().isOrAfter(ChunkStatus.SPAWN)) ); } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java index 3d0658ab..ffd08511 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java @@ -60,9 +60,9 @@ public final class ChunkHolderManager { private static final Logger LOGGER = LoggerFactory.getLogger(ChunkHolderManager.class); - public static final int FULL_LOADED_TICKET_LEVEL = 33; - public static final int BLOCK_TICKING_TICKET_LEVEL = 32; - public static final int ENTITY_TICKING_TICKET_LEVEL = 31; + public static final int FULL_LOADED_TICKET_LEVEL = ChunkLevel.FULL_CHUNK_LEVEL; + public static final int BLOCK_TICKING_TICKET_LEVEL = ChunkLevel.BLOCK_TICKING_LEVEL; + public static final int ENTITY_TICKING_TICKET_LEVEL = ChunkLevel.ENTITY_TICKING_LEVEL; public static final int MAX_TICKET_LEVEL = ChunkLevel.MAX_LEVEL; // inclusive public static final TicketType UNLOAD_COOLDOWN = TicketType.create("unload_cooldown", (u1, u2) -> 0, 5 * 20); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java index be3485c2..dbc40fa3 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java @@ -19,18 +19,24 @@ import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkProgressionTask; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkUpgradeGenericStatusTask; import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer; +import ca.spottedleaf.moonrise.patches.chunk_system.status.ChunkSystemChunkStep; import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration; import net.minecraft.CrashReport; import net.minecraft.CrashReportCategory; import net.minecraft.ReportedException; +import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.TicketType; +import net.minecraft.util.StaticCache2D; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkPyramid; import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStep; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayDeque; @@ -61,7 +67,7 @@ public static void init() { } initialised = true; newChunkSystemIOThreads = MoonriseCommon.getConfig().chunkSystem.ioThreads; - if (newChunkSystemIOThreads < 0) { + if (newChunkSystemIOThreads <= 0) { newChunkSystemIOThreads = 1; } else { newChunkSystemIOThreads = Math.max(1, newChunkSystemIOThreads); @@ -75,7 +81,7 @@ public static void init() { RegionFileIOThread.init(newChunkSystemIOThreads); - LOGGER.info("Chunk system is using " + newChunkSystemIOThreads + " I/O threads, " + MoonriseCommon.WORKER_THREADS + " worker threads, and gen parallelism of " + ChunkTaskScheduler.newChunkSystemGenParallelism + " threads"); + LOGGER.info("Chunk system is using " + newChunkSystemIOThreads + " I/O threads, " + MoonriseCommon.WORKER_THREADS + " worker threads, and population gen parallelism of " + ChunkTaskScheduler.newChunkSystemGenPopulationParallelism + " threads"); } public static final TicketType CHUNK_LOAD = TicketType.create("chunk_system:chunk_load", Long::compareTo); @@ -108,7 +114,7 @@ public static Long getNextPoiLoadId() { public static int getTicketLevel(final ChunkStatus status) { - return ChunkHolderManager.FULL_LOADED_TICKET_LEVEL + ChunkStatus.getDistance(status); + return ChunkLevel.byStatus(status); } public final ServerLevel world; @@ -199,18 +205,27 @@ public static int getTicketLevel(final ChunkStatus status) { } } + private static final int[] ACCESS_RADIUS_TABLE_LOAD = new int[ChunkStatus.getStatusList().size()]; + private static final int[] ACCESS_RADIUS_TABLE_GEN = new int[ChunkStatus.getStatusList().size()]; private static final int[] ACCESS_RADIUS_TABLE = new int[ChunkStatus.getStatusList().size()]; + static { + Arrays.fill(ACCESS_RADIUS_TABLE_LOAD, -1); + Arrays.fill(ACCESS_RADIUS_TABLE_GEN, -1); + Arrays.fill(ACCESS_RADIUS_TABLE, -1); + } - private static int getAccessRadius0(final ChunkStatus genStatus) { - if (genStatus == ChunkStatus.EMPTY) { + private static int getAccessRadius0(final ChunkStatus toStatus, final ChunkPyramid pyramid) { + if (toStatus == ChunkStatus.EMPTY) { return 0; } - final int radius = genStatus.getRange(); + final ChunkStep chunkStep = pyramid.getStepTo(toStatus); + + final int radius = chunkStep.getAccumulatedRadiusOf(ChunkStatus.EMPTY); int maxRange = radius; for (int dist = 0; dist <= radius; ++dist) { - final ChunkStatus requiredNeighbourStatus = dist == 0 ? genStatus.getParent() : ChunkStatus.getStatusAroundFullChunk(ChunkStatus.getDistance(genStatus) + dist); + final ChunkStatus requiredNeighbourStatus = ((ChunkSystemChunkStep)(Object)chunkStep).moonrise$getRequiredStatusAtRadius(dist); final int rad = ACCESS_RADIUS_TABLE[requiredNeighbourStatus.getIndex()]; if (rad == -1) { throw new IllegalStateException(); @@ -227,7 +242,13 @@ private static int getAccessRadius0(final ChunkStatus genStatus) { static { final List statuses = ChunkStatus.getStatusList(); for (int i = 0, len = statuses.size(); i < len; ++i) { - ACCESS_RADIUS_TABLE[i] = getAccessRadius0(statuses.get(i)); + final ChunkStatus status = statuses.get(i); + ACCESS_RADIUS_TABLE_LOAD[i] = getAccessRadius0(status, ChunkPyramid.LOADING_PYRAMID); + ACCESS_RADIUS_TABLE_GEN[i] = getAccessRadius0(status, ChunkPyramid.GENERATION_PYRAMID); + ACCESS_RADIUS_TABLE[i] = Math.max( + ACCESS_RADIUS_TABLE_LOAD[i], + ACCESS_RADIUS_TABLE_GEN[i] + ); } MAX_ACCESS_RADIUS = ACCESS_RADIUS_TABLE[ACCESS_RADIUS_TABLE.length - 1]; } @@ -267,7 +288,7 @@ public ChunkTaskScheduler(final ServerLevel world, final PrioritisedThreadPool w this.parallelGenExecutor = workers.createExecutor("Chunk parallel generation executor for world '" + worldName + "'", 1, Math.max(1, newChunkSystemGenParallelism)); this.radiusAwareGenExecutor = workers.createExecutor("Chunk radius aware generator for world '" + worldName + "'", 1, Math.max(1, newChunkSystemGenPopulationParallelism)); this.loadExecutor = workers.createExecutor("Chunk load executor for world '" + worldName + "'", 1, newChunkSystemLoadParallelism); - this.radiusAwareScheduler = new RadiusAwarePrioritisedExecutor(this.radiusAwareGenExecutor, Math.max(1, newChunkSystemGenPopulationParallelism)); + this.radiusAwareScheduler = new RadiusAwarePrioritisedExecutor(this.radiusAwareGenExecutor, Math.max(2, 1 + newChunkSystemGenPopulationParallelism)); this.chunkHolderManager = new ChunkHolderManager(world, this); } @@ -431,7 +452,7 @@ public void scheduleChunkLoad(final int chunkX, final int chunkZ, final boolean if (chunk == null) { onComplete.accept(null); } else { - if (chunk.getStatus().isOrAfter(toStatus)) { + if (chunk.getPersistedStatus().isOrAfter(toStatus)) { this.scheduleChunkLoad(chunkX, chunkZ, toStatus, addTicket, priority, onComplete); } else { onComplete.accept(null); @@ -608,7 +629,7 @@ public void scheduleChunkLoad(final int chunkX, final int chunkZ, final ChunkSta } private ChunkProgressionTask createTask(final int chunkX, final int chunkZ, final ChunkAccess chunk, - final NewChunkHolder chunkHolder, final List neighbours, + final NewChunkHolder chunkHolder, final StaticCache2D neighbours, final ChunkStatus toStatus, final PrioritisedExecutor.Priority initialPriority) { if (toStatus == ChunkStatus.EMPTY) { return new ChunkLoadTask(this, this.world, chunkX, chunkZ, chunkHolder, initialPriority); @@ -653,7 +674,7 @@ private ChunkProgressionTask schedule(final int chunkX, final int chunkZ, final if (currentGenStatus == null) { // not yet loaded final ChunkProgressionTask task = this.createTask( - chunkX, chunkZ, chunk, chunkHolder, Collections.emptyList(), ChunkStatus.EMPTY, requestedPriority + chunkX, chunkZ, chunk, chunkHolder, null, ChunkStatus.EMPTY, requestedPriority ); allTasks.add(task); @@ -675,12 +696,15 @@ private ChunkProgressionTask schedule(final int chunkX, final int chunkZ, final // we know for sure now that we want to schedule _something_, so set the target chunkHolder.setGenerationTarget(targetStatus); - final ChunkStatus chunkRealStatus = chunk.getStatus(); + final ChunkStatus chunkRealStatus = chunk.getPersistedStatus(); final ChunkStatus toStatus = ((ChunkSystemChunkStatus)currentGenStatus).moonrise$getNextStatus(); + final ChunkPyramid chunkPyramid = chunkRealStatus.isOrAfter(toStatus) ? ChunkPyramid.LOADING_PYRAMID : ChunkPyramid.GENERATION_PYRAMID; + final ChunkStep chunkStep = chunkPyramid.getStepTo(toStatus); - // if this chunk has already generated up to or past the specified status, then we don't - // need the neighbours AT ALL. - final int neighbourReadRadius = chunkRealStatus.isOrAfter(toStatus) ? ((ChunkSystemChunkStatus)toStatus).moonrise$getLoadRadius() : toStatus.getRange(); + final int neighbourReadRadius = Math.max( + 0, + chunkPyramid.getStepTo(toStatus).getAccumulatedRadiusOf(ChunkStatus.EMPTY) + ); boolean unGeneratedNeighbours = false; @@ -690,7 +714,7 @@ private ChunkProgressionTask schedule(final int chunkX, final int chunkZ, final final int x = CoordinateUtils.getChunkX(pos); final int z = CoordinateUtils.getChunkZ(pos); final int radius = Math.max(Math.abs(x), Math.abs(z)); - final ChunkStatus requiredNeighbourStatus = chunkMap.getDependencyStatus(toStatus, radius); + final ChunkStatus requiredNeighbourStatus = ((ChunkSystemChunkStep)(Object)chunkStep).moonrise$getRequiredStatusAtRadius(radius); unGeneratedNeighbours |= this.checkNeighbour( chunkX + x, chunkZ + z, requiredNeighbourStatus, chunkHolder, allTasks, requestedPriority @@ -708,26 +732,14 @@ private ChunkProgressionTask schedule(final int chunkX, final int chunkZ, final // need to gather neighbours - final List neighbours; - final List chunkHolderNeighbours; - if (neighbourReadRadius <= 0) { - neighbours = new ArrayList<>(1); - chunkHolderNeighbours = new ArrayList<>(1); - neighbours.add(chunk); - chunkHolderNeighbours.add(chunkHolder); - } else { - // the iteration order is _very_ important, as all generation statuses expect a certain order such that: - // chunkAtRelative = neighbours.get(relX + relZ * (2 * radius + 1)) - neighbours = new ArrayList<>((2 * neighbourReadRadius + 1) * (2 * neighbourReadRadius + 1)); - chunkHolderNeighbours = new ArrayList<>((2 * neighbourReadRadius + 1) * (2 * neighbourReadRadius + 1)); - for (int dz = -neighbourReadRadius; dz <= neighbourReadRadius; ++dz) { - for (int dx = -neighbourReadRadius; dx <= neighbourReadRadius; ++dx) { - final NewChunkHolder holder = (dx | dz) == 0 ? chunkHolder : this.chunkHolderManager.getChunkHolder(dx + chunkX, dz + chunkZ); - neighbours.add(holder.getChunkForNeighbourAccess()); + final List chunkHolderNeighbours = new ArrayList<>((2 * neighbourReadRadius + 1) * (2 * neighbourReadRadius + 1)); + final StaticCache2D neighbours = StaticCache2D + .create(chunkX, chunkZ, neighbourReadRadius, (final int nx, final int nz) -> { + final NewChunkHolder holder = nx == chunkX && nz == chunkZ ? chunkHolder : this.chunkHolderManager.getChunkHolder(nx, nz); chunkHolderNeighbours.add(holder); - } - } - } + + return holder.vanillaChunkHolder; + }); final ChunkProgressionTask task = this.createTask( chunkX, chunkZ, chunk, chunkHolder, neighbours, toStatus, diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java index d36b3ec7..1081cc11 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java @@ -14,6 +14,7 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.chunk.status.ChunkStatusTasks; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.invoke.VarHandle; @@ -41,7 +42,7 @@ public ChunkStatus getTargetStatus() { @Override public void run() { - // See Vanilla protoChunkToFullChunk for what this function should be doing + // See Vanilla ChunkPyramid#LOADING_PYRAMID.FULL for what this function should be doing final LevelChunk chunk; try { // moved from the load from nbt stage into here @@ -59,7 +60,7 @@ public void run() { final ServerLevel world = this.world; final ProtoChunk protoChunk = (ProtoChunk)this.fromChunk; chunk = new LevelChunk(this.world, protoChunk, (final LevelChunk unused) -> { - ChunkMap.postLoadProtoChunk(world, protoChunk.getEntities()); + ChunkStatusTasks.postLoadProtoChunk(world, protoChunk.getEntities()); }); } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLightTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLightTask.java index ec17c0b7..7c2e6752 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLightTask.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLightTask.java @@ -151,7 +151,7 @@ public boolean getAsBoolean() { try { final Boolean[] emptySections = StarLightEngine.getEmptySectionsForChunk(task.fromChunk); - if (task.fromChunk.isLightCorrect() && task.fromChunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { + if (task.fromChunk.isLightCorrect() && task.fromChunk.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT)) { this.lightEngine.forceLoadInChunk(task.fromChunk, emptySections); this.lightEngine.checkChunkEdges(task.chunkX, task.chunkZ); } else { @@ -160,8 +160,8 @@ public boolean getAsBoolean() { task.fromChunk.setLightCorrect(true); } // we need to advance status - if (task.fromChunk instanceof ProtoChunk chunk && chunk.getStatus() == ChunkStatus.LIGHT.getParent()) { - chunk.setStatus(ChunkStatus.LIGHT); + if (task.fromChunk instanceof ProtoChunk chunk && chunk.getPersistedStatus() == ChunkStatus.LIGHT.getParent()) { + chunk.setPersistedStatus(ChunkStatus.LIGHT); } } catch (final Throwable thr) { LOGGER.fatal( diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLoadTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLoadTask.java index 098a6998..1636ffb7 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLoadTask.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkLoadTask.java @@ -346,7 +346,7 @@ protected TaskResult runOffMain(final CompoundTag data, private TaskResult deserialize(final CompoundTag data) { try { final ChunkAccess deserialized = ChunkSerializer.read( - this.world, this.world.getPoiManager(), new ChunkPos(this.chunkX, this.chunkZ), data + this.world, this.world.getPoiManager(), this.world.getChunkSource().chunkMap.storageInfo(), new ChunkPos(this.chunkX, this.chunkZ), data ); return new TaskResult<>(deserialized, null); } catch (final Throwable thr2) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkUpgradeGenericStatusTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkUpgradeGenericStatusTask.java index 454f6162..2c17d558 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkUpgradeGenericStatusTask.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkUpgradeGenericStatusTask.java @@ -7,10 +7,13 @@ import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.StaticCache2D; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; +import net.minecraft.world.level.chunk.status.ChunkPyramid; import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.WorldGenContext; import org.slf4j.Logger; @@ -27,19 +30,19 @@ public final class ChunkUpgradeGenericStatusTask extends ChunkProgressionTask im private final ChunkAccess fromChunk; private final ChunkStatus fromStatus; private final ChunkStatus toStatus; - private final List neighbours; + private final StaticCache2D neighbours; private final PrioritisedExecutor.PrioritisedTask generateTask; public ChunkUpgradeGenericStatusTask(final ChunkTaskScheduler scheduler, final ServerLevel world, final int chunkX, - final int chunkZ, final ChunkAccess chunk, final List neighbours, + final int chunkZ, final ChunkAccess chunk, final StaticCache2D neighbours, final ChunkStatus toStatus, final PrioritisedExecutor.Priority priority) { super(scheduler, world, chunkX, chunkZ); if (!PrioritisedExecutor.Priority.isValidPriority(priority)) { throw new IllegalArgumentException("Invalid priority " + priority); } this.fromChunk = chunk; - this.fromStatus = chunk.getStatus(); + this.fromStatus = chunk.getPersistedStatus(); this.toStatus = toStatus; this.neighbours = neighbours; if (((ChunkSystemChunkStatus)this.toStatus).moonrise$isParallelCapable()) { @@ -80,27 +83,22 @@ public void run() { // note: should optimise the case where the chunk does not need to execute the status, because // schedule() calls this synchronously if it will run through that path - final WorldGenContext ctx = new WorldGenContext( - this.world, - chunkMap.generator, - chunkMap.worldGenContext.structureManager(), - serverChunkCache.getLightEngine() - ); + final WorldGenContext ctx = chunkMap.worldGenContext; try { - generation = !chunk.getStatus().isOrAfter(this.toStatus); + generation = !chunk.getPersistedStatus().isOrAfter(this.toStatus); if (generation) { if (((ChunkSystemChunkStatus)this.toStatus).moonrise$isEmptyGenStatus()) { if (chunk instanceof ProtoChunk) { - ((ProtoChunk)chunk).setStatus(this.toStatus); + ((ProtoChunk)chunk).setPersistedStatus(this.toStatus); } completing = true; this.complete(chunk, null); return; } - completeFuture = this.toStatus.generate(ctx, Runnable::run, null, this.neighbours) + completeFuture = ChunkPyramid.GENERATION_PYRAMID.getStepTo(this.toStatus).apply(ctx, this.neighbours, this.fromChunk) .whenComplete((final ChunkAccess either, final Throwable throwable) -> { if (either instanceof ProtoChunk proto) { - proto.setStatus(ChunkUpgradeGenericStatusTask.this.toStatus); + proto.setPersistedStatus(ChunkUpgradeGenericStatusTask.this.toStatus); } } ); @@ -110,7 +108,7 @@ public void run() { this.complete(chunk, null); return; } - completeFuture = this.toStatus.load(ctx, null, chunk); + completeFuture = ChunkPyramid.LOADING_PYRAMID.getStepTo(this.toStatus).apply(ctx, this.neighbours, this.fromChunk); } } catch (final Throwable throwable) { if (!completing) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/status/ChunkSystemChunkStep.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/status/ChunkSystemChunkStep.java new file mode 100644 index 00000000..ea759ce6 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/status/ChunkSystemChunkStep.java @@ -0,0 +1,9 @@ +package ca.spottedleaf.moonrise.patches.chunk_system.status; + +import net.minecraft.world.level.chunk.status.ChunkStatus; + +public interface ChunkSystemChunkStep { + + public ChunkStatus moonrise$getRequiredStatusAtRadius(final int radius); + +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/command/MoonriseCommand.java b/src/main/java/ca/spottedleaf/moonrise/patches/command/MoonriseCommand.java similarity index 79% rename from src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/command/MoonriseCommand.java rename to src/main/java/ca/spottedleaf/moonrise/patches/command/MoonriseCommand.java index 1c84b3ba..7ea5c0c2 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/command/MoonriseCommand.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/command/MoonriseCommand.java @@ -1,23 +1,21 @@ -package ca.spottedleaf.moonrise.patches.chunk_system.command; +package ca.spottedleaf.moonrise.patches.command; -import ca.spottedleaf.moonrise.patches.chunk_system.ChunkSystem; +import ca.spottedleaf.moonrise.common.util.MoonriseCommon; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder; import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.commands.arguments.DimensionArgument; -import net.minecraft.network.chat.ComponentContents; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.contents.PlainTextContents; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.FullChunkStatus; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ImposterProtoChunk; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.ProtoChunk; +import java.io.File; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; public final class MoonriseCommand { @@ -35,6 +33,11 @@ public static void register(final CommandDispatcher dispatch .executes((final CommandContext ctx) -> { return MoonriseCommand.chunkInfo(ctx); }) + ).then( + Commands.literal("reload") + .executes((final CommandContext ctx) -> { + return MoonriseCommand.reload(ctx); + }) ) ); } @@ -126,4 +129,26 @@ public static int chunkInfo(final CommandContext ctx) { return total; } + + public static int reload(final CommandContext ctx) { + if (MoonriseCommon.reloadConfig()) { + ctx.getSource().sendSuccess(() -> { + return MutableComponent.create( + new PlainTextContents.LiteralContents( + "Reloaded Moonrise config." + ) + ); + }, true); + } else { + ctx.getSource().sendFailure( + MutableComponent.create( + new PlainTextContents.LiteralContents( + "Failed to reload Moonrise config." + ) + ) + ); + } + + return 0; + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/BlockStarLightEngine.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/BlockStarLightEngine.java index 34324f70..154443ac 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/BlockStarLightEngine.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/BlockStarLightEngine.java @@ -44,7 +44,7 @@ protected void setNibbles(final ChunkAccess chunk, final SWMRNibbleArray[] to) { @Override protected boolean canUseChunk(final ChunkAccess chunk) { - return chunk.getStatus().isOrAfter(ChunkStatus.LIGHT) && (this.isClientSide || chunk.isLightCorrect()); + return chunk.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT) && (this.isClientSide || chunk.isLightCorrect()); } @Override diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/SkyStarLightEngine.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/SkyStarLightEngine.java index 2d73de03..fdbc015f 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/SkyStarLightEngine.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/SkyStarLightEngine.java @@ -229,7 +229,7 @@ protected void setNibbles(final ChunkAccess chunk, final SWMRNibbleArray[] to) { @Override protected boolean canUseChunk(final ChunkAccess chunk) { // can only use chunks for sky stuff if their sections have been init'd - return chunk.getStatus().isOrAfter(ChunkStatus.LIGHT) && (this.isClientSide || chunk.isLightCorrect()); + return chunk.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT) && (this.isClientSide || chunk.isLightCorrect()); } @Override diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java index 2ce53abd..c64ab411 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java @@ -125,7 +125,7 @@ public void setLightEnabled(final ChunkPos chunkPos, final boolean bl) { @Override public DataLayer getDataLayerData(final SectionPos pos) { final ChunkAccess chunk = StarLightInterface.this.getAnyChunkNow(pos.getX(), pos.getZ()); - if (chunk == null || (!StarLightInterface.this.isClientSide && !chunk.isLightCorrect()) || !chunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { + if (chunk == null || (!StarLightInterface.this.isClientSide && !chunk.isLightCorrect()) || !chunk.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT)) { return null; } @@ -237,7 +237,7 @@ public int getSkyLightValue(final BlockPos blockPos, final ChunkAccess chunk) { final int minLightSection = this.minLightSection; final int maxLightSection = this.maxLightSection; - if (chunk == null || (!this.isClientSide && !chunk.isLightCorrect()) || !chunk.getStatus().isOrAfter(ChunkStatus.LIGHT)) { + if (chunk == null || (!this.isClientSide && !chunk.isLightCorrect()) || !chunk.getPersistedStatus().isOrAfter(ChunkStatus.LIGHT)) { return 15; } diff --git a/src/main/resources/moonrise.accesswidener b/src/main/resources/moonrise.accesswidener index dd43b3c4..2a1f9429 100644 --- a/src/main/resources/moonrise.accesswidener +++ b/src/main/resources/moonrise.accesswidener @@ -28,31 +28,30 @@ accessible class net/minecraft/world/level/chunk/PaletteResize # ChunkMap accessible field net/minecraft/server/level/ChunkMap level Lnet/minecraft/server/level/ServerLevel; accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop; -accessible method net/minecraft/server/level/ChunkMap postLoadProtoChunk (Lnet/minecraft/server/level/ServerLevel;Ljava/util/List;)V accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder; accessible method net/minecraft/server/level/ChunkMap getVisibleChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder; accessible method net/minecraft/server/level/ChunkMap getChunkQueueLevel (J)Ljava/util/function/IntSupplier; -accessible method net/minecraft/server/level/ChunkMap releaseLightTicket (Lnet/minecraft/world/level/ChunkPos;)V accessible method net/minecraft/server/level/ChunkMap generator ()Lnet/minecraft/world/level/chunk/ChunkGenerator; -accessible method net/minecraft/server/level/ChunkMap getDependencyStatus (Lnet/minecraft/world/level/chunk/status/ChunkStatus;I)Lnet/minecraft/world/level/chunk/status/ChunkStatus; mutable field net/minecraft/server/level/ChunkMap updatingChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap; mutable field net/minecraft/server/level/ChunkMap queueSorter Lnet/minecraft/server/level/ChunkTaskPriorityQueueSorter; mutable field net/minecraft/server/level/ChunkMap worldgenMailbox Lnet/minecraft/util/thread/ProcessorHandle; mutable field net/minecraft/server/level/ChunkMap mainThreadMailbox Lnet/minecraft/util/thread/ProcessorHandle; accessible method net/minecraft/server/level/ChunkMap setServerViewDistance (I)V accessible method net/minecraft/server/level/ChunkMap upgradeChunkTag (Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag; -accessible field net/minecraft/server/level/ChunkMap generator Lnet/minecraft/world/level/chunk/ChunkGenerator; accessible field net/minecraft/server/level/ChunkMap worldGenContext Lnet/minecraft/world/level/chunk/status/WorldGenContext; accessible field net/minecraft/server/level/ChunkMap tickingGenerated Ljava/util/concurrent/atomic/AtomicInteger; +# ChunkLevel +accessible field net/minecraft/server/level/ChunkLevel FULL_CHUNK_LEVEL I +accessible field net/minecraft/server/level/ChunkLevel BLOCK_TICKING_LEVEL I +accessible field net/minecraft/server/level/ChunkLevel ENTITY_TICKING_LEVEL I -# ChunkHolder -accessible field net/minecraft/server/level/ChunkHolder chunkToSave Ljava/util/concurrent/CompletableFuture; # LevelLightEngine mutable field net/minecraft/world/level/lighting/LevelLightEngine blockEngine Lnet/minecraft/world/level/lighting/LightEngine; mutable field net/minecraft/world/level/lighting/LevelLightEngine skyEngine Lnet/minecraft/world/level/lighting/LightEngine; + # ThreadedLevelLightEngine accessible class net/minecraft/server/level/ThreadedLevelLightEngine$TaskType mutable field net/minecraft/server/level/ThreadedLevelLightEngine sorterMailbox Lnet/minecraft/util/thread/ProcessorHandle; @@ -160,13 +159,9 @@ accessible method net/minecraft/world/entity/ai/village/poi/PoiManager setDirty accessible method net/minecraft/server/network/PlayerChunkSender sendChunk (Lnet/minecraft/server/network/ServerGamePacketListenerImpl;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/LevelChunk;)V -# ChunkStatus -accessible class net/minecraft/world/level/chunk/status/ChunkStatus$GenerationTask -accessible class net/minecraft/world/level/chunk/status/ChunkStatus$LoadingTask - - # ChunkStatusTasks -accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks loadPassThrough (Lnet/minecraft/world/level/chunk/status/WorldGenContext;Lnet/minecraft/world/level/chunk/status/ChunkStatus;Lnet/minecraft/world/level/chunk/status/ToFullChunk;Lnet/minecraft/world/level/chunk/ChunkAccess;)Ljava/util/concurrent/CompletableFuture; +accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks postLoadProtoChunk (Lnet/minecraft/server/level/ServerLevel;Ljava/util/List;)V +accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks light (Lnet/minecraft/world/level/chunk/status/WorldGenContext;Lnet/minecraft/world/level/chunk/status/ChunkStep;Lnet/minecraft/util/StaticCache2D;Lnet/minecraft/world/level/chunk/ChunkAccess;)Ljava/util/concurrent/CompletableFuture; # RegionFileStorage @@ -240,6 +235,7 @@ accessible method net/minecraft/server/level/Ticket (Lnet/minecraft/serve # ChunkStorage mutable field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker; +accessible method net/minecraft/world/level/chunk/storage/ChunkStorage storageInfo ()Lnet/minecraft/world/level/chunk/storage/RegionStorageInfo; # StructureCheck diff --git a/src/main/resources/moonrise.mixins.json b/src/main/resources/moonrise.mixins.json index e1a8aae6..c546e2fd 100644 --- a/src/main/resources/moonrise.mixins.json +++ b/src/main/resources/moonrise.mixins.json @@ -18,14 +18,16 @@ "chunk_system.ChunkHolderMixin", "chunk_system.ChunkMap$DistanceManagerMixin", "chunk_system.ChunkMapMixin", + "chunk_system.ChunkPyramidMixin", "chunk_system.ChunkSerializerMixin", "chunk_system.ChunkStatusMixin", + "chunk_system.ChunkStepMixin", "chunk_system.ChunkStorageMixin", - "chunk_system.CommandsMixin", "chunk_system.DistanceManagerMixin", "chunk_system.EntityGetterMixin", "chunk_system.EntityMixin", "chunk_system.EntityTickListMixin", + "chunk_system.GenerationChunkHolderMixin", "chunk_system.LevelChunkMixin", "chunk_system.LevelChunkTicksMixin", "chunk_system.LevelMixin", @@ -65,6 +67,7 @@ "collisions.ShapesMixin", "collisions.SliceShapeMixin", "collisions.VoxelShapeMixin", + "command.CommandsMixin", "farm_block.FarmBlockMixin", "fast_palette.CrudeIncrementalIntIdentityHashBiMapMixin", "fast_palette.HashMapPaletteMixin", @@ -109,5 +112,5 @@ }, "overwrites": { "conformVisibility": true - } + } }