Update to 1.21.5

This commit is contained in:
Spottedleaf
2025-04-01 15:35:12 -07:00
parent 13948cdf26
commit 27759719e9
64 changed files with 1159 additions and 634 deletions

View File

@@ -3,9 +3,11 @@ package ca.spottedleaf.moonrise.fabric;
import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.Dynamic;
import it.unimi.dsi.fastutil.longs.LongArrays;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.core.BlockPos;
@@ -15,6 +17,7 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.level.BlockGetter;
@@ -255,4 +258,9 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH
public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
return currentRange;
}
@Override
public long[] getCounterTypesUncached(final TicketType type) {
return type == TicketType.FORCED ? new long[] { ChunkSystemTicketType.COUNTER_TYPE_FORCED } : LongArrays.EMPTY_ARRAY;
}
}

View File

@@ -1,33 +0,0 @@
package ca.spottedleaf.moonrise.fabric.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(DistanceManager.class)
abstract class FabricDistanceManagerMixin implements ChunkSystemDistanceManager {
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void addRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier) {
this.moonrise$getChunkHolderManager().addTicketAtLevel(type, pos, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, identifier);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void removeRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier) {
this.moonrise$getChunkHolderManager().removeTicketAtLevel(type, pos, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, identifier);
}
}

View File

@@ -36,7 +36,7 @@
"accessWidener": "moonrise.accesswidener",
"depends": {
"fabricloader": ">=${loader_version}",
"minecraft": ">1.21.3 <1.21.5",
"minecraft": ">1.21.4 <1.21.6",
"fabric-command-api-v2": "*"
},
"custom": {

View File

@@ -2,7 +2,6 @@
"parent": "moonrise.mixins.json",
"package": "ca.spottedleaf.moonrise.fabric.mixin",
"mixins": [
"chunk_system.FabricDistanceManagerMixin",
"chunk_system.FabricMinecraftServerMixin",
"chunk_system.FabricServerLevelMixin",
"collisions.EntityMixin"

View File

@@ -5,22 +5,22 @@ org.gradle.caching=true
org.gradle.configuration-cache=true
# Fabric Properties
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.21.4
loader_version=0.16.9
supported_minecraft_versions=1.21.4
neoforge_version=21.4.33-beta
neoform_version=1.21.4-20241203.161809
fabric_api_version=0.110.5+1.21.4
minecraft_version=1.21.5
loader_version=0.16.11
supported_minecraft_versions=1.21.5
neoforge_version=21.5.18-beta
neoform_version=1.21.5-20250325.162830
fabric_api_version=0.119.6+1.21.5
snakeyaml_version=2.3
concurrentutil_version=0.0.3
yamlconfig_version=1.0.2
cloth_version=17.0.144
modmenu_version=13.0.0-beta.1
cloth_version=18.0.145
modmenu_version=14.0.0-rc.2
junit_version=5.11.3
# version ids from modrinth
fabric_lithium_version=t1FlWYl9
neo_lithium_version=iDqQi66g
fabric_lithium_version=nhc57Td2
neo_lithium_version=P5VT33Jo
# Mod Properties
mod_version=0.2.0-SNAPSHOT
mod_version=0.3.0-SNAPSHOT
maven_group=ca.spottedleaf.moonrise
archives_base_name=moonrise

View File

@@ -4,9 +4,11 @@ import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.Dynamic;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
@@ -14,6 +16,7 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.ChunkPos;
@@ -261,4 +264,18 @@ public final class NeoForgeHooks extends BaseChunkSystemHooks implements Platfor
public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
return currentRange;
}
@Override
public long[] getCounterTypesUncached(final TicketType type) {
final LongArrayList ret = new LongArrayList();
if (type == TicketType.FORCED) {
ret.add(ChunkSystemTicketType.COUNTER_TYPE_FORCED);
}
if (type.forceNaturalSpawning()) {
ret.add(ChunkSystemTicketType.COUNTER_TYPER_NATURAL_SPAWNING_FORCED);
}
return ret.toLongArray();
}
}

View File

@@ -1,87 +0,0 @@
package ca.spottedleaf.moonrise.neoforge.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.SortedArraySet;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(DistanceManager.class)
abstract class NeoForgeDistanceManagerMixin implements ChunkSystemDistanceManager {
@Shadow
@Final
private Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets;
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void addRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier, final boolean forceTicks) {
final int level = ChunkLevel.byStatus(FullChunkStatus.FULL) - radius;
this.moonrise$getChunkHolderManager().addTicketAtLevel(type, pos, level, identifier);
if (forceTicks) {
final Ticket<T> forceTicket = new Ticket<>(type, level, identifier, forceTicks);
this.forcedTickets.compute(pos.toLong(), (final Long keyInMap, final SortedArraySet<Ticket<?>> valueInMap) -> {
final SortedArraySet<Ticket<?>> ret;
if (valueInMap != null) {
ret = valueInMap;
} else {
ret = SortedArraySet.create(4);
}
if (ret.add(forceTicket)) {
((ChunkTickServerLevel)NeoForgeDistanceManagerMixin.this.moonrise$getChunkMap().level).moonrise$addPlayerTickingRequest(
CoordinateUtils.getChunkX(keyInMap.longValue()), CoordinateUtils.getChunkZ(keyInMap.longValue())
);
}
return ret;
});
}
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void removeRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier, final boolean forceTicks) {
final int level = ChunkLevel.byStatus(FullChunkStatus.FULL) - radius;
this.moonrise$getChunkHolderManager().removeTicketAtLevel(type, pos, level, identifier);
if (forceTicks) {
final Ticket<T> forceTicket = new Ticket<>(type, level, identifier, forceTicks);
this.forcedTickets.computeIfPresent(pos.toLong(), (final Long keyInMap, final SortedArraySet<Ticket<?>> valueInMap) -> {
if (valueInMap.remove(forceTicket)) {
((ChunkTickServerLevel)NeoForgeDistanceManagerMixin.this.moonrise$getChunkMap().level).moonrise$removePlayerTickingRequest(
CoordinateUtils.getChunkX(keyInMap.longValue()), CoordinateUtils.getChunkZ(keyInMap.longValue())
);
}
return valueInMap.isEmpty() ? null : valueInMap;
});
}
}
/**
* @reason Only use containsKey, as we fix the leak with this impl
* @author Spottedleaf
*/
@Overwrite
public boolean shouldForceTicks(final long chunkPos) {
return this.forcedTickets.containsKey(chunkPos);
}
}

View File

@@ -0,0 +1,69 @@
package ca.spottedleaf.moonrise.neoforge.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketStorage;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(TicketStorage.class)
abstract class NeoForgeTicketStorageMixin implements ChunkSystemTicketStorage {
@Shadow
private LongSet chunksWithForceNaturalSpawning;
/**
* @reason Destroy old chunk system state
* @author Spottedleaf
*/
@Inject(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "RETURN"
)
)
private void destroyFields(Long2ObjectOpenHashMap p_393873_, Long2ObjectOpenHashMap p_394615_, CallbackInfo ci) {
this.chunksWithForceNaturalSpawning = null;
}
/**
* @reason The forced natural spawning chunks would be empty, as tickets should always be empty.
* We need to do this to avoid throwing immediately.
* @author Spottedleaf
*/
@Redirect(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;updateForcedNaturalSpawning()V"
)
)
private void avoidUpdatingForcedNaturalChunks(final TicketStorage instance) {}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean shouldForceNaturalSpawning(final ChunkPos pos) {
final Long2IntOpenHashMap counters = ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getChunkTaskScheduler()
.chunkHolderManager.getTicketCounters(ChunkSystemTicketType.COUNTER_TYPER_NATURAL_SPAWNING_FORCED);
if (counters == null) {
return false;
}
return counters.containsKey(CoordinateUtils.getChunkKey(pos));
}
}

View File

@@ -28,7 +28,7 @@ side = "BOTH"
[[dependencies.moonrise]]
modId = "minecraft"
type = "required"
versionRange = "(1.21.3,1.21.5)"
versionRange = "(1.21.4,1.21.6)"
ordering = "NONE"
side = "BOTH"

View File

@@ -2,9 +2,9 @@
"parent": "moonrise.mixins.json",
"package": "ca.spottedleaf.moonrise.neoforge.mixin",
"mixins": [
"chunk_system.NeoForgeDistanceManagerMixin",
"chunk_system.NeoForgeMinecraftServerMixin",
"chunk_system.NeoForgeServerLevelMixin",
"chunk_system.NeoForgeTicketStorageMixin",
"collisions.EntityMixin"
],
"client": [

View File

@@ -24,8 +24,8 @@ pluginManagement {
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
id("quiet-fabric-loom") version "1.9.312" apply false
id("net.neoforged.moddev") version "2.0.61-beta" apply false
id 'com.gradleup.shadow' version '8.3.5' apply false
id("net.neoforged.moddev") version "2.0.80" apply false
id 'com.gradleup.shadow' version '8.3.6' apply false
}
dependencyResolutionManagement {

View File

@@ -2,6 +2,7 @@ package ca.spottedleaf.moonrise.common.list;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.NoSuchElementException;
@@ -21,15 +22,34 @@ public final class IteratorSafeOrderedReferenceSet<E> {
private int iteratorCount;
public IteratorSafeOrderedReferenceSet() {
this(16, 0.75f, 16, 0.2);
this(Object.class);
}
public IteratorSafeOrderedReferenceSet(final Class<? super E> arrComponent) {
this(16, 0.75f, 16, 0.2, arrComponent);
}
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
final double maxFragFactor) {
this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, Object.class);
}
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
final double maxFragFactor, final Class<? super E> arrComponent) {
this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor);
this.indexMap.defaultReturnValue(-1);
this.maxFragFactor = maxFragFactor;
this.listElements = (E[])new Object[arrayCapacity];
this.listElements = (E[])Array.newInstance(arrComponent, arrayCapacity);
}
// includes null (gravestone) elements
public E[] getListRaw() {
return this.listElements;
}
// includes null (gravestone) elements
public int getListSize() {
return this.listSize;
}
/*
@@ -81,7 +101,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
public int createRawIterator() {
++this.iteratorCount;
if (this.indexMap.isEmpty()) {
return -1;
return Integer.MAX_VALUE;
} else {
return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0;
}
@@ -96,7 +116,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
}
return -1;
return Integer.MAX_VALUE;
}
public void finishRawIterator() {
@@ -205,10 +225,6 @@ public final class IteratorSafeOrderedReferenceSet<E> {
//this.check();
}
public E rawGet(final int index) {
return this.listElements[index];
}
public int size() {
// always returns the correct amount - listSize can be different
return this.indexMap.size();

View File

@@ -1,6 +1,6 @@
package ca.spottedleaf.moonrise.common.misc;
import ca.spottedleaf.concurrentutil.util.IntPairUtil;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
@@ -23,12 +23,16 @@ public final class PositionCountingAreaMap<T> {
return this.positions.size();
}
public boolean hasObjectsNear(final long pos) {
return this.positions.containsKey(pos);
}
public boolean hasObjectsNear(final int toX, final int toZ) {
return this.positions.containsKey(IntPairUtil.key(toX, toZ));
return this.positions.containsKey(CoordinateUtils.getChunkKey(toX, toZ));
}
public int getObjectsNear(final int toX, final int toZ) {
return this.positions.get(IntPairUtil.key(toX, toZ));
return this.positions.get(CoordinateUtils.getChunkKey(toX, toZ));
}
public boolean add(final T parameter, final int toX, final int toZ, final int distance) {
@@ -85,12 +89,12 @@ public final class PositionCountingAreaMap<T> {
@Override
protected void addCallback(final T parameter, final int toX, final int toZ) {
PositionCountingAreaMap.this.positions.addTo(IntPairUtil.key(toX, toZ), 1);
PositionCountingAreaMap.this.positions.addTo(CoordinateUtils.getChunkKey(toX, toZ), 1);
}
@Override
protected void removeCallback(final T parameter, final int toX, final int toZ) {
final long key = IntPairUtil.key(toX, toZ);
final long key = CoordinateUtils.getChunkKey(toX, toZ);
if (PositionCountingAreaMap.this.positions.addTo(key, -1) == 1) {
PositionCountingAreaMap.this.positions.remove(key);
}

View File

@@ -1,7 +1,5 @@
package ca.spottedleaf.moonrise.common.misc;
import ca.spottedleaf.concurrentutil.util.IntegerUtil;
public abstract class SingleUserAreaMap<T> {
public static final int NOT_SET = Integer.MIN_VALUE;
@@ -99,8 +97,8 @@ public abstract class SingleUserAreaMap<T> {
final int dx = toX - fromX;
final int dz = toZ - fromZ;
final int totalX = IntegerUtil.branchlessAbs(fromX - toX);
final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ);
final int totalX = Math.abs(fromX - toX);
final int totalZ = Math.abs(fromZ - toZ);
if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) {
// teleported
@@ -120,7 +118,7 @@ public abstract class SingleUserAreaMap<T> {
for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) {
// only remove if we're outside the new view distance...
if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) {
if (Math.max(Math.abs(currX - toX), Math.abs(currZ - toZ)) > newViewDistance) {
this.removeCallback(parameter, currX, currZ);
}
}
@@ -136,7 +134,7 @@ public abstract class SingleUserAreaMap<T> {
for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) {
// only add if we're outside the old view distance...
if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) {
if (Math.max(Math.abs(currX - fromX), Math.abs(currZ - fromZ)) > oldViewDistance) {
this.addCallback(parameter, currX, currZ);
}
}

View File

@@ -21,7 +21,7 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override
public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
this.scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
}
@Override
@@ -71,7 +71,7 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override
public boolean hasAnyChunkHolders(final ServerLevel level) {
return getUpdatingChunkHolderCount(level) != 0;
return this.getUpdatingChunkHolderCount(level) != 0;
}
@Override
@@ -98,16 +98,12 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override
public void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().add(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().add(chunk);
}
@Override
public void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().remove(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().remove(chunk);
}
@Override
@@ -118,37 +114,29 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override
public void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().add(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().add(chunk);
if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) {
chunk.postProcessGeneration((ServerLevel)chunk.getLevel());
}
((ServerLevel)chunk.getLevel()).startTickingChunk(chunk);
((ServerLevel)chunk.getLevel()).getChunkSource().chunkMap.tickingGenerated.incrementAndGet();
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$markChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
}
@Override
public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().remove(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().remove(chunk);
}
@Override
public void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().add(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().add(chunk);
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$markChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
}
@Override
public void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().remove(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().remove(chunk);
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
}
@Override

View File

@@ -5,6 +5,7 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -74,4 +75,6 @@ public interface ChunkSystemHooks {
public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player);
public void updateMaps(final ServerLevel world, final ServerPlayer player);
public long[] getCounterTypesUncached(final TicketType type);
}

View File

@@ -87,7 +87,7 @@ abstract class LevelMixin implements LevelAccessor, AutoCloseable {
if (doTick && this.shouldTickBlocksAt(tileEntity.getPos())) {
tileEntity.tick();
// call mid tick tasks for chunk system
// call mid-tick tasks for chunk system
if ((++tickedEntities & 7) == 0) {
((ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks();
}

View File

@@ -125,7 +125,7 @@ abstract class StateHolderMixin<O, S> implements PropertyAccessStateHolder {
* @author Spottedleaf
*/
@Overwrite
public <T extends Comparable<T>> T getNullableValue(Property<T> property) {
public <T extends Comparable<T>> T getNullableValue(final Property<T> property) {
return property == null ? null : this.optimisedTable.get(this.tableIndex, property);
}
@@ -166,7 +166,7 @@ abstract class StateHolderMixin<O, S> implements PropertyAccessStateHolder {
*/
@Overwrite
public Map<Property<?>, Comparable<?>> getValues() {
ZeroCollidingReferenceStateTable<O, S> table = this.optimisedTable;
final ZeroCollidingReferenceStateTable<O, S> table = this.optimisedTable;
// We have to use this.values until the table is loaded
return table.isLoaded() ? table.getMapView(this.tableIndex) : this.values;
}

View File

@@ -366,7 +366,7 @@ abstract class ChunkHolderMixin extends GenerationChunkHolder implements ChunkSy
/**
* @reason Use ticket system to control ticket levels
* @author Spottedleaf
* @see net.minecraft.server.level.ServerChunkCache#addRegionTicket(TicketType, ChunkPos, int, Object)
* @see net.minecraft.server.level.ServerChunkCache#addTicketWithRadius(TicketType, ChunkPos, int)
*/
@Overwrite
public void setTicketLevel(int i) {

View File

@@ -2,6 +2,7 @@ package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.level.TicketStorage;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@@ -15,8 +16,8 @@ abstract class ChunkMap$DistanceManagerMixin extends net.minecraft.server.level.
@Final
ChunkMap field_17443;
protected ChunkMap$DistanceManagerMixin(Executor executor, Executor executor2) {
super(executor, executor2);
protected ChunkMap$DistanceManagerMixin(final TicketStorage p_394060_, final Executor p_140774_, final Executor p_140775_) {
super(p_394060_, p_140774_, p_140775_);
}
/**

View File

@@ -32,6 +32,7 @@ import net.minecraft.util.Mth;
import net.minecraft.util.StaticCache2D;
import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -43,7 +44,6 @@ import net.minecraft.world.level.chunk.storage.IOWorker;
import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
import net.minecraft.world.level.entity.ChunkStatusUpdateListener;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
@@ -124,11 +124,11 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
)
)
private void constructor(
ServerLevel arg, LevelStorageSource.LevelStorageAccess arg2, DataFixer dataFixer,
StructureTemplateManager arg3, Executor executor, BlockableEventLoop<Runnable> arg4,
LightChunkGetter arg5, ChunkGenerator arg6, ChunkProgressListener arg7,
ChunkStatusUpdateListener arg8, Supplier<DimensionDataStorage> supplier, int j, boolean bl,
final CallbackInfo ci) {
ServerLevel p_214836_, LevelStorageSource.LevelStorageAccess p_214837_, DataFixer p_214838_,
StructureTemplateManager p_214839_, Executor p_214840_, BlockableEventLoop p_214841_,
LightChunkGetter p_214842_, ChunkGenerator p_214843_, ChunkProgressListener p_214844_,
ChunkStatusUpdateListener p_214845_, Supplier p_214846_, TicketStorage p_394462_, int p_214847_,
boolean p_214848_, CallbackInfo ci) {
// intentionally destroy old chunk system hooks
this.updatingChunkMap = null;
this.visibleChunkMap = null;
@@ -143,7 +143,8 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
// Dummy impl for mods that try to loadAsync directly
this.worker = new IOWorker(
// copied from super call
new RegionStorageInfo(arg2.getLevelId(), arg.dimension(), "chunk"), arg2.getDimensionPath(arg.dimension()).resolve("region"), bl
new RegionStorageInfo(p_214837_.getLevelId(), p_214836_.dimension(), "chunk"),
p_214837_.getDimensionPath(p_214836_.dimension()).resolve("region"), p_214848_
) {
@Override
public boolean isOldChunkAround(final ChunkPos chunkPos, final int i) {
@@ -543,13 +544,31 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
* @author Spottedleaf
*/
@Redirect(
method = "forEachSpawnCandidateChunk",
method = "collectSpawningChunks",
at = @At(
value = "INVOKE",
target = "Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;get(J)Ljava/lang/Object;"
)
)
private <V> V redirectChunkHolderGet(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) {
private <V> V redirectChunkHolderGetForSpawning(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) {
return (V)this.getVisibleChunkIfPresent(key);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Redirect(
method = {
"method_67499",
"lambda$forEachBlockTickingChunk$36"
},
at = @At(
value = "INVOKE",
target = "Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;get(J)Ljava/lang/Object;"
)
)
private <V> V redirectChunkHolderGetForBlockTicking(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) {
return (V)this.getVisibleChunkIfPresent(key);
}

View File

@@ -1,22 +1,27 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketStorage;
import it.unimi.dsi.fastutil.longs.LongConsumer;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.LoadingChunkTracker;
import net.minecraft.server.level.SimulationChunkTracker;
import net.minecraft.server.level.ThrottlingChunkTaskDispatcher;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import net.minecraft.server.level.TickingTracker;
import net.minecraft.util.Mth;
import net.minecraft.util.SortedArraySet;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@@ -24,6 +29,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -31,13 +37,14 @@ import java.util.concurrent.Executor;
abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
@Shadow
Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets;
public LoadingChunkTracker loadingChunkTracker;
@Shadow
private DistanceManager.ChunkTicketTracker ticketTracker;
public SimulationChunkTracker simulationChunkTracker;
@Shadow
private TickingTracker tickingTicketsTracker;
@Final
private TicketStorage ticketStorage;
@Shadow
private DistanceManager.PlayerTicketTracker playerTicketManager;
@@ -64,7 +71,8 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
}
/**
* @reason Destroy old chunk system state to prevent it from being used
* @reason Destroy old chunk system state to prevent it from being used, and set the chunk map
* for the ticket storage
* @author Spottedleaf
*/
@Inject(
@@ -74,15 +82,16 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
)
)
private void destroyFields(final CallbackInfo ci) {
this.tickets = null;
this.ticketTracker = null;
this.tickingTicketsTracker = null;
this.loadingChunkTracker = null;
this.simulationChunkTracker = null;
this.playerTicketManager = null;
this.chunksToUpdateFutures = null;
this.ticketDispatcher = null;
this.ticketsToRelease = null;
this.mainThreadExecutor = null;
this.simulationDistance = -1;
((ChunkSystemTicketStorage)this.ticketStorage).moonrise$setChunkMap(this.moonrise$getChunkMap());
}
@Override
@@ -90,15 +99,6 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
return ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getChunkTaskScheduler().chunkHolderManager;
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void purgeStaleTickets() {
this.moonrise$getChunkHolderManager().tick();
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
@@ -108,46 +108,6 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
return this.moonrise$getChunkHolderManager().processTicketUpdates();
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void addTicket(final long pos, final Ticket<?> ticket) {
this.moonrise$getChunkHolderManager().addTicketAtLevel((TicketType)ticket.getType(), pos, ticket.getTicketLevel(), ticket.key);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void removeTicket(final long pos, final Ticket<?> ticket) {
this.moonrise$getChunkHolderManager().removeTicketAtLevel((TicketType)ticket.getType(), pos, ticket.getTicketLevel(), ticket.key);
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public SortedArraySet<Ticket<?>> getTickets(final long pos) {
throw new UnsupportedOperationException();
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void updateChunkForced(final ChunkPos pos, final boolean forced) {
if (forced) {
this.moonrise$getChunkHolderManager().addTicketAtLevel(TicketType.FORCED, pos, ChunkMap.FORCED_TICKET_LEVEL, pos);
} else {
this.moonrise$getChunkHolderManager().removeTicketAtLevel(TicketType.FORCED, pos, ChunkMap.FORCED_TICKET_LEVEL, pos);
}
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
@@ -170,11 +130,10 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
method = "addPlayer",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/TickingTracker;addTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"
target = "Lnet/minecraft/world/level/TicketStorage;addTicket(Lnet/minecraft/server/level/Ticket;Lnet/minecraft/world/level/ChunkPos;)V"
)
)
private <T> void skipTickingTicketTrackerAdd(final TickingTracker instance, final TicketType<T> ticketType,
final ChunkPos chunkPos, final int i, final T object) {}
private void skipTickingTicketTrackerAdd(final TicketStorage instance, final Ticket ticket, final ChunkPos pos) {}
/**
* @reason Remove old chunk system hooks
@@ -213,11 +172,10 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
method = "removePlayer",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/TickingTracker;removeTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"
target = "Lnet/minecraft/world/level/TicketStorage;removeTicket(Lnet/minecraft/server/level/Ticket;Lnet/minecraft/world/level/ChunkPos;)V"
)
)
private <T> void skipTickingTicketTrackerRemove(final TickingTracker instance, final TicketType<T> ticketType,
final ChunkPos chunkPos, final int i, final T object) {}
private void skipTickingTicketTrackerRemove(final TicketStorage instance, final Ticket ticket, final ChunkPos pos) {}
/**
* @reason Remove old chunk system hooks
@@ -268,8 +226,9 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
* @author Spottedleaf
*/
@Overwrite
public String getTicketDebugString(final long pos) {
return this.moonrise$getChunkHolderManager().getTicketDebugString(pos);
public int getChunkLevel(final long pos, final boolean simulation) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().getChunkHolder(pos);
return chunkHolder == null ? ChunkHolderManager.MAX_TICKET_LEVEL + 1 : chunkHolder.getTicketLevel();
}
/**
@@ -293,55 +252,30 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getPlayerChunkLoader().setTickDistance(clamped);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void forEachEntityTickingChunk(final LongConsumer consumer) {
final ReferenceList<LevelChunk> chunks = ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getEntityTickingChunks();
final LevelChunk[] raw = chunks.getRawDataUnchecked();
final int size = chunks.size();
Objects.checkFromToIndex(0, size, raw.length);
for (int i = 0; i < size; ++i) {
final LevelChunk chunk = raw[i];
consumer.accept(CoordinateUtils.getChunkKey(chunk.getPos()));
}
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public String getDebugStatus() {
return "No DistanceManager stats available";
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public void dumpTickets(final String file) {
throw new UnsupportedOperationException();
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public TickingTracker tickingTracker() {
throw new UnsupportedOperationException();
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public LongSet getTickingChunks() {
throw new UnsupportedOperationException();
}
/**
* @reason This hack is not required anymore, see {@link MinecraftServerMixin}
* @author Spottedleaf
*/
@Overwrite
public void removeTicketsOnClosing() {}
/**
* @reason This hack is not required anymore, see {@link MinecraftServerMixin}
* @author Spottedleaf
*/
@Overwrite
public boolean hasTickets() {
throw new UnsupportedOperationException();
return "N/A";
}
}

View File

@@ -11,9 +11,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(DynamicGameEventListener.class)
abstract class DynamicGameEventListenerMixin {
@Shadow @Nullable private SectionPos lastSection;
@Shadow
@Nullable
private SectionPos lastSection;
@Inject(method = "remove", at = @At("RETURN"))
@Inject(
method = "remove",
at = @At("RETURN")
)
private void onRemove(final CallbackInfo ci) {
// We need to unset the last section when removed, otherwise if the same instance is re-added at the same position it
// will assume there was no change and fail to re-register.

View File

@@ -4,6 +4,7 @@ import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import com.google.common.collect.ImmutableList;
import com.mojang.logging.LogUtils;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
@@ -32,10 +33,6 @@ abstract class EntityMixin implements ChunkSystemEntity {
@Shadow
protected abstract Stream<Entity> getIndirectPassengersStream();
@Shadow
@Final
private static Logger LOGGER;
@Shadow
private Level level;
@@ -43,6 +40,8 @@ abstract class EntityMixin implements ChunkSystemEntity {
@Nullable
private Entity.RemovalReason removalReason;
@Unique
private static final Logger LOGGER = LogUtils.getLogger();
@Unique
private final boolean isHardColliding = this.moonrise$isHardCollidingUncached();

View File

@@ -25,7 +25,7 @@ abstract class EntityTickListMixin {
private Int2ObjectMap<Entity> passive;
@Unique
private final IteratorSafeOrderedReferenceSet<Entity> entities = new IteratorSafeOrderedReferenceSet<>();
private final IteratorSafeOrderedReferenceSet<Entity> entities = new IteratorSafeOrderedReferenceSet<>(Entity.class);
/**
* @reason Initialise new fields and destroy old state

View File

@@ -1,6 +1,7 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks;
import net.minecraft.core.Registry;
import net.minecraft.server.level.ServerChunkCache;
@@ -48,7 +49,7 @@ abstract class LevelChunkMixin extends ChunkAccess implements ChunkSystemLevelCh
private boolean postProcessingDone;
@Unique
private ServerChunkCache.ChunkAndHolder chunkAndHolder;
private NewChunkHolder chunkAndHolder;
@Override
public final boolean moonrise$isPostProcessingDone() {
@@ -56,12 +57,12 @@ abstract class LevelChunkMixin extends ChunkAccess implements ChunkSystemLevelCh
}
@Override
public final ServerChunkCache.ChunkAndHolder moonrise$getChunkAndHolder() {
public final NewChunkHolder moonrise$getChunkHolder() {
return this.chunkAndHolder;
}
@Override
public final void moonrise$setChunkAndHolder(final ServerChunkCache.ChunkAndHolder holder) {
public final void moonrise$setChunkHolder(final NewChunkHolder holder) {
this.chunkAndHolder = holder;
}

View File

@@ -105,12 +105,12 @@ abstract class LevelChunkTicksMixin<T> implements ChunkSystemLevelChunkTicks, Se
* @author Spottedleaf
*/
@Inject(
method = "save(JLjava/util/function/Function;)Lnet/minecraft/nbt/ListTag;",
method = "pack",
at = @At(
value = "HEAD"
)
)
private void saveHook(final long time, final Function<T, String> idFunction, final CallbackInfoReturnable<ListTag> cir) {
private void saveHook(final long time, final CallbackInfoReturnable<ListTag> cir) {
this.lastSaved = time;
}

View File

@@ -190,6 +190,11 @@ abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<TickTask
)
)
private boolean doNotWaitChunkSystemShutdown(final Stream<ServerLevel> instance, final Predicate<? super ServerLevel> predicate) {
// note: make sure we call deactivateTicketsOnClosing
for (final ServerLevel world : this.getAllLevels()) {
world.getChunkSource().deactivateTicketsOnClosing();
}
return false;
}
@@ -238,9 +243,9 @@ abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<TickTask
)
)
private void closeIOThreads(final CallbackInfo ci) {
LOGGER.info("Waiting for I/O tasks to complete...");
LOGGER.info("Waiting for all RegionFile I/O tasks to complete...");
MoonriseRegionFileIO.flush((MinecraftServer)(Object)this);
LOGGER.info("All I/O tasks to complete");
LOGGER.info("All RegionFile I/O tasks to complete");
if ((Object)this instanceof DedicatedServer) {
MoonriseCommon.haltExecutors();
}

View File

@@ -3,18 +3,17 @@ package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.common.util.TickThread;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer;
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
@@ -35,8 +34,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@@ -59,9 +56,6 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
@Unique
private final ConcurrentLong2ReferenceChainedHashTable<LevelChunk> fullChunks = new ConcurrentLong2ReferenceChainedHashTable<>();
@Unique
private long chunksTicked;
@Override
public final void moonrise$setFullChunk(final int chunkX, final int chunkZ, final LevelChunk chunk) {
final long key = CoordinateUtils.getChunkKey(chunkX, chunkZ);
@@ -339,38 +333,34 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
}
/**
* @reason Perform mid-tick chunk task processing during chunk tick
* @author Spottedleaf
*/
@Inject(
method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V",
at = @At(
value = "INVOKE",
shift = At.Shift.AFTER,
target = "Lnet/minecraft/server/level/ServerLevel;tickChunk(Lnet/minecraft/world/level/chunk/LevelChunk;I)V"
)
)
private void midTickChunks(final CallbackInfo ci) {
if ((++this.chunksTicked & 7L) != 0L) {
return;
}
((ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks();
}
/**
* @reason In the chunk system, ticking chunks always have loaded entities. Of course, they are also always
* marked to be as ticking as well.
* @reason In the chunk system, spawn chunks will return only entity ticking chunks - we can elide the
* entity ticking range check.
* @author Spottedleaf
*/
@Redirect(
method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V",
method = "tickSpawningChunk",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerLevel;shouldTickBlocksAt(J)Z"
target = "Lnet/minecraft/server/level/DistanceManager;inEntityTickingRange(J)Z"
)
)
private boolean shortShouldTickBlocks(final ServerLevel instance, final long pos) {
private boolean shortTickThunder(final DistanceManager instance, final long pos) {
return true;
}
/**
* @reason In the chunk system, spawn chunks will return only entity ticking chunks - we can elide the
* entity ticking check.
* @author Spottedleaf
*/
@Redirect(
method = "tickSpawningChunk",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerLevel;canSpawnEntitiesInChunk(Lnet/minecraft/world/level/ChunkPos;)Z"
)
)
private boolean onlyCheckWBForSpawning(final ServerLevel instance, final ChunkPos pos) {
return instance.getWorldBorder().isWithinBounds(pos);
}
}

View File

@@ -10,7 +10,6 @@ import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.EntityData
import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.PoiDataController;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup;
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
@@ -27,13 +26,11 @@ import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.RandomSequences;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
@@ -64,12 +61,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
@Mixin(ServerLevel.class)
@@ -121,16 +116,16 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
private final NearbyPlayers nearbyPlayers = new NearbyPlayers((ServerLevel)(Object)this);
@Unique
private static final ServerChunkCache.ChunkAndHolder[] EMPTY_CHUNK_AND_HOLDERS = new ServerChunkCache.ChunkAndHolder[0];
private static final LevelChunk[] EMPTY_LEVEL_CHUNKS = new LevelChunk[0];
@Unique
private final ReferenceList<ServerChunkCache.ChunkAndHolder> loadedChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS);
private final ReferenceList<LevelChunk> loadedChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS);
@Unique
private final ReferenceList<ServerChunkCache.ChunkAndHolder> tickingChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS);
private final ReferenceList<LevelChunk> tickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS);
@Unique
private final ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS);
private final ReferenceList<LevelChunk> entityTickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS);
/**
* @reason Initialise fields / destroy entity manager state
@@ -334,17 +329,17 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
}
@Override
public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getLoadedChunks() {
public final ReferenceList<LevelChunk> moonrise$getLoadedChunks() {
return this.loadedChunks;
}
@Override
public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getTickingChunks() {
public final ReferenceList<LevelChunk> moonrise$getTickingChunks() {
return this.tickingChunks;
}
@Override
public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getEntityTickingChunks() {
public final ReferenceList<LevelChunk> moonrise$getEntityTickingChunks() {
return this.entityTickingChunks;
}
@@ -666,7 +661,7 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
* @author Spottedleaf
*/
@Overwrite
public boolean isPositionEntityTicking(BlockPos pos) {
public boolean isPositionEntityTicking(final BlockPos pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos));
return chunkHolder != null && chunkHolder.isEntityTickingReady();
}
@@ -676,7 +671,7 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
* @author Spottedleaf
*/
@Overwrite
public boolean isNaturalSpawningAllowed(final BlockPos pos) {
public boolean areEntitiesActuallyLoadedAndTicking(final ChunkPos pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos));
return chunkHolder != null && chunkHolder.isEntityTickingReady();
}
@@ -685,8 +680,14 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
* @reason Redirect to chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean isNaturalSpawningAllowed(final ChunkPos pos) {
@Redirect(
method = "canSpawnEntitiesInChunk",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;canPositionTick(Lnet/minecraft/world/level/ChunkPos;)Z"
)
)
private <T extends EntityAccess> boolean redirectCanEntitiesSpawnTickCheck(final PersistentEntitySectionManager<T> instance, final ChunkPos pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos));
return chunkHolder != null && chunkHolder.isEntityTickingReady();
}

View File

@@ -49,8 +49,7 @@ abstract class SortedArraySetMixin<T> extends AbstractSet<T> implements ChunkSys
if (i >= len) {
return false;
}
if (!filter.test(backingArray[i])) {
++i;
if (!filter.test(backingArray[i++])) {
continue;
}
break;
@@ -58,7 +57,7 @@ abstract class SortedArraySetMixin<T> extends AbstractSet<T> implements ChunkSys
// we only want to write back to backingArray if we really need to
int lastIndex = i; // this is where new elements are shifted to
int lastIndex = i - 1; // this is where new elements are shifted to
for (; i < len; ++i) {
final T curr = backingArray[i];

View File

@@ -1,6 +1,7 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import org.spongepowered.asm.mixin.Final;
@@ -8,61 +9,75 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import java.util.Comparator;
@Mixin(Ticket.class)
abstract class TicketMixin<T> implements ChunkSystemTicket<T>, Comparable<Ticket<?>> {
abstract class TicketMixin<T> implements ChunkSystemTicket<T>, Comparable<Ticket> {
@Shadow
@Final
private TicketType<T> type;
private TicketType type;
@Shadow
@Final
private int ticketLevel;
@Shadow
@Final
public T key;
private long ticksLeft;
@Unique
private long removeDelay;
private T identifier;
@Override
public final long moonrise$getRemoveDelay() {
return this.removeDelay;
return this.ticksLeft;
}
@Override
public final void moonrise$setRemoveDelay(final long removeDelay) {
this.removeDelay = removeDelay;
this.ticksLeft = removeDelay;
}
@Override
public final T moonrise$getIdentifier() {
return this.identifier;
}
@Override
public final void moonrise$setIdentifier(final T identifier) {
if ((identifier == null) != (((ChunkSystemTicketType<T>)(Object)this.type).moonrise$getIdentifierComparator() == null)) {
throw new IllegalStateException("Nullability of identifier should match nullability of comparator");
}
this.identifier = identifier;
}
/**
* @reason Change debug to include remove delay
* @reason Change debug to include remove identifier
* @author Spottedleaf
*/
@Overwrite
@Override
public String toString() {
return "Ticket[" + this.type + " " + this.ticketLevel + " (" + this.key + ")] to die in " + this.removeDelay;
return "Ticket[" + this.type + " " + this.ticketLevel + " (" + this.identifier + ")] to die in " + this.ticksLeft;
}
/**
* @reason Remove old chunk system hook
* @author Spottedleaf
*/
@Overwrite
public void setCreatedTick(final long tickCreated) {
throw new UnsupportedOperationException();
@Override
public final int compareTo(final Ticket ticket) {
final int levelCompare = Integer.compare(this.ticketLevel, ((TicketMixin<?>)(Object)ticket).ticketLevel);
if (levelCompare != 0) {
return levelCompare;
}
/**
* @reason Remove old chunk system hook
* @author Spottedleaf
*/
@Overwrite
public boolean timedOut(final long currentTick) {
throw new UnsupportedOperationException();
final int typeCompare = Long.compare(
((ChunkSystemTicketType<T>)(Object)this.type).moonrise$getId(),
((ChunkSystemTicketType<?>)(Object)((TicketMixin<?>)(Object)ticket).type).moonrise$getId()
);
if (typeCompare != 0) {
return typeCompare;
}
final Comparator<T> comparator = ((ChunkSystemTicketType<T>)(Object)this.type).moonrise$getIdentifierComparator();
return comparator == null ? 0 : comparator.compare(this.identifier, ((TicketMixin<T>)(Object)ticket).identifier);
}
}

View File

@@ -0,0 +1,258 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketStorage;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.SortedArraySet;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import net.minecraft.world.level.saveddata.SavedData;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
@Mixin(TicketStorage.class)
abstract class TicketStorageMixin extends SavedData implements ChunkSystemTicketStorage {
@Shadow
@Final
private Long2ObjectOpenHashMap<List<Ticket>> deactivatedTickets;
@Shadow
private Long2ObjectOpenHashMap<List<Ticket>> tickets;
@Shadow
private LongSet chunksWithForcedTickets;
@Unique
private ChunkMap chunkMap;
@Override
public final ChunkMap moonrise$getChunkMap() {
return this.chunkMap;
}
@Override
public final void moonrise$setChunkMap(final ChunkMap chunkMap) {
this.chunkMap = chunkMap;
}
/**
* @reason Destroy old chunk system state
* @author Spottedleaf
*/
@Inject(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "RETURN"
)
)
private void destroyFields(Long2ObjectOpenHashMap p_393873_, Long2ObjectOpenHashMap p_394615_, CallbackInfo ci) {
if (!this.tickets.isEmpty()) {
throw new IllegalStateException("Expect tickets to be empty here!");
}
this.tickets = null;
this.chunksWithForcedTickets = null;
}
/**
* @reason The forced chunks would be empty, as tickets should always be empty.
* We need to do this to avoid throwing immediately.
* @author Spottedleaf
*/
@Redirect(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;updateForcedChunks()V"
)
)
private void avoidUpdatingForcedChunks(final TicketStorage instance) {}
/**
* @reason Redirect regular ticket retrieval to new chunk system
* @author Spottedleaf
*/
@Redirect(
method = "forEachTicket(Ljava/util/function/BiConsumer;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;forEachTicket(Ljava/util/function/BiConsumer;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
ordinal = 0
)
)
private void redirectRegularTickets(final BiConsumer<ChunkPos, Ticket> consumer, final Long2ObjectOpenHashMap<List<Ticket>> ticketsParam) {
if (ticketsParam != null) {
throw new IllegalStateException("Bad injection point");
}
final Long2ObjectOpenHashMap<SortedArraySet<Ticket>> tickets = ((ChunkSystemServerLevel)this.chunkMap.level)
.moonrise$getChunkTaskScheduler().chunkHolderManager.getTicketsCopy();
for (final Iterator<Long2ObjectMap.Entry<SortedArraySet<Ticket>>> iterator = tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
final Long2ObjectMap.Entry<SortedArraySet<Ticket>> entry = iterator.next();
final long pos = entry.getLongKey();
final SortedArraySet<Ticket> chunkTickets = entry.getValue();
final ChunkPos chunkPos = new ChunkPos(pos);
for (final Ticket ticket : chunkTickets) {
consumer.accept(chunkPos, ticket);
}
}
}
/**
* @reason Avoid setting old chunk system state
* @author Spottedleaf
*/
@Overwrite
public void setLoadingChunkUpdatedListener(final TicketStorage.ChunkUpdated callback) {}
/**
* @reason Avoid setting old chunk system state
* @author Spottedleaf
*/
@Overwrite
public void setSimulationChunkUpdatedListener(final TicketStorage.ChunkUpdated callback) {}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean hasTickets() {
return ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager.hasTickets();
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public List<Ticket> getTickets(final long pos) {
return ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager
.getTicketsAt(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean addTicket(final long pos, final Ticket ticket) {
final boolean ret = ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager
.addTicketAtLevel(ticket.getType(), pos, ticket.getTicketLevel(), null);
this.setDirty();
return ret;
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean removeTicket(final long pos, final Ticket ticket) {
final boolean ret = ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager
.removeTicketAtLevel(ticket.getType(), pos, ticket.getTicketLevel(), null);
if (ret) {
this.setDirty();
}
return ret;
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void purgeStaleTickets() {
((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager.tick();
}
/**
* @reason All tickets (inactive or not) are packed and saved, so there's no real reason we need to remove them.
* Vanilla removes them as it requires every chunk to go through the unload logic; however we already manually
* do this on shutdown.
* @author Spottedleaf
*/
@Redirect(
method = "deactivateTicketsOnClosing",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;removeTicketIf(Ljava/util/function/Predicate;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V"
)
)
private void avoidRemovingTicketsOnShutdown(final TicketStorage instance,
final Predicate<Ticket> predicate,
final Long2ObjectOpenHashMap<List<Ticket>> tickets) {}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public void removeTicketIf(final Predicate<Ticket> predicate, final Long2ObjectOpenHashMap<List<Ticket>> into) {
throw new UnsupportedOperationException();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public void replaceTicketLevelOfType(final int newLevel, final TicketType forType) {
throw new UnsupportedOperationException();
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public LongSet getForceLoadedChunks() {
final Long2IntOpenHashMap forced = ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler()
.chunkHolderManager.getTicketCounters(ChunkSystemTicketType.COUNTER_TYPE_FORCED);
if (forced == null) {
return LongSet.of();
}
return forced.keySet();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public LongSet getAllChunksWithTicketThat(final Predicate<Ticket> predicate) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,69 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import net.minecraft.server.level.TicketType;
import org.spongepowered.asm.mixin.Mixin;
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;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicLong;
@Mixin(TicketType.class)
abstract class TicketTypeMixin<T> implements ChunkSystemTicketType<T> {
@Unique
private static AtomicLong ID_GENERATOR;
/**
* @reason Need to initialise at the start of clinit, as ticket types are constructed after.
* Using just the field initialiser would append the static initialiser.
* @author Spottedleaf
*/
@Inject(
method = "<clinit>",
at = @At(
value = "HEAD"
)
)
private static void initIdGenerator(final CallbackInfo ci) {
ID_GENERATOR = new AtomicLong();
}
@Unique
private final long id = ID_GENERATOR.getAndIncrement();
@Unique
private Comparator<T> identifierComparator;
@Unique
private volatile long[] counterTypes;
@Override
public final long moonrise$getId() {
return this.id;
}
@Override
public final Comparator<T> moonrise$getIdentifierComparator() {
return this.identifierComparator;
}
@Override
public final void moonrise$setIdentifierComparator(final Comparator<T> comparator) {
this.identifierComparator = comparator;
}
@Override
public final long[] moonrise$getCounterTypes() {
// need to lazy init this because we cannot check if we are FORCED during construction
final long[] types = this.counterTypes;
if (types != null) {
return types;
}
return this.counterTypes = PlatformHooks.get().getCounterTypesUncached((TicketType)(Object)this);
}
}

View File

@@ -2,18 +2,27 @@ package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import com.llamalad7.mixinextras.sugar.Local;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -85,11 +94,15 @@ abstract class ChunkMapMixin {
}
/**
* @reason Avoid checking first if there are nearby players, as we make internal perform this implicitly.
* @reason Avoid checking for DEFAULT state, as we make internal perform this implicitly.
* @author Spottedleaf
*/
@Overwrite
public boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos) {
if (((ChunkTickDistanceManager)this.distanceManager).moonrise$hasAnyNearbyNarrow(pos.x, pos.z)) {
return true;
}
return this.anyPlayerCloseEnoughForSpawningInternal(pos);
}
@@ -152,4 +165,111 @@ abstract class ChunkMapMixin {
return ret == null ? new ArrayList<>() : ret;
}
@Unique
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
final ChunkData chunkData = ((ChunkSystemLevelChunk)levelChunk).moonrise$getChunkHolder().holderData;
final NearbyPlayers.TrackedChunk nearbyPlayers = chunkData.nearbyPlayers;
if (nearbyPlayers == null) {
return false;
}
if (((ChunkTickDistanceManager)this.distanceManager).moonrise$hasAnyNearbyNarrow(chunkPos.x, chunkPos.z)) {
return true;
}
final ReferenceList<ServerPlayer> players = nearbyPlayers.getPlayers(NearbyPlayers.NearbyMapType.SPAWN_RANGE);
if (players == null) {
return false;
}
final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size();
Objects.checkFromIndexSize(0, len, raw.length);
for (int i = 0; i < len; ++i) {
if (chunkMap.playerIsCloseEnoughForSpawning(raw[i], chunkPos)) {
return true;
}
}
return false;
}
/**
* @reason Use the player ticking chunks list, which already contains chunks that are:
* 1. entity ticking
* 2. within spawn range (8 chunks on any axis)
* @author Spottedleaf
*/
@Inject(
method = "collectSpawningChunks",
// use cancellable inject to be compatible with the chunk system's hook here
cancellable = true,
at = @At(
value = "HEAD"
)
)
public void collectSpawningChunks(final List<LevelChunk> list, final CallbackInfo ci) {
final ReferenceList<LevelChunk> tickingChunks = ((ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks();
final Long2IntOpenHashMap forceSpawningChunks = ((ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler()
.chunkHolderManager.getTicketCounters(ChunkSystemTicketType.COUNTER_TYPER_NATURAL_SPAWNING_FORCED);
final LevelChunk[] raw = tickingChunks.getRawDataUnchecked();
final int size = tickingChunks.size();
Objects.checkFromToIndex(0, size, raw.length);
if (forceSpawningChunks != null && !forceSpawningChunks.isEmpty()) {
// note: expect forceSpawningChunks.size <<< tickingChunks.size
final LongOpenHashSet seen = new LongOpenHashSet(forceSpawningChunks.size());
final ChunkHolderManager chunkHolderManager = ((ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager;
// note: this fixes a bug in neoforge where these chunks don't tick away from a player...
// note: this is NOT the only problem with their implementation, either...
for (final LongIterator iterator = forceSpawningChunks.keySet().longIterator(); iterator.hasNext();) {
final long pos = iterator.nextLong();
final NewChunkHolder holder = chunkHolderManager.getChunkHolder(pos);
if (holder == null || !holder.isEntityTickingReady()) {
continue;
}
seen.add(pos);
list.add((LevelChunk)holder.getCurrentChunk());
}
for (int i = 0; i < size; ++i) {
final LevelChunk levelChunk = raw[i];
if (seen.contains(CoordinateUtils.getChunkKey(levelChunk.getPos()))) {
// do not add duplicate chunks
continue;
}
if (!this.isChunkNearPlayer((ChunkMap)(Object)this, levelChunk.getPos(), levelChunk)) {
continue;
}
list.add(levelChunk);
}
} else {
for (int i = 0; i < size; ++i) {
final LevelChunk levelChunk = raw[i];
if (!this.isChunkNearPlayer((ChunkMap)(Object)this, levelChunk.getPos(), levelChunk)) {
continue;
}
list.add(levelChunk);
}
}
ci.cancel();
}
}

View File

@@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.longs.LongIterator;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.TriState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@@ -21,20 +22,24 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
@Shadow
private DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter;
public DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter;
@Unique
private final PositionCountingAreaMap<ServerPlayer> spawnChunkTracker = new PositionCountingAreaMap<>();
@Unique
private final PositionCountingAreaMap<ServerPlayer> narrowSpawnChunkTracker = new PositionCountingAreaMap<>();
@Override
public final void moonrise$addPlayer(final ServerPlayer player, final SectionPos pos) {
this.spawnChunkTracker.add(player, pos.x(), pos.z(), ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE);
this.narrowSpawnChunkTracker.add(player, pos.x(), pos.z(), ChunkTickConstants.NARROW_SPAWN_TRACK_RANGE);
}
@Override
public final void moonrise$removePlayer(final ServerPlayer player, final SectionPos pos) {
this.spawnChunkTracker.remove(player);
this.narrowSpawnChunkTracker.remove(player);
}
@Override
@@ -43,11 +48,18 @@ abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
final boolean oldIgnore, final boolean newIgnore) {
if (newIgnore) {
this.spawnChunkTracker.remove(player);
this.narrowSpawnChunkTracker.remove(player);
} else {
this.spawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE);
this.narrowSpawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ChunkTickConstants.NARROW_SPAWN_TRACK_RANGE);
}
}
@Override
public final boolean moonrise$hasAnyNearbyNarrow(final int chunkX, final int chunkZ) {
return this.narrowSpawnChunkTracker.hasObjectsNear(chunkX, chunkZ);
}
/**
* @reason Destroy natural spawning tracker field to prevent it from being used
* @author Spottedleaf
@@ -104,8 +116,11 @@ abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
* @author Spottedleaf
*/
@Overwrite
public boolean hasPlayersNearby(final long pos) {
return this.spawnChunkTracker.hasObjectsNear(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
public TriState hasPlayersNearby(final long pos) {
if (this.narrowSpawnChunkTracker.hasObjectsNear(pos)) {
return TriState.TRUE;
}
return this.spawnChunkTracker.hasObjectsNear(pos) ? TriState.DEFAULT : TriState.FALSE;
}
/**

View File

@@ -1,30 +1,26 @@
package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer;
import net.minecraft.Util;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
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.Redirect;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
@Mixin(ServerChunkCache.class)
abstract class ServerChunkCacheMixin extends ChunkSource {
@@ -41,69 +37,13 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
@Unique
private final SimpleThreadUnsafeRandom shuffleRandom = new SimpleThreadUnsafeRandom(0L);
@Unique
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
final ChunkData chunkData = ((ChunkSystemChunkHolder)((ChunkSystemLevelChunk)levelChunk).moonrise$getChunkAndHolder().holder())
.moonrise$getRealChunkHolder().holderData;
final NearbyPlayers.TrackedChunk nearbyPlayers = chunkData.nearbyPlayers;
if (nearbyPlayers == null) {
return false;
}
final ReferenceList<ServerPlayer> players = nearbyPlayers.getPlayers(NearbyPlayers.NearbyMapType.SPAWN_RANGE);
if (players == null) {
return false;
}
final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size();
Objects.checkFromIndexSize(0, len, raw.length);
for (int i = 0; i < len; ++i) {
if (chunkMap.playerIsCloseEnoughForSpawning(raw[i], chunkPos)) {
return true;
}
}
return false;
}
/**
* @reason Use the player ticking chunks list, which already contains chunks that are:
* 1. block ticking
* 2. within spawn range (8 chunks on any axis)
* @author Spottedleaf
*/
@Overwrite
private void collectTickingChunks(final List<LevelChunk> list) {
final ReferenceList<ServerChunkCache.ChunkAndHolder> tickingChunks =
((ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks();
final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked();
final int size = tickingChunks.size();
final ChunkMap chunkMap = this.chunkMap;
for (int i = 0; i < size; ++i) {
final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i];
final LevelChunk levelChunk = chunkAndHolder.chunk();
if (!this.isChunkNearPlayer(chunkMap, levelChunk.getPos(), levelChunk)) {
continue;
}
list.add(levelChunk);
}
}
/**
* @reason Use random implementation which does not use CAS and has a faster nextInt(int)
* function
* @author Spottedleaf
*/
@Redirect(
method = "tickChunks()V",
method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/Util;shuffle(Ljava/util/List;Lnet/minecraft/util/RandomSource;)V"
@@ -113,4 +53,41 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
this.shuffleRandom.setSeed(randomSource.nextLong());
Util.shuffle(list, this.shuffleRandom);
}
/**
* @reason Do not iterate over entire chunk holder map; additionally perform mid-tick chunk task execution
* @author Spottedleaf
*/
@Redirect(
method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ChunkMap;forEachBlockTickingChunk(Ljava/util/function/Consumer;)V"
)
)
private void iterateTickingChunksFaster(final ChunkMap instance, final Consumer<LevelChunk> consumer) {
final ServerLevel world = this.level;
final int randomTickSpeed = world.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
// TODO check on update: impl of forEachBlockTickingChunk will only iterate ENTITY ticking chunks!
// TODO check on update: consumer just runs tickChunk
final ReferenceList<LevelChunk> entityTickingChunks = ((ChunkSystemServerLevel)world).moonrise$getEntityTickingChunks();
// note: we can use the backing array here because:
// 1. we do not care about new additions
// 2. _removes_ are impossible at this stage in the tick
final LevelChunk[] raw = entityTickingChunks.getRawDataUnchecked();
final int size = entityTickingChunks.size();
Objects.checkFromToIndex(0, size, raw.length);
for (int i = 0; i < size; ++i) {
world.tickChunk(raw[i], randomTickSpeed);
// call mid-tick tasks for chunk system
if ((i & 7) == 0) {
((ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks();
continue;
}
}
}
}

View File

@@ -19,16 +19,16 @@ import org.spongepowered.asm.mixin.Unique;
abstract class ServerLevelMixin implements ChunkTickServerLevel {
@Unique
private static final ServerChunkCache.ChunkAndHolder[] EMPTY_PLAYER_CHUNK_HOLDERS = new ServerChunkCache.ChunkAndHolder[0];
private static final LevelChunk[] EMPTY_LEVEL_CHUNKS = new LevelChunk[0];
@Unique
private final ReferenceList<ServerChunkCache.ChunkAndHolder> playerTickingChunks = new ReferenceList<>(EMPTY_PLAYER_CHUNK_HOLDERS);
private final ReferenceList<LevelChunk> playerTickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS);
@Unique
private final Long2IntOpenHashMap playerTickingRequests = new Long2IntOpenHashMap();
@Override
public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getPlayerTickingChunks() {
public final ReferenceList<LevelChunk> moonrise$getPlayerTickingChunks() {
return this.playerTickingChunks;
}
@@ -39,12 +39,12 @@ abstract class ServerLevelMixin implements ChunkTickServerLevel {
return;
}
this.playerTickingChunks.add(((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder());
this.playerTickingChunks.add(chunk);
}
@Override
public final void moonrise$removeChunkForPlayerTicking(final LevelChunk chunk) {
this.playerTickingChunks.remove(((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder());
this.playerTickingChunks.remove(chunk);
}
@Override
@@ -65,9 +65,7 @@ abstract class ServerLevelMixin implements ChunkTickServerLevel {
return;
}
this.playerTickingChunks.add(
((ChunkSystemLevelChunk)(LevelChunk)chunkHolder.getCurrentChunk()).moonrise$getChunkAndHolder()
);
this.playerTickingChunks.add((LevelChunk)chunkHolder.getCurrentChunk());
}
@Override
@@ -93,8 +91,6 @@ abstract class ServerLevelMixin implements ChunkTickServerLevel {
return;
}
this.playerTickingChunks.remove(
((ChunkSystemLevelChunk)(LevelChunk)chunkHolder.getCurrentChunk()).moonrise$getChunkAndHolder()
);
this.playerTickingChunks.remove((LevelChunk)chunkHolder.getCurrentChunk());
}
}

View File

@@ -345,11 +345,8 @@ abstract class ShapesMixin {
* @author Spottedleaf
*/
@Overwrite
public static boolean blockOccudes(final VoxelShape first, final VoxelShape second, final Direction direction) {
final boolean firstBlock = first == BLOCK;
final boolean secondBlock = second == BLOCK;
if (firstBlock & secondBlock) {
public static boolean blockOccludes(final VoxelShape first, final VoxelShape second, final Direction direction) {
if (first == BLOCK & second == BLOCK) {
return true;
}

View File

@@ -17,7 +17,7 @@ interface ServerAddressResolverMixin {
@Redirect(
method = {
"method_36903",
"*(Lnet/minecraft/client/multiplayer/resolver/ServerAddress;)Ljava/util/Optional;"
"lambda$static$0"
},
at = @At(
value = "INVOKE",

View File

@@ -49,10 +49,10 @@ import java.util.function.Supplier;
abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements StarLightLightingProvider {
@Shadow
private ConsecutiveExecutor consecutiveExecutor;
public ConsecutiveExecutor consecutiveExecutor;
@Shadow
private ChunkTaskDispatcher taskDispatcher;
public ChunkTaskDispatcher taskDispatcher;
public ThreadedLevelLightEngineMixin(final LightChunkGetter chunkProvider, final boolean hasBlockLight, final boolean hasSkyLight) {
super(chunkProvider, hasBlockLight, hasSkyLight);
@@ -86,10 +86,10 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
final Long ticketId = Long.valueOf(this.chunkWorkCounter.getAndIncrement());
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
world.getChunkSource().addRegionTicket(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, ticketId);
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.LIGHT_TICKET_LEVEL, ticketId);
scheduledTask.queueOrRunTask(() -> {
world.getChunkSource().removeRegionTicket(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, ticketId);
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.LIGHT_TICKET_LEVEL, ticketId);
});
}
@@ -105,7 +105,7 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
final ChunkPos pos = iterator.next();
final Long id = ChunkTaskScheduler.getNextChunkRelightId();
world.getChunkSource().addRegionTicket(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, id);
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.LIGHT_TICKET_LEVEL, id);
ticketIds.put(pos, id);
final ChunkAccess chunk = (ChunkAccess)world.getChunkSource().getChunkForLighting(pos.x, pos.z);
@@ -113,7 +113,7 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
// cannot relight this chunk
iterator.remove();
ticketIds.remove(pos);
world.getChunkSource().removeRegionTicket(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, id);
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.LIGHT_TICKET_LEVEL, id);
continue;
}
}
@@ -160,9 +160,9 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
}
for (final Map.Entry<ChunkPos, Long> entry : ticketIds.entrySet()) {
world.getChunkSource().removeRegionTicket(
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(
ChunkTaskScheduler.CHUNK_RELIGHT, entry.getKey(),
StarLightInterface.REGION_LIGHT_TICKET_LEVEL, entry.getValue()
StarLightInterface.LIGHT_TICKET_LEVEL, entry.getValue()
);
}
}

View File

@@ -60,13 +60,13 @@ abstract class SerializableChunkDataMixin {
method = "parse",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/nbt/CompoundTag;getBoolean(Ljava/lang/String;)Z",
target = "Lnet/minecraft/nbt/CompoundTag;getBooleanOr(Ljava/lang/String;Z)Z",
ordinal = 0
)
)
private static boolean setLightCorrect(final CompoundTag instance, final String string,
private static boolean setLightCorrect(final CompoundTag instance, final String string, final boolean dfl,
@Local(ordinal = 0, argsOnly = false) final ChunkStatus status) {
final boolean starlightCorrect = instance.get("isLightOn") != null && instance.getInt(SaveUtil.STARLIGHT_VERSION_TAG) == SaveUtil.STARLIGHT_LIGHT_VERSION;
final boolean starlightCorrect = instance.get("isLightOn") != null && instance.getIntOr(SaveUtil.STARLIGHT_VERSION_TAG, -1) == SaveUtil.STARLIGHT_LIGHT_VERSION;
return status.isOrAfter(ChunkStatus.LIGHT) && starlightCorrect;
}
@@ -84,17 +84,17 @@ abstract class SerializableChunkDataMixin {
)
private static SerializableChunkData.SectionData readStarlightState(final int y, final LevelChunkSection chunkSection,
final DataLayer blockLight, final DataLayer skyLight,
@Local(ordinal = 3, argsOnly = false) final CompoundTag sectionData) {
@Local(ordinal = 2, argsOnly = false) final CompoundTag sectionData) {
final SerializableChunkData.SectionData ret = new SerializableChunkData.SectionData(
y, chunkSection, blockLight, skyLight
);
if (sectionData.contains(SaveUtil.BLOCKLIGHT_STATE_TAG, Tag.TAG_ANY_NUMERIC)) {
((StarlightSectionData)(Object)ret).starlight$setBlockLightState(sectionData.getInt(SaveUtil.BLOCKLIGHT_STATE_TAG));
if (sectionData.contains(SaveUtil.BLOCKLIGHT_STATE_TAG)) {
((StarlightSectionData)(Object)ret).starlight$setBlockLightState(sectionData.getIntOr(SaveUtil.BLOCKLIGHT_STATE_TAG, 0));
}
if (sectionData.contains(SaveUtil.SKYLIGHT_STATE_TAG, Tag.TAG_ANY_NUMERIC)) {
((StarlightSectionData)(Object)ret).starlight$setSkyLightState(sectionData.getInt(SaveUtil.SKYLIGHT_STATE_TAG));
if (sectionData.contains(SaveUtil.SKYLIGHT_STATE_TAG)) {
((StarlightSectionData)(Object)ret).starlight$setSkyLightState(sectionData.getIntOr(SaveUtil.SKYLIGHT_STATE_TAG, 0));
}
return ret;

View File

@@ -19,8 +19,7 @@ public final class ChunkSystemConverters {
}
private static int getDataVersion(final CompoundTag data, final int dfl) {
return !data.contains(SharedConstants.DATA_VERSION_TAG, Tag.TAG_ANY_NUMERIC)
? dfl : data.getInt(SharedConstants.DATA_VERSION_TAG);
return data.getIntOr(SharedConstants.DATA_VERSION_TAG, dfl);
}
public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) {

View File

@@ -48,7 +48,7 @@ public final class EntityDataController extends MoonriseRegionFileIO.RegionDataC
}
private static void checkPosition(final ChunkPos pos, final CompoundTag nbt) {
final ChunkPos nbtPos = nbt == null ? null : EntityStorage.readChunkPos(nbt);
final ChunkPos nbtPos = nbt == null ? null : nbt.read("Position", ChunkPos.CODEC).orElse(null);
if (nbtPos != null && !pos.equals(nbtPos)) {
throw new IllegalArgumentException(
"Entity chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + pos.toString()

View File

@@ -1,6 +1,7 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level;
import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet;
import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
@@ -10,6 +11,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import java.util.List;
import java.util.function.Consumer;
@@ -56,9 +58,9 @@ public interface ChunkSystemServerLevel extends ChunkSystemLevel {
public NearbyPlayers moonrise$getNearbyPlayers();
public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getLoadedChunks();
public ReferenceList<LevelChunk> moonrise$getLoadedChunks();
public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getTickingChunks();
public ReferenceList<LevelChunk> moonrise$getTickingChunks();
public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getEntityTickingChunks();
public ReferenceList<LevelChunk> moonrise$getEntityTickingChunks();
}

View File

@@ -1,13 +1,13 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level.chunk;
import net.minecraft.server.level.ServerChunkCache;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
public interface ChunkSystemLevelChunk {
public boolean moonrise$isPostProcessingDone();
public ServerChunkCache.ChunkAndHolder moonrise$getChunkAndHolder();
public NewChunkHolder moonrise$getChunkHolder();
public void moonrise$setChunkAndHolder(final ServerChunkCache.ChunkAndHolder holder);
public void moonrise$setChunkHolder(final NewChunkHolder holder);
}

View File

@@ -76,7 +76,7 @@ public final class ChunkEntitySlices {
public static List<Entity> readEntities(final ServerLevel world, final CompoundTag compoundTag) {
// TODO check this and below on update for format changes
return EntityType.loadEntitiesRecursive(compoundTag.getList("Entities", 10), world, EntitySpawnReason.LOAD).collect(ImmutableList.toImmutableList());
return EntityType.loadEntitiesRecursive(compoundTag.getListOrEmpty("Entities"), world, EntitySpawnReason.LOAD).collect(ImmutableList.toImmutableList());
}
// Paper start - rewrite chunk system
@@ -84,12 +84,12 @@ public final class ChunkEntitySlices {
if (from == null) {
return;
}
final ListTag entitiesFrom = from.getList("Entities", Tag.TAG_COMPOUND);
final ListTag entitiesFrom = from.getListOrEmpty("Entities");
if (entitiesFrom == null || entitiesFrom.isEmpty()) {
return;
}
final ListTag entitiesInto = into.getList("Entities", Tag.TAG_COMPOUND);
final ListTag entitiesInto = into.getListOrEmpty("Entities");
into.put("Entities", entitiesInto); // this is in case into doesn't have any entities
entitiesInto.addAll(0, entitiesFrom);
}
@@ -112,7 +112,7 @@ public final class ChunkEntitySlices {
}
final CompoundTag ret = NbtUtils.addCurrentDataVersion(new CompoundTag());
ret.put("Entities", entitiesTag);
EntityStorage.writeChunkPos(ret, chunkPos);
ret.store("Position", ChunkPos.CODEC, chunkPos);
return !force && entitiesTag.isEmpty() ? null : ret;
}

View File

@@ -159,7 +159,7 @@ public final class PoiChunk {
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, world.registryAccess());
final CompoundTag sections = data.getCompound("Sections");
final CompoundTag sections = data.getCompoundOrEmpty("Sections");
if (sections.isEmpty()) {
// nothing to parse
@@ -176,7 +176,7 @@ public final class PoiChunk {
continue;
}
final CompoundTag section = sections.getCompound(key);
final CompoundTag section = sections.getCompoundOrEmpty(key);
final DataResult<PoiSection.Packed> deserializeResult = PoiSection.Packed.CODEC.parse(registryOps, section);
final int finalSectionY = sectionY;
final PoiSection.Packed packed = deserializeResult.resultOrPartial((final String description) -> {

View File

@@ -14,6 +14,7 @@ import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunk
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
@@ -45,11 +46,8 @@ import java.util.function.Function;
public final class RegionizedPlayerChunkLoader {
public static final TicketType<Long> PLAYER_TICKET = TicketType.create("chunk_system:player_ticket", Long::compareTo);
public static final TicketType<Long> PLAYER_TICKET_DELAYED = TicketType.create("chunk_system:player_ticket_delayed", Long::compareTo, 5 * 20);
public static final int MIN_VIEW_DISTANCE = 2;
public static final int MAX_VIEW_DISTANCE = 32;
public static final TicketType PLAYER_TICKET = ChunkSystemTicketType.create("chunk_system:player_ticket", Long::compareTo);
public static final TicketType PLAYER_TICKET_DELAYED = ChunkSystemTicketType.create("chunk_system:player_ticket_delayed", Long::compareTo, 5L * 20L);
public static final int GENERATED_TICKET_LEVEL = ChunkHolderManager.FULL_LOADED_TICKET_LEVEL;
public static final int LOADED_TICKET_LEVEL = ChunkTaskScheduler.getTicketLevel(ChunkStatus.EMPTY);
@@ -685,8 +683,7 @@ public final class RegionizedPlayerChunkLoader {
}
this.pushDelayedTicketOp(
ChunkHolderManager.TicketOperation.addOp(
chunk,
PLAYER_TICKET, LOADED_TICKET_LEVEL, this.idBoxed
chunk, PLAYER_TICKET, LOADED_TICKET_LEVEL, this.idBoxed
)
);
chunks.add(chunk);

View File

@@ -16,9 +16,11 @@ 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.GenericDataLoadTask;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_system.util.ChunkSystemSortedArraySet;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ByteLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ByteMap;
import it.unimi.dsi.fastutil.longs.Long2IntMap;
@@ -65,13 +67,12 @@ public final class ChunkHolderManager {
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);
public static final TicketType UNLOAD_COOLDOWN = ChunkSystemTicketType.create("chunk_system:unload_cooldown", null, 5L * 20L);
private static final long NO_TIMEOUT_MARKER = Long.MIN_VALUE;
private static final long PROBE_MARKER = Long.MIN_VALUE + 1;
public final ReentrantAreaLock ticketLockArea;
private final ConcurrentLong2ReferenceChainedHashTable<SortedArraySet<Ticket<?>>> tickets = new ConcurrentLong2ReferenceChainedHashTable<>();
private final ConcurrentLong2ReferenceChainedHashTable<SortedArraySet<Ticket>> tickets = new ConcurrentLong2ReferenceChainedHashTable<>();
private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> sectionToChunkToExpireCount = new ConcurrentLong2ReferenceChainedHashTable<>();
final ChunkUnloadQueue unloadQueue;
@@ -102,6 +103,8 @@ public final class ChunkHolderManager {
return Long.compare(coord1, coord2);
});
private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> ticketCounters = new ConcurrentLong2ReferenceChainedHashTable<>();
public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) {
this.world = world;
this.taskScheduler = taskScheduler;
@@ -163,7 +166,6 @@ public final class ChunkHolderManager {
return this.chunkHolders.size();
}
// TODO replace the need for this, specifically: optimise ServerChunkCache#tickChunks
public Iterable<ChunkHolder> getOldChunkHoldersIterable() {
return new Iterable<ChunkHolder>() {
@Override
@@ -411,7 +413,7 @@ public final class ChunkHolderManager {
public String getTicketDebugString(final long coordinate) {
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(coordinate), CoordinateUtils.getChunkZ(coordinate));
try {
final SortedArraySet<Ticket<?>> tickets = this.tickets.get(coordinate);
final SortedArraySet<Ticket> tickets = this.tickets.get(coordinate);
return tickets != null ? tickets.first().toString() : "no_ticket";
} finally {
@@ -421,8 +423,40 @@ public final class ChunkHolderManager {
}
}
public Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> getTicketsCopy() {
final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> ret = new Long2ObjectOpenHashMap<>();
public boolean hasTickets() {
return !this.tickets.isEmpty();
}
public List<Ticket> getTicketsAt(final int chunkX, final int chunkZ) {
final long key = CoordinateUtils.getChunkKey(chunkX, chunkZ);
if (!this.tickets.containsKey(key)) {
// avoid contending lock
return new ArrayList<>();
}
final ReentrantAreaLock.Node lock = this.ticketLockArea.lock(chunkX, chunkZ);
try {
final SortedArraySet<Ticket> tickets = this.tickets.get(key);
if (tickets == null) {
return new ArrayList<>();
}
final List<Ticket> ret = new ArrayList<>(tickets.size());
for (final Ticket ticket : tickets) {
ret.add(ticket);
}
return ret;
} finally {
this.ticketLockArea.unlock(lock);
}
}
public Long2ObjectOpenHashMap<SortedArraySet<Ticket>> getTicketsCopy() {
final Long2ObjectOpenHashMap<SortedArraySet<Ticket>> ret = new Long2ObjectOpenHashMap<>();
final Long2ObjectOpenHashMap<LongArrayList> sections = new Long2ObjectOpenHashMap<>();
final int sectionShift = this.taskScheduler.getChunkSystemLockShift();
for (final PrimitiveIterator.OfLong iterator = this.tickets.keyIterator(); iterator.hasNext();) {
@@ -451,12 +485,12 @@ public final class ChunkHolderManager {
try {
for (final LongIterator iterator2 = coordinates.iterator(); iterator2.hasNext();) {
final long coord = iterator2.nextLong();
final SortedArraySet<Ticket<?>> tickets = this.tickets.get(coord);
final SortedArraySet<Ticket> tickets = this.tickets.get(coord);
if (tickets == null) {
// removed before we acquired lock
continue;
}
ret.put(coord, ((ChunkSystemSortedArraySet<Ticket<?>>)tickets).moonrise$copy());
ret.put(coord, ((ChunkSystemSortedArraySet<Ticket>)tickets).moonrise$copy());
}
} finally {
this.ticketLockArea.unlock(ticketLock);
@@ -474,16 +508,16 @@ public final class ChunkHolderManager {
}
}
private static int getTicketLevelAt(SortedArraySet<Ticket<?>> tickets) {
private static int getTicketLevelAt(final SortedArraySet<Ticket> tickets) {
return !tickets.isEmpty() ? tickets.first().getTicketLevel() : MAX_TICKET_LEVEL + 1;
}
public <T> boolean addTicketAtLevel(final TicketType<T> type, final ChunkPos chunkPos, final int level,
public <T> boolean addTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level,
final T identifier) {
return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier);
}
public <T> boolean addTicketAtLevel(final TicketType<T> type, final int chunkX, final int chunkZ, final int level,
public <T> boolean addTicketAtLevel(final TicketType type, final int chunkX, final int chunkZ, final int level,
final T identifier) {
return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkX, chunkZ), level, identifier);
}
@@ -524,29 +558,29 @@ public final class ChunkHolderManager {
// supposed to return true if the ticket was added and did not replace another
// but, we always return false if the ticket cannot be added
public <T> boolean addTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier) {
public <T> boolean addTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) {
return this.addTicketAtLevel(type, chunk, level, identifier, true);
}
<T> boolean addTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier, final boolean lock) {
final long removeDelay = type.timeout <= 0 ? NO_TIMEOUT_MARKER : type.timeout;
<T> boolean addTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier, final boolean lock) {
final long removeDelay = type.timeout() <= 0 ? NO_TIMEOUT_MARKER : type.timeout();
if (level > MAX_TICKET_LEVEL) {
return false;
}
final int chunkX = CoordinateUtils.getChunkX(chunk);
final int chunkZ = CoordinateUtils.getChunkZ(chunk);
final Ticket<T> ticket = new Ticket<>(type, level, identifier);
((ChunkSystemTicket<T>)(Object)ticket).moonrise$setRemoveDelay(removeDelay);
final Ticket ticket = new Ticket(type, level, removeDelay);
((ChunkSystemTicket<T>)(Object)ticket).moonrise$setIdentifier(identifier);
final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null;
try {
final SortedArraySet<Ticket<?>> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> {
return SortedArraySet.create(4);
final SortedArraySet<Ticket> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> {
return (SortedArraySet)SortedArraySet.create(4);
});
final int levelBefore = getTicketLevelAt(ticketsAtChunk);
final Ticket<T> current = (Ticket<T>)((ChunkSystemSortedArraySet<Ticket<?>>)ticketsAtChunk).moonrise$replace(ticket);
final Ticket current = (Ticket)((ChunkSystemSortedArraySet<Ticket>)ticketsAtChunk).moonrise$replace(ticket);
final int levelAfter = getTicketLevelAt(ticketsAtChunk);
if (current != ticket) {
@@ -563,6 +597,7 @@ public final class ChunkHolderManager {
if (removeDelay != NO_TIMEOUT_MARKER) {
this.addExpireCount(chunkX, chunkZ);
}
this.addTicketCounter(type, chunk);
}
if (levelBefore != levelAfter) {
@@ -577,36 +612,85 @@ public final class ChunkHolderManager {
}
}
public <T> boolean removeTicketAtLevel(final TicketType<T> type, final ChunkPos chunkPos, final int level, final T identifier) {
private void addTicketCounter(final TicketType type, final long pos) {
final long[] counterTypes = ((ChunkSystemTicketType<?>)(Object)type).moonrise$getCounterTypes();
if (counterTypes.length == 0) {
return;
}
synchronized (this.ticketCounters) {
for (final long counterType : counterTypes) {
final Long2IntOpenHashMap oldCounters = this.ticketCounters.get(counterType);
final Long2IntOpenHashMap newCounters = oldCounters == null ? new Long2IntOpenHashMap() : oldCounters.clone();
newCounters.addTo(pos, 1);
this.ticketCounters.put(counterType, newCounters);
}
}
}
private void removeTicketCounter(final TicketType type, final long pos) {
final long[] counterTypes = ((ChunkSystemTicketType<?>)(Object)type).moonrise$getCounterTypes();
if (counterTypes.length == 0) {
return;
}
synchronized (this.ticketCounters) {
for (final long counterType : counterTypes) {
final Long2IntOpenHashMap oldCounters = this.ticketCounters.get(counterType);
final Long2IntOpenHashMap newCounters = oldCounters == null ? new Long2IntOpenHashMap() : oldCounters.clone();
final int currCount = newCounters.get(pos);
if (currCount <= 0) {
throw new IllegalStateException("Count must be > 0 at this stage");
}
if (currCount == 1) {
newCounters.remove(pos);
} else {
newCounters.put(pos, currCount - 1);
}
this.ticketCounters.put(counterType, newCounters);
}
}
}
public Long2IntOpenHashMap getTicketCounters(final long counterType) {
return this.ticketCounters.get(counterType);
}
public <T> boolean removeTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, final T identifier) {
return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier);
}
public <T> boolean removeTicketAtLevel(final TicketType<T> type, final int chunkX, final int chunkZ, final int level, final T identifier) {
public <T> boolean removeTicketAtLevel(final TicketType type, final int chunkX, final int chunkZ, final int level, final T identifier) {
return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkX, chunkZ), level, identifier);
}
public <T> boolean removeTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier) {
public <T> boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) {
return this.removeTicketAtLevel(type, chunk, level, identifier, true);
}
<T> boolean removeTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier, final boolean lock) {
<T> boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier, final boolean lock) {
if (level > MAX_TICKET_LEVEL) {
return false;
}
final int chunkX = CoordinateUtils.getChunkX(chunk);
final int chunkZ = CoordinateUtils.getChunkZ(chunk);
final Ticket<T> probe = new Ticket<>(type, level, identifier);
final Ticket probe = new Ticket(type, level, 0L);
((ChunkSystemTicket<T>)(Object)probe).moonrise$setIdentifier(identifier);
final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null;
try {
final SortedArraySet<Ticket<?>> ticketsAtChunk = this.tickets.get(chunk);
final SortedArraySet<Ticket> ticketsAtChunk = this.tickets.get(chunk);
if (ticketsAtChunk == null) {
return false;
}
final int oldLevel = getTicketLevelAt(ticketsAtChunk);
final Ticket<T> ticket = (Ticket<T>)((ChunkSystemSortedArraySet<Ticket<?>>)ticketsAtChunk).moonrise$removeAndGet(probe);
final Ticket ticket = (Ticket)((ChunkSystemSortedArraySet<Ticket>)ticketsAtChunk).moonrise$removeAndGet(probe);
if (ticket == null) {
return false;
@@ -615,8 +699,7 @@ public final class ChunkHolderManager {
final int newLevel = getTicketLevelAt(ticketsAtChunk);
// we should not change the ticket levels while the target region may be ticking
if (oldLevel != newLevel) {
final Ticket<ChunkPos> unknownTicket = new Ticket<>(TicketType.UNKNOWN, level, new ChunkPos(chunk));
((ChunkSystemTicket<ChunkPos>)(Object)unknownTicket).moonrise$setRemoveDelay(Math.max(1, TicketType.UNKNOWN.timeout));
final Ticket unknownTicket = new Ticket(TicketType.UNKNOWN, level);
if (ticketsAtChunk.add(unknownTicket)) {
this.addExpireCount(chunkX, chunkZ);
} else {
@@ -629,6 +712,8 @@ public final class ChunkHolderManager {
this.removeExpireCount(chunkX, chunkZ);
}
this.removeTicketCounter(type, chunk);
return true;
} finally {
if (ticketLock != null) {
@@ -638,8 +723,8 @@ public final class ChunkHolderManager {
}
// atomic with respect to all add/remove/addandremove ticket calls for the given chunk
public <T, V> void addAndRemoveTickets(final long chunk, final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
public <T, V> void addAndRemoveTickets(final long chunk, final TicketType addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) {
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk));
try {
this.addTicketAtLevel(addType, chunk, addLevel, addIdentifier, false);
@@ -650,8 +735,8 @@ public final class ChunkHolderManager {
}
// atomic with respect to all add/remove/addandremove ticket calls for the given chunk
public <T, V> boolean addIfRemovedTicket(final long chunk, final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
public <T, V> boolean addIfRemovedTicket(final long chunk, final TicketType addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) {
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk));
try {
if (this.removeTicketAtLevel(removeType, chunk, removeLevel, removeIdentifier, false)) {
@@ -664,7 +749,7 @@ public final class ChunkHolderManager {
}
}
public <T> void removeAllTicketsFor(final TicketType<T> ticketType, final int ticketLevel, final T ticketIdentifier) {
public <T> void removeAllTicketsFor(final TicketType ticketType, final int ticketLevel, final T ticketIdentifier) {
if (ticketLevel > MAX_TICKET_LEVEL) {
return;
}
@@ -710,7 +795,7 @@ public final class ChunkHolderManager {
final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift();
final Predicate<Ticket<?>> expireNow = (final Ticket<?> ticket) -> {
final Predicate<Ticket> expireNow = (final Ticket ticket) -> {
long removeDelay = ((ChunkSystemTicket<?>)(Object)ticket).moonrise$getRemoveDelay();
if (removeDelay == NO_TIMEOUT_MARKER) {
return false;
@@ -746,7 +831,7 @@ public final class ChunkHolderManager {
final long chunkKey = entry.getLongKey();
final int expireCount = entry.getIntValue();
final SortedArraySet<Ticket<?>> tickets = this.tickets.get(chunkKey);
final SortedArraySet<Ticket> tickets = this.tickets.get(chunkKey);
final int levelBefore = getTicketLevelAt(tickets);
final int sizeBefore = tickets.size();
@@ -1164,7 +1249,7 @@ public final class ChunkHolderManager {
this.removeChunkHolder(holder);
} else {
// add cooldown so the next unload check is not immediately next tick
this.addTicketAtLevel(UNLOAD_COOLDOWN, CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ), MAX_TICKET_LEVEL, Unit.INSTANCE, false);
this.addTicketAtLevel(UNLOAD_COOLDOWN, CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ), MAX_TICKET_LEVEL, null, false);
}
}
} finally {
@@ -1188,42 +1273,42 @@ public final class ChunkHolderManager {
public static record TicketOperation<T, V> (
TicketOperationType op, long chunkCoord,
TicketType<T> ticketType, int ticketLevel, T identifier,
TicketType<V> ticketType2, int ticketLevel2, V identifier2
TicketType ticketType, int ticketLevel, T identifier,
TicketType ticketType2, int ticketLevel2, V identifier2
) {
private TicketOperation(TicketOperationType op, long chunkCoord,
TicketType<T> ticketType, int ticketLevel, T identifier) {
TicketType ticketType, int ticketLevel, T identifier) {
this(op, chunkCoord, ticketType, ticketLevel, identifier, null, 0, null);
}
public static <T> TicketOperation<T, T> addOp(final ChunkPos chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
public static <T> TicketOperation<T, T> addOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) {
return addOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier);
}
public static <T> TicketOperation<T, T> addOp(final int chunkX, final int chunkZ, final TicketType<T> type, final int ticketLevel, final T identifier) {
public static <T> TicketOperation<T, T> addOp(final int chunkX, final int chunkZ, final TicketType type, final int ticketLevel, final T identifier) {
return addOp(CoordinateUtils.getChunkKey(chunkX, chunkZ), type, ticketLevel, identifier);
}
public static <T> TicketOperation<T, T> addOp(final long chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
public static <T> TicketOperation<T, T> addOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) {
return new TicketOperation<>(TicketOperationType.ADD, chunk, type, ticketLevel, identifier);
}
public static <T> TicketOperation<T, T> removeOp(final ChunkPos chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
public static <T> TicketOperation<T, T> removeOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) {
return removeOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier);
}
public static <T> TicketOperation<T, T> removeOp(final int chunkX, final int chunkZ, final TicketType<T> type, final int ticketLevel, final T identifier) {
public static <T> TicketOperation<T, T> removeOp(final int chunkX, final int chunkZ, final TicketType type, final int ticketLevel, final T identifier) {
return removeOp(CoordinateUtils.getChunkKey(chunkX, chunkZ), type, ticketLevel, identifier);
}
public static <T> TicketOperation<T, T> removeOp(final long chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
public static <T> TicketOperation<T, T> removeOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) {
return new TicketOperation<>(TicketOperationType.REMOVE, chunk, type, ticketLevel, identifier);
}
public static <T, V> TicketOperation<T, V> addIfRemovedOp(final long chunk,
final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
final TicketType addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) {
return new TicketOperation<>(
TicketOperationType.ADD_IF_REMOVED, chunk, addType, addLevel, addIdentifier,
removeType, removeLevel, removeIdentifier
@@ -1231,8 +1316,8 @@ public final class ChunkHolderManager {
}
public static <T, V> TicketOperation<T, V> addAndRemove(final long chunk,
final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
final TicketType addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) {
return new TicketOperation<>(
TicketOperationType.ADD_AND_REMOVE, chunk, addType, addLevel, addIdentifier,
removeType, removeLevel, removeIdentifier
@@ -1391,11 +1476,11 @@ public final class ChunkHolderManager {
final JsonArray allTicketsJson = new JsonArray();
ret.add("tickets", allTicketsJson);
for (final Iterator<ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.entryIterator();
for (final Iterator<ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket>>> iterator = this.tickets.entryIterator();
iterator.hasNext();) {
final ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket<?>>> coordinateTickets = iterator.next();
final ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket>> coordinateTickets = iterator.next();
final long coordinate = coordinateTickets.getKey();
final SortedArraySet<Ticket<?>> tickets = coordinateTickets.getValue();
final SortedArraySet<Ticket> tickets = coordinateTickets.getValue();
final JsonObject coordinateJson = new JsonObject();
allTicketsJson.add(coordinateJson);
@@ -1410,17 +1495,17 @@ public final class ChunkHolderManager {
// directly over the set using the iterator
// however, it also means we need to null-check the values, and there is a possibility that we _miss_ an
// entry OR iterate over an entry multiple times
for (final Object ticketUncasted : ((ChunkSystemSortedArraySet<Ticket<?>>)tickets).moonrise$copyBackingArray()) {
for (final Object ticketUncasted : ((ChunkSystemSortedArraySet<Ticket>)tickets).moonrise$copyBackingArray()) {
if (ticketUncasted == null) {
continue;
}
final Ticket<?> ticket = (Ticket<?>)ticketUncasted;
final Ticket ticket = (Ticket)ticketUncasted;
final JsonObject ticketSerialized = new JsonObject();
ticketsSerialized.add(ticketSerialized);
ticketSerialized.addProperty("type", ticket.getType().toString());
ticketSerialized.addProperty("level", Integer.valueOf(ticket.getTicketLevel()));
ticketSerialized.addProperty("identifier", Objects.toString(ticket.key));
ticketSerialized.addProperty("identifier", Objects.toString(((ChunkSystemTicket<?>)(Object)ticket).moonrise$getIdentifier()));
ticketSerialized.addProperty("remove_tick", Long.valueOf(((ChunkSystemTicket<?>)(Object)ticket).moonrise$getRemoveDelay()));
}
}

View File

@@ -22,6 +22,7 @@ import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkProgres
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.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -73,35 +74,35 @@ public final class ChunkTaskScheduler {
LOGGER.info("Chunk system is using population gen parallelism: " + useParallelGen);
}
public static final TicketType<Long> CHUNK_LOAD = TicketType.create("chunk_system:chunk_load", Long::compareTo);
public static final TicketType CHUNK_LOAD = ChunkSystemTicketType.create("chunk_system:chunk_load", Long::compareTo);
private static final AtomicLong CHUNK_LOAD_IDS = new AtomicLong();
public static Long getNextChunkLoadId() {
return Long.valueOf(CHUNK_LOAD_IDS.getAndIncrement());
}
public static final TicketType<Long> NON_FULL_CHUNK_LOAD = TicketType.create("chunk_system:non_full_load", Long::compareTo);
public static final TicketType NON_FULL_CHUNK_LOAD = ChunkSystemTicketType.create("chunk_system:non_full_load", Long::compareTo);
private static final AtomicLong NON_FULL_CHUNK_LOAD_IDS = new AtomicLong();
public static Long getNextNonFullLoadId() {
return Long.valueOf(NON_FULL_CHUNK_LOAD_IDS.getAndIncrement());
}
public static final TicketType<Long> ENTITY_LOAD = TicketType.create("chunk_system:entity_load", Long::compareTo);
public static final TicketType ENTITY_LOAD = ChunkSystemTicketType.create("chunk_system:entity_load", Long::compareTo);
private static final AtomicLong ENTITY_LOAD_IDS = new AtomicLong();
public static Long getNextEntityLoadId() {
return Long.valueOf(ENTITY_LOAD_IDS.getAndIncrement());
}
public static final TicketType<Long> POI_LOAD = TicketType.create("chunk_system:poi_load", Long::compareTo);
public static final TicketType POI_LOAD = ChunkSystemTicketType.create("chunk_system:poi_load", Long::compareTo);
private static final AtomicLong POI_LOAD_IDS = new AtomicLong();
public static Long getNextPoiLoadId() {
return Long.valueOf(POI_LOAD_IDS.getAndIncrement());
}
public static final TicketType<Long> CHUNK_RELIGHT = TicketType.create("starlight:chunk_relight", Long::compareTo);
public static final TicketType CHUNK_RELIGHT = ChunkSystemTicketType.create("starlight:chunk_relight", Long::compareTo);
private static final AtomicLong CHUNK_RELIGHT_IDS = new AtomicLong();
public static Long getNextChunkRelightId() {

View File

@@ -70,7 +70,7 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl
this.chunkHolder.replaceProtoChunk(new ImposterProtoChunk(chunk, false));
}
((ChunkSystemLevelChunk)chunk).moonrise$setChunkAndHolder(new ServerChunkCache.ChunkAndHolder(chunk, this.chunkHolder.vanillaChunkHolder));
((ChunkSystemLevelChunk)chunk).moonrise$setChunkHolder(this.chunkHolder);
final NewChunkHolder chunkHolder = this.chunkHolder;

View File

@@ -6,4 +6,8 @@ public interface ChunkSystemTicket<T> {
public void moonrise$setRemoveDelay(final long removeDelay);
public T moonrise$getIdentifier();
public void moonrise$setIdentifier(final T identifier);
}

View File

@@ -0,0 +1,11 @@
package ca.spottedleaf.moonrise.patches.chunk_system.ticket;
import net.minecraft.server.level.ChunkMap;
public interface ChunkSystemTicketStorage {
public ChunkMap moonrise$getChunkMap();
public void moonrise$setChunkMap(final ChunkMap chunkMap);
}

View File

@@ -0,0 +1,33 @@
package ca.spottedleaf.moonrise.patches.chunk_system.ticket;
import net.minecraft.server.level.TicketType;
import java.util.Comparator;
public interface ChunkSystemTicketType<T> {
public static final long COUNTER_TYPE_FORCED = 0L;
// used only by neoforge
public static final long COUNTER_TYPER_NATURAL_SPAWNING_FORCED = 1L;
public static <T> TicketType create(final String name, final Comparator<T> identifierComparator) {
return create(name, identifierComparator, 0L);
}
public static <T> TicketType create(final String name, final Comparator<T> identifierComparator, final long timeout) {
// note: cannot persist unless registered
final TicketType ret = new TicketType(timeout, false, TicketType.TicketUse.LOADING_AND_SIMULATION);
((ChunkSystemTicketType<T>)(Object)ret).moonrise$setIdentifierComparator(identifierComparator);
return ret;
}
public long moonrise$getId();
public Comparator<T> moonrise$getIdentifierComparator();
public void moonrise$setIdentifierComparator(final Comparator<T> comparator);
public long[] moonrise$getCounterTypes();
}

View File

@@ -3,5 +3,13 @@ package ca.spottedleaf.moonrise.patches.chunk_tick_iteration;
public final class ChunkTickConstants {
public static final int PLAYER_SPAWN_TRACK_RANGE = 8;
// the smallest distance on x/z is at 45 degrees, we need to subtract 0.5 since this is calculated from chunk center and not chunk perimeter
// note: vanilla does not subtract 0.5 but the result is (luckily!) the same
public static final int NARROW_SPAWN_TRACK_RANGE = (int)Math.floor(((double)PLAYER_SPAWN_TRACK_RANGE / Math.sqrt(2.0)) - 0.5);
static {
if (NARROW_SPAWN_TRACK_RANGE < 0) {
throw new IllegalStateException();
}
}
}

View File

@@ -13,4 +13,6 @@ public interface ChunkTickDistanceManager {
final SectionPos oldPos, final SectionPos newPos,
final boolean oldIgnore, final boolean newIgnore);
public boolean moonrise$hasAnyNearbyNarrow(final int chunkX, final int chunkZ);
}

View File

@@ -6,7 +6,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
public interface ChunkTickServerLevel {
public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getPlayerTickingChunks();
public ReferenceList<LevelChunk> moonrise$getPlayerTickingChunks();
public void moonrise$markChunkForPlayerTicking(final LevelChunk chunk);

View File

@@ -2004,11 +2004,10 @@ public final class CollisionUtil {
VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantContextCollisionShape();
if (edgeCount == 0 || ((edgeCount != 1 || blockData.hasLargeCollisionShape()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON))) {
if (useEntityCollisionShape) {
mutablePos.set(blockX, blockY, blockZ);
if (useEntityCollisionShape) {
blockCollision = collisionShape.getCollisionShape(blockData, world, mutablePos);
} else if (blockCollision == null) {
mutablePos.set(blockX, blockY, blockZ);
blockCollision = blockData.getCollisionShape(world, mutablePos, collisionShape);
}
@@ -2020,7 +2019,6 @@ public final class CollisionUtil {
}
if (predicate != null) {
mutablePos.set(blockX, blockY, blockZ);
if (!predicate.test(blockData, mutablePos)) {
continue;
}
@@ -2046,7 +2044,6 @@ public final class CollisionUtil {
}
if (predicate != null) {
mutablePos.set(blockX, blockY, blockZ);
if (!predicate.test(blockData, mutablePos)) {
continue;
}
@@ -2126,7 +2123,7 @@ public final class CollisionUtil {
private boolean delegated;
public LazyEntityCollisionContext(final Entity entity) {
super(false, 0.0, null, null, entity);
super(false, false, 0.0, null, null, entity);
}
public static boolean useEntityCollisionShape(final Level world, final Entity entity) {
@@ -2156,6 +2153,11 @@ public final class CollisionUtil {
return this.getDelegate().isDescending();
}
@Override
public boolean isPlacement() {
return this.getDelegate().isPlacement();
}
@Override
public boolean isAbove(final VoxelShape shape, final BlockPos pos, final boolean defaultValue) {
return this.getDelegate().isAbove(shape, pos, defaultValue);

View File

@@ -182,7 +182,7 @@ public abstract class StarLightEngine {
for (int dx = -radius; dx <= radius; ++dx) {
final int cx = centerChunkX + dx;
final int cz = centerChunkZ + dz;
final boolean isTwoRadius = Math.max(IntegerUtil.branchlessAbs(dx), IntegerUtil.branchlessAbs(dz)) == 2;
final boolean isTwoRadius = Math.max(Math.abs(dx), Math.abs(dz)) == 2;
final ChunkAccess chunk = (ChunkAccess)chunkProvider.getChunkForLighting(cx, cz);
if (chunk == null) {

View File

@@ -9,6 +9,7 @@ import ca.spottedleaf.moonrise.common.util.WorldUtil;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkStatus;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.shorts.ShortCollection;
@@ -39,10 +40,8 @@ import java.util.function.IntConsumer;
public final class StarLightInterface {
public static final TicketType<Long> CHUNK_WORK_TICKET = TicketType.create("starlight:chunk_work_ticket", Long::compareTo);
public static final TicketType CHUNK_WORK_TICKET = ChunkSystemTicketType.create("starlight:chunk_work_ticket", Long::compareTo);
public static final int LIGHT_TICKET_LEVEL = ChunkLevel.byStatus(ChunkStatus.LIGHT);
// ticket level = ChunkLevel.byStatus(FullChunkStatus.FULL) - input
public static final int REGION_LIGHT_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.FULL) - LIGHT_TICKET_LEVEL;
/**
* Can be {@code null}, indicating the light is all empty.

View File

@@ -56,15 +56,18 @@ public final class SaveUtil {
tag.putBoolean("isLightOn", false);
}
// diff end - store our tag for whether light data is init'd
ChunkStatus status = ChunkStatus.byName(tag.getString("Status"));
ChunkStatus status = tag.read("Status", ChunkStatus.CODEC).orElse(ChunkStatus.EMPTY);
CompoundTag[] sections = new CompoundTag[maxSection - minSection + 1];
ListTag sectionsStored = tag.getList("sections", 10);
ListTag sectionsStored = tag.getListOrEmpty("sections");
for (int i = 0; i < sectionsStored.size(); ++i) {
CompoundTag sectionStored = sectionsStored.getCompound(i);
int k = sectionStored.getByte("Y");
CompoundTag sectionStored = sectionsStored.getCompound(i).orElse(null);
if (sectionStored == null) {
continue;
}
int k = sectionStored.getByteOr("Y", (byte)0);
// strip light data
sectionStored.remove("BlockLight");
@@ -147,33 +150,38 @@ public final class SaveUtil {
// start copy from the original method
boolean lit = tag.get("isLightOn") != null && tag.getInt(STARLIGHT_VERSION_TAG) == STARLIGHT_LIGHT_VERSION;
boolean lit = tag.get("isLightOn") != null && tag.getIntOr(STARLIGHT_VERSION_TAG, -1) == STARLIGHT_LIGHT_VERSION;
boolean canReadSky = world.dimensionType().hasSkyLight();
ChunkStatus status = ChunkStatus.byName(tag.getString("Status"));
ChunkStatus status = tag.read("Status", ChunkStatus.CODEC).orElse(ChunkStatus.EMPTY);
if (lit && status.isOrAfter(ChunkStatus.LIGHT)) { // diff - we add the status check here
ListTag sections = tag.getList("sections", 10);
ListTag sections = tag.getListOrEmpty("sections");
for (int i = 0; i < sections.size(); ++i) {
CompoundTag sectionData = sections.getCompound(i);
int y = sectionData.getByte("Y");
CompoundTag sectionData = sections.getCompound(i).orElse(null);
if (sectionData == null) {
continue;
}
int y = sectionData.getByteOr("Y", (byte)0);
if (sectionData.contains("BlockLight", 7)) {
final byte[] blockLight = sectionData.getByteArray("BlockLight").orElse(null);
if (blockLight != null) {
// this is where our diff is
blockNibbles[y - minSection] = new SWMRNibbleArray(sectionData.getByteArray("BlockLight").clone(), sectionData.getInt(BLOCKLIGHT_STATE_TAG)); // clone for data safety
blockNibbles[y - minSection] = new SWMRNibbleArray(blockLight.clone(), sectionData.getIntOr(BLOCKLIGHT_STATE_TAG, 0)); // clone for data safety
} else {
blockNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getInt(BLOCKLIGHT_STATE_TAG));
blockNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getIntOr(BLOCKLIGHT_STATE_TAG, 0));
}
if (canReadSky) {
if (sectionData.contains("SkyLight", 7)) {
final byte[] skyLight = sectionData.getByteArray("SkyLight").orElse(null);
if (skyLight != null) {
// we store under the same key so mod programs editing nbt
// can still read the data, hopefully.
// however, for compatibility we store chunks as unlit so vanilla
// is forced to re-light them if it encounters our data. It's too much of a burden
// to try and maintain compatibility with a broken and inferior skylight management system.
skyNibbles[y - minSection] = new SWMRNibbleArray(sectionData.getByteArray("SkyLight").clone(), sectionData.getInt(SKYLIGHT_STATE_TAG)); // clone for data safety
skyNibbles[y - minSection] = new SWMRNibbleArray(skyLight.clone(), sectionData.getIntOr(SKYLIGHT_STATE_TAG, 0)); // clone for data safety
} else {
skyNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getInt(SKYLIGHT_STATE_TAG));
skyNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getIntOr(SKYLIGHT_STATE_TAG, 0));
}
}
}

View File

@@ -194,9 +194,8 @@ accessible class net/minecraft/server/level/ChunkMap$DistanceManager
# DistanceManager
mutable field net/minecraft/server/level/DistanceManager playersPerChunk Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;
mutable field net/minecraft/server/level/DistanceManager tickets Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;
mutable field net/minecraft/server/level/DistanceManager ticketTracker Lnet/minecraft/server/level/DistanceManager$ChunkTicketTracker;
mutable field net/minecraft/server/level/DistanceManager tickingTicketsTracker Lnet/minecraft/server/level/TickingTracker;
mutable field net/minecraft/server/level/DistanceManager loadingChunkTracker Lnet/minecraft/server/level/LoadingChunkTracker;
mutable field net/minecraft/server/level/DistanceManager simulationChunkTracker Lnet/minecraft/server/level/SimulationChunkTracker;
mutable field net/minecraft/server/level/DistanceManager playerTicketManager Lnet/minecraft/server/level/DistanceManager$PlayerTicketTracker;
mutable field net/minecraft/server/level/DistanceManager chunksToUpdateFutures Ljava/util/Set;
mutable field net/minecraft/server/level/DistanceManager ticketDispatcher Lnet/minecraft/server/level/ThrottlingChunkTaskDispatcher;
@@ -205,10 +204,6 @@ mutable field net/minecraft/server/level/DistanceManager mainThreadExecutor Ljav
mutable field net/minecraft/server/level/DistanceManager naturalSpawnChunkCounter Lnet/minecraft/server/level/DistanceManager$FixedPlayerDistanceChunkTracker;
# DistanceManager$ChunkTicketTracker
accessible class net/minecraft/server/level/DistanceManager$ChunkTicketTracker
# DistanceManager$PlayerTicketTracker
accessible class net/minecraft/server/level/DistanceManager$PlayerTicketTracker
@@ -217,11 +212,6 @@ accessible class net/minecraft/server/level/DistanceManager$PlayerTicketTracker
accessible class net/minecraft/server/level/DistanceManager$FixedPlayerDistanceChunkTracker
# Ticket
accessible field net/minecraft/server/level/Ticket key Ljava/lang/Object;
accessible field net/minecraft/server/level/TicketType timeout J
# ServerChunkCache
accessible method net/minecraft/server/level/ServerChunkCache runDistanceManagerUpdates ()Z
accessible field net/minecraft/server/level/ServerChunkCache level Lnet/minecraft/server/level/ServerLevel;
@@ -241,14 +231,6 @@ accessible class net/minecraft/server/level/ServerLevel$EntityCallbacks
accessible method net/minecraft/server/level/ServerLevel$EntityCallbacks <init> (Lnet/minecraft/server/level/ServerLevel;)V
# EntityStorage
accessible method net/minecraft/world/level/chunk/storage/EntityStorage readChunkPos (Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/level/ChunkPos;
accessible method net/minecraft/world/level/chunk/storage/EntityStorage writeChunkPos (Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/ChunkPos;)V
# Ticket
accessible method net/minecraft/server/level/Ticket <init> (Lnet/minecraft/server/level/TicketType;ILjava/lang/Object;)V
# ChunkStorage
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
mutable field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -285,11 +267,6 @@ accessible class net/minecraft/server/level/ChunkMap$TrackedEntity
accessible field net/minecraft/server/level/ChunkMap$TrackedEntity serverEntity Lnet/minecraft/server/level/ServerEntity;
# ServerChunkCache$ChunkAndHolder
accessible class net/minecraft/server/level/ServerChunkCache$ChunkAndHolder
accessible method net/minecraft/server/level/ServerChunkCache$ChunkAndHolder <init> (Lnet/minecraft/world/level/chunk/LevelChunk;Lnet/minecraft/server/level/ChunkHolder;)V
# LevelLoadStatusManager$Status
accessible class net/minecraft/client/multiplayer/LevelLoadStatusManager$Status
@@ -314,3 +291,15 @@ accessible class net/minecraft/world/level/LocalMobCapCalculator$MobCounts
accessible class net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk
# MDG requires we AT the constructor if we AT the class
accessible method net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk <init> (Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;Z)V
# Ticket
accessible method net/minecraft/server/level/Ticket <init> (Lnet/minecraft/server/level/TicketType;IJ)V
# LoadingChunkTracker
accessible class net/minecraft/server/level/LoadingChunkTracker
# TicketStorage
mutable field net/minecraft/world/level/TicketStorage tickets Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;

View File

@@ -52,6 +52,8 @@
"chunk_system.StructureCheckMixin",
"chunk_system.StructureTemplate$PaletteMixin",
"chunk_system.TicketMixin",
"chunk_system.TicketStorageMixin",
"chunk_system.TicketTypeMixin",
"chunk_tick_iteration.ChunkMapMixin",
"chunk_tick_iteration.DistanceManagerMixin",
"chunk_tick_iteration.ServerChunkCacheMixin",