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 918af79..96bb532 100644 --- a/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/FabricHooks.java +++ b/fabric/src/main/java/ca/spottedleaf/moonrise/fabric/FabricHooks.java @@ -271,4 +271,9 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH public long[] getCounterTypesUncached(final TicketType type) { return type == TicketType.FORCED ? new long[] { ChunkSystemTicketType.COUNTER_TYPE_FORCED } : LongArrays.EMPTY_ARRAY; } + + @Override + public boolean addTicketForEnderPearls() { + return true; + } } diff --git a/gradle.properties b/gradle.properties index d94e22b..4f515c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,13 +8,13 @@ org.gradle.configuration-cache=true minecraft_version=1.21.6 loader_version=0.16.14 supported_minecraft_versions=1.21.6 -neoforge_version=21.6.5-beta +neoforge_version=21.6.11-beta neoform_version=1.21.6-20250617.151856 fabric_api_version=0.127.0+1.21.6 snakeyaml_version=2.3 concurrentutil_version=0.0.3 yamlconfig_version=1.0.2 -cloth_version=19.0.146 +cloth_version=19.0.147 modmenu_version=15.0.0-beta.2 # set to false when modmenu/cloth is not updated for the current minecraft version enable_gui=true 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 3ef8b96..6efff26 100644 --- a/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/NeoForgeHooks.java +++ b/neoforge/src/main/java/ca/spottedleaf/moonrise/neoforge/NeoForgeHooks.java @@ -286,4 +286,9 @@ public final class NeoForgeHooks extends BaseChunkSystemHooks implements Platfor return ret.toLongArray(); } + + @Override + public boolean addTicketForEnderPearls() { + return true; + } } diff --git a/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java b/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java index 5721a87..3f55b5c 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java @@ -102,6 +102,8 @@ public interface PlatformHooks extends ChunkSystemHooks { public int modifyEntityTrackingRange(final Entity entity, final int currentRange); + public boolean addTicketForEnderPearls(); + public static final class Holder { private Holder() { } diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java b/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java index 31b92bd..bb5b9c9 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java @@ -16,7 +16,8 @@ public final class CoordinateUtils { } public static long getChunkKey(final Entity entity) { - return ((Mth.lfloor(entity.getZ()) >> 4) << 32) | ((Mth.lfloor(entity.getX()) >> 4) & 0xFFFFFFFFL); + final ChunkPos pos = entity.chunkPosition(); + return ((long)pos.z << 32) | (pos.x & 0xFFFFFFFFL); } public static long getChunkKey(final ChunkPos pos) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java index a038215..cf929c6 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/client/ClientEntityLookup.java @@ -45,8 +45,7 @@ public final class ClientEntityLookup extends EntityLookup { final boolean ticking = this.tickingChunks.contains(CoordinateUtils.getChunkKey(chunkX, chunkZ)); final ChunkEntitySlices ret = new ChunkEntitySlices( - this.world, chunkX, chunkZ, - ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null, + this.world, chunkX, chunkZ, ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world) ); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java index 2620744..e472520 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java @@ -7,9 +7,14 @@ import ca.spottedleaf.moonrise.common.util.TickThread; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices; import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; 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.projectile.ThrownEnderpearl; import net.minecraft.world.level.entity.LevelCallback; public final class ServerEntityLookup extends EntityLookup { @@ -19,6 +24,13 @@ public final class ServerEntityLookup extends EntityLookup { private final ServerLevel serverWorld; public final ReferenceList trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker + // Vanilla does not increment ticket timeouts if the chunk is progressing in generation. They made this change in 1.21.6 so that the ender pearl + // ticket does not expire if the chunk fails to generate before the timeout expires. Rather than blindly adjusting the entire system behavior + // to fix this small issue, we instead add non-expirable tickets here to keep ender pearls ticking. This is how the original feature should have + // been implemented, but I don't think Vanilla has proper entity add/remove hooks like we do. Fixes MC-297591 + private static final TicketType ENDER_PEARL_TICKER = ChunkSystemTicketType.create("chunk_system:ender_pearl_ticker", null); + private final Long2IntOpenHashMap enderPearlChunkCount = new Long2IntOpenHashMap(); + public ServerEntityLookup(final ServerLevel world, final LevelCallback worldCallback) { super(world, worldCallback); this.serverWorld = world; @@ -63,6 +75,10 @@ public final class ServerEntityLookup extends EntityLookup { if (entity instanceof ServerPlayer player) { ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().tickPlayer(player); } + if (entity instanceof ThrownEnderpearl enderpearl && (oldSectionX != newSectionX || oldSectionZ != newSectionZ)) { + this.removeEnderPearl(CoordinateUtils.getChunkKey(oldSectionX, oldSectionZ)); + this.addEnderPearl(CoordinateUtils.getChunkKey(newSectionX, newSectionZ)); + } PlatformHooks.get().entityMove( entity, CoordinateUtils.getChunkSectionKey(oldSectionX, oldSectionY, oldSectionZ), @@ -75,6 +91,9 @@ public final class ServerEntityLookup extends EntityLookup { if (entity instanceof ServerPlayer player) { ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player); } + if (entity instanceof ThrownEnderpearl enderpearl) { + this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition())); + } } @Override @@ -82,6 +101,9 @@ public final class ServerEntityLookup extends EntityLookup { if (entity instanceof ServerPlayer player) { ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player); } + if (entity instanceof ThrownEnderpearl enderpearl) { + this.removeEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition())); + } } @Override @@ -112,4 +134,23 @@ public final class ServerEntityLookup extends EntityLookup { protected boolean screenEntity(final Entity entity, final boolean fromDisk, final boolean event) { return PlatformHooks.get().screenEntity(this.serverWorld, entity, fromDisk, event); } + + private void addEnderPearl(final long coordinate) { + final int oldCount = this.enderPearlChunkCount.addTo(coordinate, 1); + if (oldCount != 0) { + return; + } + ((ChunkSystemServerLevel)this.serverWorld).moonrise$getChunkTaskScheduler().chunkHolderManager + .addTicketAtLevel(ENDER_PEARL_TICKER, coordinate, ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL, null); + } + + private void removeEnderPearl(final long coordinate) { + final int oldCount = this.enderPearlChunkCount.addTo(coordinate, -1); + if (oldCount != 1) { + return; + } + this.enderPearlChunkCount.remove(coordinate); + ((ChunkSystemServerLevel)this.serverWorld).moonrise$getChunkTaskScheduler().chunkHolderManager + .removeTicketAtLevel(ENDER_PEARL_TICKER, coordinate, ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL, null); + } }