diff --git a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/FabricHooks.java b/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/FabricHooks.java index dd4f0aa..740ceb6 100644 --- a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/FabricHooks.java +++ b/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/FabricHooks.java @@ -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; + } } diff --git a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/chunk_system/FabricDistanceManagerMixin.java b/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/chunk_system/FabricDistanceManagerMixin.java deleted file mode 100644 index b4debbc..0000000 --- a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/mixin/chunk_system/FabricDistanceManagerMixin.java +++ /dev/null @@ -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 void addRegionTicket(final TicketType 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 void removeRegionTicket(final TicketType type, final ChunkPos pos, final int radius, final T identifier) { - this.moonrise$getChunkHolderManager().removeTicketAtLevel(type, pos, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, identifier); - } - -} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index a8a9571..dbc6864 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -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": { diff --git a/fabric/src/main/resources/moonrise-fabric.mixins.json b/fabric/src/main/resources/moonrise-fabric.mixins.json index 268ddbf..076b4ed 100644 --- a/fabric/src/main/resources/moonrise-fabric.mixins.json +++ b/fabric/src/main/resources/moonrise-fabric.mixins.json @@ -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" diff --git a/gradle.properties b/gradle.properties index 8b5eb7e..d8d5a63 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/NeoForgeHooks.java b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/NeoForgeHooks.java index 36fab0f..b2929bd 100644 --- a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/NeoForgeHooks.java +++ b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/NeoForgeHooks.java @@ -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(); + } } diff --git a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/chunk_system/NeoForgeDistanceManagerMixin.java b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/chunk_system/NeoForgeDistanceManagerMixin.java deleted file mode 100644 index f5cddc2..0000000 --- a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/chunk_system/NeoForgeDistanceManagerMixin.java +++ /dev/null @@ -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>> forcedTickets; - - /** - * @reason Route to new chunk system - * @author Spottedleaf - */ - @Overwrite - public void addRegionTicket(final TicketType 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 forceTicket = new Ticket<>(type, level, identifier, forceTicks); - - this.forcedTickets.compute(pos.toLong(), (final Long keyInMap, final SortedArraySet> valueInMap) -> { - final SortedArraySet> 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 void removeRegionTicket(final TicketType 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 forceTicket = new Ticket<>(type, level, identifier, forceTicks); - - this.forcedTickets.computeIfPresent(pos.toLong(), (final Long keyInMap, final SortedArraySet> 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); - } -} diff --git a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/chunk_system/NeoForgeTicketStorageMixin.java b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/chunk_system/NeoForgeTicketStorageMixin.java new file mode 100644 index 0000000..147033a --- /dev/null +++ b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/mixin/chunk_system/NeoForgeTicketStorageMixin.java @@ -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 = "(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 = "(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)); + } +} diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml index 3ee9181..e17873d 100644 --- a/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -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" diff --git a/neoforge/src/main/resources/moonrise-neoforge.mixins.json b/neoforge/src/main/resources/moonrise-neoforge.mixins.json index 01a85dc..835abbd 100644 --- a/neoforge/src/main/resources/moonrise-neoforge.mixins.json +++ b/neoforge/src/main/resources/moonrise-neoforge.mixins.json @@ -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": [ diff --git a/settings.gradle b/settings.gradle index 1067e59..f7f11c9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -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 { diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java b/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java index c21e008..ece6db7 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/list/IteratorSafeOrderedReferenceSet.java @@ -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 { private int iteratorCount; public IteratorSafeOrderedReferenceSet() { - this(16, 0.75f, 16, 0.2); + this(Object.class); + } + + public IteratorSafeOrderedReferenceSet(final Class 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 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 { 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 { } } - return -1; + return Integer.MAX_VALUE; } public void finishRawIterator() { @@ -205,10 +225,6 @@ public final class IteratorSafeOrderedReferenceSet { //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(); diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/PositionCountingAreaMap.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/PositionCountingAreaMap.java index 9056076..09b1892 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/misc/PositionCountingAreaMap.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/PositionCountingAreaMap.java @@ -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 { 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 { @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); } diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java index 94689e0..7e85bb5 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java @@ -1,7 +1,5 @@ package ca.spottedleaf.moonrise.common.misc; -import ca.spottedleaf.concurrentutil.util.IntegerUtil; - public abstract class SingleUserAreaMap { public static final int NOT_SET = Integer.MIN_VALUE; @@ -99,8 +97,8 @@ public abstract class SingleUserAreaMap { 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 { 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 { 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); } } diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/BaseChunkSystemHooks.java b/src/main/java/ca/spottedleaf/moonrise/common/util/BaseChunkSystemHooks.java index b9636cb..885bf35 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/BaseChunkSystemHooks.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/BaseChunkSystemHooks.java @@ -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 diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystemHooks.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystemHooks.java index 427079a..15a3c24 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystemHooks.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystemHooks.java @@ -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); } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/block_entity_remove/LevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/block_entity_remove/LevelMixin.java index a0dd198..26c82a6 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/block_entity_remove/LevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/block_entity_remove/LevelMixin.java @@ -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(); } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/blockstate_propertyaccess/StateHolderMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/blockstate_propertyaccess/StateHolderMixin.java index ba1e27f..1e407e9 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/blockstate_propertyaccess/StateHolderMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/blockstate_propertyaccess/StateHolderMixin.java @@ -125,7 +125,7 @@ abstract class StateHolderMixin implements PropertyAccessStateHolder { * @author Spottedleaf */ @Overwrite - public > T getNullableValue(Property property) { + public > T getNullableValue(final Property property) { return property == null ? null : this.optimisedTable.get(this.tableIndex, property); } @@ -166,7 +166,7 @@ abstract class StateHolderMixin implements PropertyAccessStateHolder { */ @Overwrite public Map, Comparable> getValues() { - ZeroCollidingReferenceStateTable table = this.optimisedTable; + final ZeroCollidingReferenceStateTable table = this.optimisedTable; // We have to use this.values until the table is loaded return table.isLoaded() ? table.getMapView(this.tableIndex) : this.values; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java index a6906d4..3d628ec 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkHolderMixin.java @@ -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) { diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMap$DistanceManagerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMap$DistanceManagerMixin.java index 7d41abb..89b1a28 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMap$DistanceManagerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMap$DistanceManagerMixin.java @@ -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_); } /** diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java index f86cbf5..de7a7f3 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ChunkMapMixin.java @@ -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 arg4, - LightChunkGetter arg5, ChunkGenerator arg6, ChunkProgressListener arg7, - ChunkStatusUpdateListener arg8, Supplier 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 redirectChunkHolderGet(final Long2ObjectLinkedOpenHashMap instance, final long key) { + private V redirectChunkHolderGetForSpawning(final Long2ObjectLinkedOpenHashMap 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 redirectChunkHolderGetForBlockTicking(final Long2ObjectLinkedOpenHashMap instance, final long key) { return (V)this.getVisibleChunkIfPresent(key); } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DistanceManagerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DistanceManagerMixin.java index 0f3e3b7..9b580f4 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DistanceManagerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DistanceManagerMixin.java @@ -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>> 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> 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 void skipTickingTicketTrackerAdd(final TickingTracker instance, final TicketType 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 void skipTickingTicketTrackerRemove(final TickingTracker instance, final TicketType 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 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"; } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DynamicGameEventListenerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DynamicGameEventListenerMixin.java index ed0c3ba..5b0c234 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DynamicGameEventListenerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/DynamicGameEventListenerMixin.java @@ -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. diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityMixin.java index 9abf738..f446f1f 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityMixin.java @@ -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 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(); diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityTickListMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityTickListMixin.java index 0675292..d765b19 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityTickListMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/EntityTickListMixin.java @@ -25,7 +25,7 @@ abstract class EntityTickListMixin { private Int2ObjectMap passive; @Unique - private final IteratorSafeOrderedReferenceSet entities = new IteratorSafeOrderedReferenceSet<>(); + private final IteratorSafeOrderedReferenceSet entities = new IteratorSafeOrderedReferenceSet<>(Entity.class); /** * @reason Initialise new fields and destroy old state diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkMixin.java index bb44d7c..2f5a684 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkMixin.java @@ -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; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkTicksMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkTicksMixin.java index e8cbe69..3efd906 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkTicksMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/LevelChunkTicksMixin.java @@ -105,12 +105,12 @@ abstract class LevelChunkTicksMixin 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 idFunction, final CallbackInfoReturnable cir) { + private void saveHook(final long time, final CallbackInfoReturnable cir) { this.lastSaved = time; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/MinecraftServerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/MinecraftServerMixin.java index df36220..f2505e1 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/MinecraftServerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/MinecraftServerMixin.java @@ -190,6 +190,11 @@ abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop instance, final Predicate 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 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); + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java index 9c4992a..c0ccf92 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java @@ -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 loadedChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS); + private final ReferenceList loadedChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); @Unique - private final ReferenceList tickingChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS); + private final ReferenceList tickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); @Unique - private final ReferenceList entityTickingChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS); + private final ReferenceList 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 moonrise$getLoadedChunks() { + public final ReferenceList moonrise$getLoadedChunks() { return this.loadedChunks; } @Override - public final ReferenceList moonrise$getTickingChunks() { + public final ReferenceList moonrise$getTickingChunks() { return this.tickingChunks; } @Override - public final ReferenceList moonrise$getEntityTickingChunks() { + public final ReferenceList 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 boolean redirectCanEntitiesSpawnTickCheck(final PersistentEntitySectionManager instance, final ChunkPos pos) { final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos)); return chunkHolder != null && chunkHolder.isEntityTickingReady(); } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/SortedArraySetMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/SortedArraySetMixin.java index 6ce6d56..c9498f6 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/SortedArraySetMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/SortedArraySetMixin.java @@ -49,8 +49,7 @@ abstract class SortedArraySetMixin extends AbstractSet 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 extends AbstractSet 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]; diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketMixin.java index 40335ca..6580da2 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketMixin.java @@ -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 implements ChunkSystemTicket, Comparable> { +abstract class TicketMixin implements ChunkSystemTicket, Comparable { @Shadow @Final - private TicketType 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)(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)(Object)this.type).moonrise$getId(), + ((ChunkSystemTicketType)(Object)((TicketMixin)(Object)ticket).type).moonrise$getId() + ); + if (typeCompare != 0) { + return typeCompare; + } + + final Comparator comparator = ((ChunkSystemTicketType)(Object)this.type).moonrise$getIdentifierComparator(); + return comparator == null ? 0 : comparator.compare(this.identifier, ((TicketMixin)(Object)ticket).identifier); } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketStorageMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketStorageMixin.java new file mode 100644 index 0000000..b405ce7 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketStorageMixin.java @@ -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> deactivatedTickets; + + @Shadow + private Long2ObjectOpenHashMap> 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 = "(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 = "(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 consumer, final Long2ObjectOpenHashMap> ticketsParam) { + if (ticketsParam != null) { + throw new IllegalStateException("Bad injection point"); + } + + final Long2ObjectOpenHashMap> tickets = ((ChunkSystemServerLevel)this.chunkMap.level) + .moonrise$getChunkTaskScheduler().chunkHolderManager.getTicketsCopy(); + + for (final Iterator>> iterator = tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { + final Long2ObjectMap.Entry> entry = iterator.next(); + + final long pos = entry.getLongKey(); + final SortedArraySet 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 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 predicate, + final Long2ObjectOpenHashMap> tickets) {} + + /** + * @reason Destroy old chunk system hooks + * @author Spottedleaf + */ + @Overwrite + public void removeTicketIf(final Predicate predicate, final Long2ObjectOpenHashMap> 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 predicate) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketTypeMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketTypeMixin.java new file mode 100644 index 0000000..3c690e4 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/TicketTypeMixin.java @@ -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 implements ChunkSystemTicketType { + + @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 = "", + 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 identifierComparator; + + @Unique + private volatile long[] counterTypes; + + @Override + public final long moonrise$getId() { + return this.id; + } + + @Override + public final Comparator moonrise$getIdentifierComparator() { + return this.identifierComparator; + } + + @Override + public final void moonrise$setIdentifierComparator(final Comparator 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); + } +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ChunkMapMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ChunkMapMixin.java index 0b2001c..20d8790 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ChunkMapMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ChunkMapMixin.java @@ -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 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 list, final CallbackInfo ci) { + final ReferenceList 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(); + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/DistanceManagerMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/DistanceManagerMixin.java index 70b0275..bf9a294 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/DistanceManagerMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/DistanceManagerMixin.java @@ -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 spawnChunkTracker = new PositionCountingAreaMap<>(); + @Unique + private final PositionCountingAreaMap 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; } /** diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerChunkCacheMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerChunkCacheMixin.java index 5024ee9..555d46d 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerChunkCacheMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerChunkCacheMixin.java @@ -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 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 list) { - final ReferenceList 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 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 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; + } + } + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerLevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerLevelMixin.java index 520cbd1..3fa9289 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerLevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_tick_iteration/ServerLevelMixin.java @@ -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 playerTickingChunks = new ReferenceList<>(EMPTY_PLAYER_CHUNK_HOLDERS); + private final ReferenceList playerTickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); @Unique private final Long2IntOpenHashMap playerTickingRequests = new Long2IntOpenHashMap(); @Override - public final ReferenceList moonrise$getPlayerTickingChunks() { + public final ReferenceList 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()); } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ShapesMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ShapesMixin.java index d8c305b..8c16cba 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ShapesMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ShapesMixin.java @@ -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; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/serverlist/ServerAddressResolverMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/serverlist/ServerAddressResolverMixin.java index e6dfe6f..539e902 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/serverlist/ServerAddressResolverMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/serverlist/ServerAddressResolverMixin.java @@ -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", diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java index 6f40688..9efde57 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/lightengine/ThreadedLevelLightEngineMixin.java @@ -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 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() ); } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/SerializableChunkDataMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/SerializableChunkDataMixin.java index 2f6f790..d83a266 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/SerializableChunkDataMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/starlight/world/SerializableChunkDataMixin.java @@ -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; diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java index 44bb255..f3f5a3f 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java @@ -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) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/datacontroller/EntityDataController.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/datacontroller/EntityDataController.java index 828c868..992d19e 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/datacontroller/EntityDataController.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/datacontroller/EntityDataController.java @@ -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() diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java index 9d46482..5f3d223 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/ChunkSystemServerLevel.java @@ -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 moonrise$getLoadedChunks(); + public ReferenceList moonrise$getLoadedChunks(); - public ReferenceList moonrise$getTickingChunks(); + public ReferenceList moonrise$getTickingChunks(); - public ReferenceList moonrise$getEntityTickingChunks(); + public ReferenceList moonrise$getEntityTickingChunks(); } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemLevelChunk.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemLevelChunk.java index 5b092bc..59cbbf6 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemLevelChunk.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/chunk/ChunkSystemLevelChunk.java @@ -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); } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java index 7aea4e3..1c82dcd 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java @@ -76,7 +76,7 @@ public final class ChunkEntitySlices { public static List 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; } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/poi/PoiChunk.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/poi/PoiChunk.java index bbf9d6c..8b5eede 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/poi/PoiChunk.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/poi/PoiChunk.java @@ -159,7 +159,7 @@ public final class PoiChunk { final RegistryOps 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 deserializeResult = PoiSection.Packed.CODEC.parse(registryOps, section); final int finalSectionY = sectionY; final PoiSection.Packed packed = deserializeResult.resultOrPartial((final String description) -> { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java index b3610f6..bc42f16 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java @@ -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 PLAYER_TICKET = TicketType.create("chunk_system:player_ticket", Long::compareTo); - public static final TicketType 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); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java index e4ff355..bf2ed2f 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java @@ -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 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>> tickets = new ConcurrentLong2ReferenceChainedHashTable<>(); + private final ConcurrentLong2ReferenceChainedHashTable> tickets = new ConcurrentLong2ReferenceChainedHashTable<>(); private final ConcurrentLong2ReferenceChainedHashTable sectionToChunkToExpireCount = new ConcurrentLong2ReferenceChainedHashTable<>(); final ChunkUnloadQueue unloadQueue; @@ -102,6 +103,8 @@ public final class ChunkHolderManager { return Long.compare(coord1, coord2); }); + private final ConcurrentLong2ReferenceChainedHashTable 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 getOldChunkHoldersIterable() { return new Iterable() { @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> tickets = this.tickets.get(coordinate); + final SortedArraySet tickets = this.tickets.get(coordinate); return tickets != null ? tickets.first().toString() : "no_ticket"; } finally { @@ -421,8 +423,40 @@ public final class ChunkHolderManager { } } - public Long2ObjectOpenHashMap>> getTicketsCopy() { - final Long2ObjectOpenHashMap>> ret = new Long2ObjectOpenHashMap<>(); + public boolean hasTickets() { + return !this.tickets.isEmpty(); + } + + public List 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 tickets = this.tickets.get(key); + + if (tickets == null) { + return new ArrayList<>(); + } + + final List ret = new ArrayList<>(tickets.size()); + + for (final Ticket ticket : tickets) { + ret.add(ticket); + } + + return ret; + } finally { + this.ticketLockArea.unlock(lock); + } + } + + public Long2ObjectOpenHashMap> getTicketsCopy() { + final Long2ObjectOpenHashMap> ret = new Long2ObjectOpenHashMap<>(); final Long2ObjectOpenHashMap 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> tickets = this.tickets.get(coord); + final SortedArraySet tickets = this.tickets.get(coord); if (tickets == null) { // removed before we acquired lock continue; } - ret.put(coord, ((ChunkSystemSortedArraySet>)tickets).moonrise$copy()); + ret.put(coord, ((ChunkSystemSortedArraySet)tickets).moonrise$copy()); } } finally { this.ticketLockArea.unlock(ticketLock); @@ -474,16 +508,16 @@ public final class ChunkHolderManager { } } - private static int getTicketLevelAt(SortedArraySet> tickets) { + private static int getTicketLevelAt(final SortedArraySet tickets) { return !tickets.isEmpty() ? tickets.first().getTicketLevel() : MAX_TICKET_LEVEL + 1; } - public boolean addTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, + public boolean addTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, final T identifier) { return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier); } - public boolean addTicketAtLevel(final TicketType type, final int chunkX, final int chunkZ, final int level, + public 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 boolean addTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) { + public boolean addTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) { return this.addTicketAtLevel(type, chunk, level, identifier, true); } - 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; + 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 ticket = new Ticket<>(type, level, identifier); - ((ChunkSystemTicket)(Object)ticket).moonrise$setRemoveDelay(removeDelay); + final Ticket ticket = new Ticket(type, level, removeDelay); + ((ChunkSystemTicket)(Object)ticket).moonrise$setIdentifier(identifier); final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null; try { - final SortedArraySet> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> { - return SortedArraySet.create(4); + final SortedArraySet ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> { + return (SortedArraySet)SortedArraySet.create(4); }); final int levelBefore = getTicketLevelAt(ticketsAtChunk); - final Ticket current = (Ticket)((ChunkSystemSortedArraySet>)ticketsAtChunk).moonrise$replace(ticket); + final Ticket current = (Ticket)((ChunkSystemSortedArraySet)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 boolean removeTicketAtLevel(final TicketType 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 boolean removeTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, final T identifier) { return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier); } - public boolean removeTicketAtLevel(final TicketType type, final int chunkX, final int chunkZ, final int level, final T identifier) { + public 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 boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) { + public boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) { return this.removeTicketAtLevel(type, chunk, level, identifier, true); } - boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier, final boolean lock) { + 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 probe = new Ticket<>(type, level, identifier); + final Ticket probe = new Ticket(type, level, 0L); + ((ChunkSystemTicket)(Object)probe).moonrise$setIdentifier(identifier); final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null; try { - final SortedArraySet> ticketsAtChunk = this.tickets.get(chunk); + final SortedArraySet ticketsAtChunk = this.tickets.get(chunk); if (ticketsAtChunk == null) { return false; } final int oldLevel = getTicketLevelAt(ticketsAtChunk); - final Ticket ticket = (Ticket)((ChunkSystemSortedArraySet>)ticketsAtChunk).moonrise$removeAndGet(probe); + final Ticket ticket = (Ticket)((ChunkSystemSortedArraySet)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 unknownTicket = new Ticket<>(TicketType.UNKNOWN, level, new ChunkPos(chunk)); - ((ChunkSystemTicket)(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 void addAndRemoveTickets(final long chunk, final TicketType addType, final int addLevel, final T addIdentifier, - final TicketType removeType, final int removeLevel, final V removeIdentifier) { + public 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 boolean addIfRemovedTicket(final long chunk, final TicketType addType, final int addLevel, final T addIdentifier, - final TicketType removeType, final int removeLevel, final V removeIdentifier) { + public 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 void removeAllTicketsFor(final TicketType ticketType, final int ticketLevel, final T ticketIdentifier) { + public 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> expireNow = (final Ticket ticket) -> { + final Predicate 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> tickets = this.tickets.get(chunkKey); + final SortedArraySet 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 ( TicketOperationType op, long chunkCoord, - TicketType ticketType, int ticketLevel, T identifier, - TicketType ticketType2, int ticketLevel2, V identifier2 + TicketType ticketType, int ticketLevel, T identifier, + TicketType ticketType2, int ticketLevel2, V identifier2 ) { private TicketOperation(TicketOperationType op, long chunkCoord, - TicketType ticketType, int ticketLevel, T identifier) { + TicketType ticketType, int ticketLevel, T identifier) { this(op, chunkCoord, ticketType, ticketLevel, identifier, null, 0, null); } - public static TicketOperation addOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) { + public static TicketOperation addOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) { return addOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier); } - public static TicketOperation addOp(final int chunkX, final int chunkZ, final TicketType type, final int ticketLevel, final T identifier) { + public static TicketOperation 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 TicketOperation addOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) { + public static TicketOperation addOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) { return new TicketOperation<>(TicketOperationType.ADD, chunk, type, ticketLevel, identifier); } - public static TicketOperation removeOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) { + public static TicketOperation removeOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) { return removeOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier); } - public static TicketOperation removeOp(final int chunkX, final int chunkZ, final TicketType type, final int ticketLevel, final T identifier) { + public static TicketOperation 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 TicketOperation removeOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) { + public static TicketOperation removeOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) { return new TicketOperation<>(TicketOperationType.REMOVE, chunk, type, ticketLevel, identifier); } public static TicketOperation addIfRemovedOp(final long chunk, - final TicketType addType, final int addLevel, final T addIdentifier, - final TicketType 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 TicketOperation addAndRemove(final long chunk, - final TicketType addType, final int addLevel, final T addIdentifier, - final TicketType 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>>> iterator = this.tickets.entryIterator(); + for (final Iterator>> iterator = this.tickets.entryIterator(); iterator.hasNext();) { - final ConcurrentLong2ReferenceChainedHashTable.TableEntry>> coordinateTickets = iterator.next(); + final ConcurrentLong2ReferenceChainedHashTable.TableEntry> coordinateTickets = iterator.next(); final long coordinate = coordinateTickets.getKey(); - final SortedArraySet> tickets = coordinateTickets.getValue(); + final SortedArraySet 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>)tickets).moonrise$copyBackingArray()) { + for (final Object ticketUncasted : ((ChunkSystemSortedArraySet)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())); } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java index eb77db5..05dcfa9 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java @@ -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 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 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 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 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 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() { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java index 6ab353b..96ccb8f 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java @@ -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; diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicket.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicket.java index 786e6ad..befc922 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicket.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicket.java @@ -6,4 +6,8 @@ public interface ChunkSystemTicket { public void moonrise$setRemoveDelay(final long removeDelay); + public T moonrise$getIdentifier(); + + public void moonrise$setIdentifier(final T identifier); + } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicketStorage.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicketStorage.java new file mode 100644 index 0000000..8942da3 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicketStorage.java @@ -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); + +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicketType.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicketType.java new file mode 100644 index 0000000..0c76e48 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ticket/ChunkSystemTicketType.java @@ -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 { + + public static final long COUNTER_TYPE_FORCED = 0L; + // used only by neoforge + public static final long COUNTER_TYPER_NATURAL_SPAWNING_FORCED = 1L; + + public static TicketType create(final String name, final Comparator identifierComparator) { + return create(name, identifierComparator, 0L); + } + + public static TicketType create(final String name, final Comparator identifierComparator, final long timeout) { + // note: cannot persist unless registered + final TicketType ret = new TicketType(timeout, false, TicketType.TicketUse.LOADING_AND_SIMULATION); + + ((ChunkSystemTicketType)(Object)ret).moonrise$setIdentifierComparator(identifierComparator); + + return ret; + } + + public long moonrise$getId(); + + public Comparator moonrise$getIdentifierComparator(); + + public void moonrise$setIdentifierComparator(final Comparator comparator); + + public long[] moonrise$getCounterTypes(); + +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java index e97e7d2..6d1fe80 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java @@ -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(); + } + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickDistanceManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickDistanceManager.java index f28fd0e..27f8e6a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickDistanceManager.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickDistanceManager.java @@ -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); + } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickServerLevel.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickServerLevel.java index 6af03fd..1414f25 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickServerLevel.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickServerLevel.java @@ -6,7 +6,7 @@ import net.minecraft.world.level.chunk.LevelChunk; public interface ChunkTickServerLevel { - public ReferenceList moonrise$getPlayerTickingChunks(); + public ReferenceList moonrise$getPlayerTickingChunks(); public void moonrise$markChunkForPlayerTicking(final LevelChunk chunk); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java index e04bd54..a97a2a8 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java @@ -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))) { + mutablePos.set(blockX, blockY, blockZ); if (useEntityCollisionShape) { - mutablePos.set(blockX, blockY, blockZ); 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); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightEngine.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightEngine.java index 8aeb5fb..d570e87 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightEngine.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightEngine.java @@ -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) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java index 571db5f..51f4dd4 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/light/StarLightInterface.java @@ -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 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. diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/util/SaveUtil.java b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/util/SaveUtil.java index 689ce36..f1f72a0 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/starlight/util/SaveUtil.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/starlight/util/SaveUtil.java @@ -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)); } } } diff --git a/src/main/resources/moonrise.accesswidener b/src/main/resources/moonrise.accesswidener index 103c46c..8a67e13 100644 --- a/src/main/resources/moonrise.accesswidener +++ b/src/main/resources/moonrise.accesswidener @@ -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 (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 (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 (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 (Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;Z)V + + +# Ticket +accessible method net/minecraft/server/level/Ticket (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; diff --git a/src/main/resources/moonrise.mixins.json b/src/main/resources/moonrise.mixins.json index bb7be20..493ba7a 100644 --- a/src/main/resources/moonrise.mixins.json +++ b/src/main/resources/moonrise.mixins.json @@ -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",