Fix MC-297591
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 to keep ender pearls ticking.
This commit is contained in:
@@ -271,4 +271,9 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH
|
|||||||
public long[] getCounterTypesUncached(final TicketType type) {
|
public long[] getCounterTypesUncached(final TicketType type) {
|
||||||
return type == TicketType.FORCED ? new long[] { ChunkSystemTicketType.COUNTER_TYPE_FORCED } : LongArrays.EMPTY_ARRAY;
|
return type == TicketType.FORCED ? new long[] { ChunkSystemTicketType.COUNTER_TYPE_FORCED } : LongArrays.EMPTY_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addTicketForEnderPearls() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ org.gradle.configuration-cache=true
|
|||||||
minecraft_version=1.21.6
|
minecraft_version=1.21.6
|
||||||
loader_version=0.16.14
|
loader_version=0.16.14
|
||||||
supported_minecraft_versions=1.21.6
|
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
|
neoform_version=1.21.6-20250617.151856
|
||||||
fabric_api_version=0.127.0+1.21.6
|
fabric_api_version=0.127.0+1.21.6
|
||||||
snakeyaml_version=2.3
|
snakeyaml_version=2.3
|
||||||
concurrentutil_version=0.0.3
|
concurrentutil_version=0.0.3
|
||||||
yamlconfig_version=1.0.2
|
yamlconfig_version=1.0.2
|
||||||
cloth_version=19.0.146
|
cloth_version=19.0.147
|
||||||
modmenu_version=15.0.0-beta.2
|
modmenu_version=15.0.0-beta.2
|
||||||
# set to false when modmenu/cloth is not updated for the current minecraft version
|
# set to false when modmenu/cloth is not updated for the current minecraft version
|
||||||
enable_gui=true
|
enable_gui=true
|
||||||
|
|||||||
@@ -286,4 +286,9 @@ public final class NeoForgeHooks extends BaseChunkSystemHooks implements Platfor
|
|||||||
|
|
||||||
return ret.toLongArray();
|
return ret.toLongArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addTicketForEnderPearls() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ public interface PlatformHooks extends ChunkSystemHooks {
|
|||||||
|
|
||||||
public int modifyEntityTrackingRange(final Entity entity, final int currentRange);
|
public int modifyEntityTrackingRange(final Entity entity, final int currentRange);
|
||||||
|
|
||||||
|
public boolean addTicketForEnderPearls();
|
||||||
|
|
||||||
public static final class Holder {
|
public static final class Holder {
|
||||||
private Holder() {
|
private Holder() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ public final class CoordinateUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long getChunkKey(final Entity entity) {
|
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) {
|
public static long getChunkKey(final ChunkPos pos) {
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ public final class ClientEntityLookup extends EntityLookup {
|
|||||||
final boolean ticking = this.tickingChunks.contains(CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
final boolean ticking = this.tickingChunks.contains(CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||||
|
|
||||||
final ChunkEntitySlices ret = new ChunkEntitySlices(
|
final ChunkEntitySlices ret = new ChunkEntitySlices(
|
||||||
this.world, chunkX, chunkZ,
|
this.world, chunkX, chunkZ, ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null,
|
||||||
ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null,
|
|
||||||
WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
|
WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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.ChunkSystemServerLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
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.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.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.server.level.TicketType;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
|
||||||
import net.minecraft.world.level.entity.LevelCallback;
|
import net.minecraft.world.level.entity.LevelCallback;
|
||||||
|
|
||||||
public final class ServerEntityLookup extends EntityLookup {
|
public final class ServerEntityLookup extends EntityLookup {
|
||||||
@@ -19,6 +24,13 @@ public final class ServerEntityLookup extends EntityLookup {
|
|||||||
private final ServerLevel serverWorld;
|
private final ServerLevel serverWorld;
|
||||||
public final ReferenceList<Entity> trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
|
public final ReferenceList<Entity> 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<Entity> worldCallback) {
|
public ServerEntityLookup(final ServerLevel world, final LevelCallback<Entity> worldCallback) {
|
||||||
super(world, worldCallback);
|
super(world, worldCallback);
|
||||||
this.serverWorld = world;
|
this.serverWorld = world;
|
||||||
@@ -63,6 +75,10 @@ public final class ServerEntityLookup extends EntityLookup {
|
|||||||
if (entity instanceof ServerPlayer player) {
|
if (entity instanceof ServerPlayer player) {
|
||||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().tickPlayer(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(
|
PlatformHooks.get().entityMove(
|
||||||
entity,
|
entity,
|
||||||
CoordinateUtils.getChunkSectionKey(oldSectionX, oldSectionY, oldSectionZ),
|
CoordinateUtils.getChunkSectionKey(oldSectionX, oldSectionY, oldSectionZ),
|
||||||
@@ -75,6 +91,9 @@ public final class ServerEntityLookup extends EntityLookup {
|
|||||||
if (entity instanceof ServerPlayer player) {
|
if (entity instanceof ServerPlayer player) {
|
||||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player);
|
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player);
|
||||||
}
|
}
|
||||||
|
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||||
|
this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -82,6 +101,9 @@ public final class ServerEntityLookup extends EntityLookup {
|
|||||||
if (entity instanceof ServerPlayer player) {
|
if (entity instanceof ServerPlayer player) {
|
||||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player);
|
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player);
|
||||||
}
|
}
|
||||||
|
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||||
|
this.removeEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,4 +134,23 @@ public final class ServerEntityLookup extends EntityLookup {
|
|||||||
protected boolean screenEntity(final Entity entity, final boolean fromDisk, final boolean event) {
|
protected boolean screenEntity(final Entity entity, final boolean fromDisk, final boolean event) {
|
||||||
return PlatformHooks.get().screenEntity(this.serverWorld, entity, fromDisk, 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user