Update to 1.21
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user