Update to 1.21

This commit is contained in:
Spottedleaf
2024-06-14 09:50:54 -07:00
parent fff73cff5b
commit 188ddaae7b
38 changed files with 570 additions and 300 deletions

View File

@@ -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

View File

@@ -36,21 +36,24 @@ public final class MoonriseConfig {
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 final class MoonriseConfig {
@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 final class MoonriseConfig {
@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.
"""

View File

@@ -214,6 +214,9 @@ public final class TypeAdapterRegistry {
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;
}

View File

@@ -7,7 +7,7 @@ import java.lang.annotation.Target;
/**
* 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)

View File

@@ -9,7 +9,7 @@ import java.util.function.Function;
/**
* 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)

View File

@@ -67,6 +67,10 @@ public final class YamlConfig<T> {
}
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 final class YamlConfig<T> {
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 final class YamlConfig<T> {
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) {

View File

@@ -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<MoonriseConfig> 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=<file> - Override the config file location. Maybe useful for multiple game versions.
-DMoonrise.WorkerThreadCount=<number> - Override the auto configured worker thread counts (worker-threads).
""";
static {
reloadConfig();
@@ -31,25 +42,27 @@ public final class MoonriseCommon {
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 final class MoonriseCommon {
int workerThreads = MoonriseCommon.getConfig().workerThreads;
if (workerThreads < 0) {
if (workerThreads <= 0) {
workerThreads = defaultWorkerThreads;
} else {
workerThreads = Math.max(1, workerThreads);
}
WORKER_POOL = new PrioritisedThreadPool(

View File

@@ -22,7 +22,7 @@ import java.util.function.Supplier;
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 <U> CompletableFuture<U> redirectBiomesExecutor(final Supplier<U> supplier, final Executor badExecutor,
@Local(ordinal = 0, argsOnly = true) final Executor executor) {
return CompletableFuture.supplyAsync(supplier, executor);
private <U> CompletableFuture<U> redirectBiomesExecutor(final Supplier<U> supplier, final Executor badExecutor) {
return CompletableFuture.supplyAsync(supplier, Runnable::run);
}
/**

View File

@@ -12,6 +12,7 @@ import net.minecraft.server.level.ChunkHolder;
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.CompletableFuture;
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<ChunkResult<ChunkAccess>> UNLOADED_CHUNK_FUTURE;
public ChunkHolderMixin(ChunkPos chunkPos) {
super(chunkPos);
}
@Unique
private NewChunkHolder newChunkHolder;
@@ -126,26 +122,6 @@ public abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
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<ChunkResult<ChunkAccess>> 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<ChunkResult<ChunkAccess>> 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 abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
* @author Spottedleaf
*/
@Overwrite
public CompletableFuture<?> getChunkSendSyncFuture() {
public CompletableFuture<?> getSendSyncFuture() {
throw new UnsupportedOperationException();
}
@@ -248,33 +224,13 @@ public abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
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<ChunkAccess> getChunkToSave() {
public CompletableFuture<ChunkAccess> getSaveSyncFuture() {
throw new UnsupportedOperationException();
}
@@ -296,27 +252,6 @@ public abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
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<ChunkResult<ChunkAccess>> 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 @@ public abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
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<ChunkResult<ChunkAccess>> 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<? extends ChunkResult<? extends ChunkAccess>> 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 abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
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 abstract class ChunkHolderMixin implements ChunkSystemChunkHolder {
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<Pair<ChunkStatus, CompletableFuture<ChunkResult<ChunkAccess>>>> getAllFutures() {
throw new UnsupportedOperationException();
}
}

View File

@@ -11,19 +11,24 @@ import com.mojang.datafixers.DataFixer;
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.IntFunction;
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
@@ -239,15 +244,6 @@ public abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.
throw new UnsupportedOperationException();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public CompletableFuture<ChunkResult<ChunkAccess>> schedule(final ChunkHolder holder, final ChunkStatus requiredStatus) {
throw new UnsupportedOperationException();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
@@ -261,9 +257,9 @@ public abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Override
@Overwrite
public CompletableFuture<ChunkResult<ChunkAccess>> scheduleChunkGeneration(final ChunkHolder holder,
final ChunkStatus requiredStatus) {
public GenerationChunkHolder acquireGeneration(final long pos) {
throw new UnsupportedOperationException();
}
@@ -271,9 +267,40 @@ public abstract class ChunkMapMixin extends ChunkStorage implements ChunkHolder.
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Override
@Overwrite
public CompletableFuture<ChunkResult<ChunkAccess>> protoChunkToFullChunk(final ChunkHolder chunkHolder,
final ChunkAccess chunkAccess) {
public void releaseGeneration(final GenerationChunkHolder holder) {
throw new UnsupportedOperationException();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Override
@Overwrite
public CompletableFuture<ChunkAccess> applyStep(final GenerationChunkHolder generationChunkHolder, final ChunkStep chunkStep,
final StaticCache2D<GenerationChunkHolder> 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 void runGenerationTasks() {
throw new UnsupportedOperationException();
}

View File

@@ -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 = "<clinit>",
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<ChunkStep.Builder> 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);
})
);
}
}

View File

@@ -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<Heightmap.Types> enumSet, ChunkType chunkType,
ChunkStatus.GenerationTask generationTask, ChunkStatus.LoadingTask loadingTask,
CallbackInfo ci) {
private void initFields(ChunkStatus prevStatus, EnumSet<Heightmap.Types> 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;

View File

@@ -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 = "<init>",
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];
}
}

View File

@@ -8,6 +8,7 @@ import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
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 abstract class ChunkStorageMixin implements ChunkSystemChunkStorage, Auto
}
};
}
/**
* @reason Redirect to access the storage directly
* @author Spottedleaf
*/
@Overwrite
public RegionStorageInfo storageInfo() {
return this.storage.info();
}
}

View File

@@ -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<ChunkResult<ChunkAccess>> scheduleChunkGenerationTask(final ChunkStatus chunkStatus,
final ChunkMap chunkMap) {
throw new UnsupportedOperationException();
}
/**
* @reason Chunk system is not built on futures anymore
* @author Spottedleaf
*/
@Overwrite
public CompletableFuture<ChunkResult<ChunkAccess>> applyStep(final ChunkStep chunkStep, final GeneratingChunkMap generatingChunkMap,
final StaticCache2D<GenerationChunkHolder> 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<ChunkResult<ChunkAccess>> 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<Pair<ChunkStatus, CompletableFuture<ChunkResult<ChunkAccess>>>> 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();
}
}

View File

@@ -20,7 +20,7 @@ import java.util.function.Supplier;
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 <U> CompletableFuture<U> redirectBiomesExecutor(final Supplier<U> supplier, final Executor badExecutor,
@Local(ordinal = 0, argsOnly = true) final Executor executor) {
return CompletableFuture.supplyAsync(supplier, executor);
private <U> CompletableFuture<U> redirectBiomesExecutor(final Supplier<U> 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 @@ public abstract class NoiseBasedChunkGeneratorMixin {
target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"
)
)
private <U> CompletableFuture<U> redirectNoiseExecutor(final Supplier<U> supplier, final Executor badExecutor,
@Local(ordinal = 0, argsOnly = true) final Executor executor) {
return CompletableFuture.supplyAsync(supplier, executor);
private <U> CompletableFuture<U> redirectNoiseExecutor(final Supplier<U> supplier, final Executor badExecutor) {
return CompletableFuture.supplyAsync(supplier, Runnable::run);
}
}

View File

@@ -22,6 +22,7 @@ import net.minecraft.world.level.ChunkPos;
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 @@ import java.util.stream.Stream;
@Mixin(PoiManager.class)
public abstract class PoiManagerMixin extends SectionStorage<PoiSection> implements ChunkSystemPoiManager {
@Shadow
abstract boolean isVillageCenter(long l);
@Shadow
public abstract void checkConsistencyWithBlocks(SectionPos sectionPos, LevelChunkSection levelChunkSection);
public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function<Runnable, Codec<PoiSection>> function, Function<Runnable, PoiSection> function2, RegistryAccess registryAccess, LevelHeightAccessor levelHeightAccessor) {
super(simpleRegionStorage, function, function2, registryAccess, levelHeightAccessor);
public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function<Runnable, Codec<PoiSection>> function, Function<Runnable, PoiSection> function2, RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor) {
super(simpleRegionStorage, function, function2, registryAccess, chunkIOErrorReporter, levelHeightAccessor);
}
@Unique
@@ -89,7 +91,8 @@ public abstract class PoiManagerMixin extends SectionStorage<PoiSection> impleme
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();

View File

@@ -13,9 +13,9 @@ import net.minecraft.util.Mth;
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 abstract class ExplosionMixin {
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;
}

View File

@@ -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;

View File

@@ -12,6 +12,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiRecord;
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 @@ import java.util.stream.Stream;
@Mixin(PoiManager.class)
public abstract class PoiManagerMixin extends SectionStorage<PoiSection> {
public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function<Runnable, Codec<PoiSection>> function, Function<Runnable, PoiSection> function2, RegistryAccess registryAccess, LevelHeightAccessor levelHeightAccessor) {
super(simpleRegionStorage, function, function2, registryAccess, levelHeightAccessor);
public PoiManagerMixin(SimpleRegionStorage simpleRegionStorage, Function<Runnable, Codec<PoiSection>> function, Function<Runnable, PoiSection> function2, RegistryAccess registryAccess, ChunkIOErrorReporter chunkIOErrorReporter, LevelHeightAccessor levelHeightAccessor) {
super(simpleRegionStorage, function, function2, registryAccess, chunkIOErrorReporter, levelHeightAccessor);
}
/**

View File

@@ -37,7 +37,7 @@ public abstract class PortalForcerMixin {
* @author Spottedleaf
*/
@Overwrite
public Optional<BlockUtil.FoundRectangle> findPortalAround(BlockPos blockPos, boolean bl, WorldBorder worldBorder) {
public Optional<BlockUtil.FoundRectangle> findClosestPortalPosition(BlockPos blockPos, boolean bl, WorldBorder worldBorder) {
PoiManager poiManager = this.level.getPoiManager();
int i = bl ? 16 : 128;
List<PoiRecord> records = new ArrayList<>();
@@ -46,7 +46,7 @@ public abstract class PortalForcerMixin {
(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?

View File

@@ -51,7 +51,7 @@ public abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine imp
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;

View File

@@ -8,6 +8,7 @@ import net.minecraft.world.level.ChunkPos;
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 @@ public abstract class ChunkSerializerMixin {
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<ProtoChunk> cir) {
SaveUtil.loadLightHook(serverLevel, chunkPos, compoundTag, cir.getReturnValue());
}

View File

@@ -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();

View File

@@ -539,19 +539,19 @@ public final class RegionizedPlayerChunkLoader {
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 @@ public final class RegionizedPlayerChunkLoader {
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 @@ public final class RegionizedPlayerChunkLoader {
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))
);
}

View File

@@ -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<Unit> UNLOAD_COOLDOWN = TicketType.create("unload_cooldown", (u1, u2) -> 0, 5 * 20);

View File

@@ -19,18 +19,24 @@ import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkLoadTas
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 final class ChunkTaskScheduler {
}
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 final class ChunkTaskScheduler {
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<Long> CHUNK_LOAD = TicketType.create("chunk_system:chunk_load", Long::compareTo);
@@ -108,7 +114,7 @@ public final class ChunkTaskScheduler {
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 final class ChunkTaskScheduler {
}
}
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 @@ public final class ChunkTaskScheduler {
static {
final List<ChunkStatus> 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 final class ChunkTaskScheduler {
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 final class ChunkTaskScheduler {
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 final class ChunkTaskScheduler {
}
private ChunkProgressionTask createTask(final int chunkX, final int chunkZ, final ChunkAccess chunk,
final NewChunkHolder chunkHolder, final List<ChunkAccess> neighbours,
final NewChunkHolder chunkHolder, final StaticCache2D<GenerationChunkHolder> 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 @@ public final class ChunkTaskScheduler {
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 @@ public final class ChunkTaskScheduler {
// 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 @@ public final class ChunkTaskScheduler {
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 @@ public final class ChunkTaskScheduler {
// need to gather neighbours
final List<ChunkAccess> neighbours;
final List<NewChunkHolder> 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<NewChunkHolder> chunkHolderNeighbours = new ArrayList<>((2 * neighbourReadRadius + 1) * (2 * neighbourReadRadius + 1));
final StaticCache2D<GenerationChunkHolder> 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,

View File

@@ -14,6 +14,7 @@ import net.minecraft.world.level.chunk.ImposterProtoChunk;
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 final class ChunkFullTask extends ChunkProgressionTask implements Runnabl
@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 final class ChunkFullTask extends ChunkProgressionTask implements Runnabl
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());
});
}

View File

@@ -151,7 +151,7 @@ public final class ChunkLightTask extends ChunkProgressionTask {
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 final class ChunkLightTask extends ChunkProgressionTask {
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(

View File

@@ -346,7 +346,7 @@ public final class ChunkLoadTask extends ChunkProgressionTask {
private TaskResult<ChunkAccess, Throwable> 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) {

View File

@@ -7,10 +7,13 @@ import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunk
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<ChunkAccess> neighbours;
private final StaticCache2D<GenerationChunkHolder> 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<ChunkAccess> neighbours,
final int chunkZ, final ChunkAccess chunk, final StaticCache2D<GenerationChunkHolder> 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 final class ChunkUpgradeGenericStatusTask extends ChunkProgressionTask im
// 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 final class ChunkUpgradeGenericStatusTask extends ChunkProgressionTask im
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) {

View File

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

View File

@@ -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 final class MoonriseCommand {
.executes((final CommandContext<CommandSourceStack> ctx) -> {
return MoonriseCommand.chunkInfo(ctx);
})
).then(
Commands.literal("reload")
.executes((final CommandContext<CommandSourceStack> ctx) -> {
return MoonriseCommand.reload(ctx);
})
)
);
}
@@ -126,4 +129,26 @@ public final class MoonriseCommand {
return total;
}
public static int reload(final CommandContext<CommandSourceStack> 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;
}
}

View File

@@ -44,7 +44,7 @@ public final class BlockStarLightEngine extends StarLightEngine {
@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

View File

@@ -229,7 +229,7 @@ public final class SkyStarLightEngine extends StarLightEngine {
@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

View File

@@ -125,7 +125,7 @@ public final class StarLightInterface {
@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 final class StarLightInterface {
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;
}

View File

@@ -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 <init> (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

View File

@@ -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
}
}
}