fix FullChunkAccess enum move (#9281)

This commit is contained in:
Jake Potrebic 2023-06-08 12:22:12 -07:00
parent ebe89a7928
commit b7b98b0bd8
2 changed files with 97 additions and 87 deletions

View file

@ -2675,6 +2675,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import io.papermc.paper.util.CoordinateUtils; +import io.papermc.paper.util.CoordinateUtils;
+import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap;
+import net.minecraft.server.level.FullChunkStatus;
+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.server.level.TicketType;
@ -2787,7 +2788,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ, + public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
+ final ChunkHolder.FullChunkStatus toStatus, final boolean addTicket, + final FullChunkStatus toStatus, final boolean addTicket,
+ final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) { + final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) {
+ if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) { + if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) {
+ throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status"); + throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");

View file

@ -2599,7 +2599,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ, public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
final ChunkHolder.FullChunkStatus toStatus, final boolean addTicket, final FullChunkStatus toStatus, final boolean addTicket,
final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) { final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) {
- if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) { - if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) {
- throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status"); - throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
@ -4182,6 +4182,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.minecraft.world.level.entity.EntityInLevelCallback; +import net.minecraft.world.level.entity.EntityInLevelCallback;
+import net.minecraft.world.level.entity.EntityTypeTest; +import net.minecraft.world.level.entity.EntityTypeTest;
+import net.minecraft.world.level.entity.LevelCallback; +import net.minecraft.world.level.entity.LevelCallback;
+import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.world.level.entity.LevelEntityGetter; +import net.minecraft.world.level.entity.LevelEntityGetter;
+import net.minecraft.world.level.entity.Visibility; +import net.minecraft.world.level.entity.Visibility;
+import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.AABB;
@ -4462,7 +4463,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ } + }
+ +
+ public void chunkStatusChange(final int x, final int z, final ChunkHolder.FullChunkStatus newStatus) { + public void chunkStatusChange(final int x, final int z, final FullChunkStatus newStatus) {
+ this.getChunk(x, z).updateStatus(newStatus, this); + this.getChunk(x, z).updateStatus(newStatus, this);
+ } + }
+ +
@ -4492,8 +4493,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (entity.isAlwaysTicking()) { + if (entity.isAlwaysTicking()) {
+ return Visibility.TICKING; + return Visibility.TICKING;
+ } + }
+ final ChunkHolder.FullChunkStatus entityStatus = entity.chunkStatus; + final FullChunkStatus entityStatus = entity.chunkStatus;
+ return Visibility.fromFullChunkStatus(entityStatus == null ? ChunkHolder.FullChunkStatus.INACCESSIBLE : entityStatus); + return Visibility.fromFullChunkStatus(entityStatus == null ? FullChunkStatus.INACCESSIBLE : entityStatus);
+ } + }
+ +
+ private boolean addEntity(final Entity entity, final boolean fromDisk) { + private boolean addEntity(final Entity entity, final boolean fromDisk) {
@ -4649,7 +4650,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) { + for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) { + for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT)); + final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
+ continue; + continue;
+ } + }
+ +
@ -4688,7 +4689,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) { + for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) { + for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT)); + final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
+ continue; + continue;
+ } + }
+ +
@ -4727,7 +4728,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) { + for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) { + for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT)); + final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
+ continue; + continue;
+ } + }
+ +
@ -4767,7 +4768,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) { + for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) { + for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT)); + final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
+ continue; + continue;
+ } + }
+ +
@ -4807,7 +4808,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) { + for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) { + for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT)); + final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
+ continue; + continue;
+ } + }
+ +
@ -7027,7 +7028,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import io.papermc.paper.chunk.system.ChunkSystem; +import io.papermc.paper.chunk.system.ChunkSystem;
+import net.minecraft.server.MinecraftServer; +import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkLevel;
+import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap;
+import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.Ticket; +import net.minecraft.server.level.Ticket;
+import net.minecraft.server.level.TicketType; +import net.minecraft.server.level.TicketType;
@ -7061,7 +7064,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static final int FULL_LOADED_TICKET_LEVEL = 33; + public static final int FULL_LOADED_TICKET_LEVEL = 33;
+ public static final int BLOCK_TICKING_TICKET_LEVEL = 32; + public static final int BLOCK_TICKING_TICKET_LEVEL = 32;
+ public static final int ENTITY_TICKING_TICKET_LEVEL = 31; + public static final int ENTITY_TICKING_TICKET_LEVEL = 31;
+ public static final int MAX_TICKET_LEVEL = ChunkMap.MAX_CHUNK_DISTANCE; // inclusive + public static final int MAX_TICKET_LEVEL = ChunkLevel.MAX_LEVEL; // inclusive
+ +
+ private static final long NO_TIMEOUT_MARKER = -1L; + private static final long NO_TIMEOUT_MARKER = -1L;
+ +
@ -7190,13 +7193,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ++autoSaved; + ++autoSaved;
+ } + }
+ +
+ if (holder.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) {
+ reschedule.add(holder); + reschedule.add(holder);
+ } + }
+ } + }
+ +
+ for (final NewChunkHolder holder : reschedule) { + for (final NewChunkHolder holder : reschedule) {
+ if (holder.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) {
+ this.autoSaveQueue.add(holder); + this.autoSaveQueue.add(holder);
+ } + }
+ } + }
@ -7293,7 +7296,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // and the levels we get out of the propagator + // and the levels we get out of the propagator
+ +
+ public static int convertBetweenTicketLevels(final int level) { + public static int convertBetweenTicketLevels(final int level) {
+ return ChunkMap.MAX_CHUNK_DISTANCE - level + 1; + return ChunkLevel.MAX_LEVEL - level + 1;
+ } + }
+ +
+ public boolean hasTickets() { + public boolean hasTickets() {
@ -7353,7 +7356,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ protected final void updateTicketLevel(final long coordinate, final int ticketLevel) { + protected final void updateTicketLevel(final long coordinate, final int ticketLevel) {
+ if (ticketLevel > ChunkMap.MAX_CHUNK_DISTANCE) { + if (ticketLevel > ChunkLevel.MAX_LEVEL) {
+ this.ticketLevelPropagator.removeSource(coordinate); + this.ticketLevelPropagator.removeSource(coordinate);
+ } else { + } else {
+ this.ticketLevelPropagator.setSource(coordinate, convertBetweenTicketLevels(ticketLevel)); + this.ticketLevelPropagator.setSource(coordinate, convertBetweenTicketLevels(ticketLevel));
@ -9166,12 +9169,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ +
+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor; +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadPool; +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadPool;
+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadedTaskQueue;
+import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; +import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
+import com.mojang.logging.LogUtils; +import com.mojang.logging.LogUtils;
+import io.papermc.paper.chunk.system.scheduling.queue.RadiusAwarePrioritisedExecutor; +import io.papermc.paper.chunk.system.scheduling.queue.RadiusAwarePrioritisedExecutor;
+import io.papermc.paper.configuration.GlobalConfiguration; +import io.papermc.paper.configuration.GlobalConfiguration;
+import io.papermc.paper.util.CoordinateUtils; +import io.papermc.paper.util.CoordinateUtils;
+import io.papermc.paper.util.TickThread; +import io.papermc.paper.util.TickThread;
+import java.util.function.BooleanSupplier;
+import net.minecraft.CrashReport; +import net.minecraft.CrashReport;
+import net.minecraft.CrashReportCategory; +import net.minecraft.CrashReportCategory;
+import net.minecraft.ReportedException; +import net.minecraft.ReportedException;
@ -9179,12 +9184,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.minecraft.server.MinecraftServer; +import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap;
+import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.TicketType; +import net.minecraft.server.level.TicketType;
+import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.ChunkStatus;
+import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunk;
+import org.bukkit.Bukkit;
+import org.slf4j.Logger; +import org.slf4j.Logger;
+import java.io.File; +import java.io.File;
+import java.util.ArrayDeque; +import java.util.ArrayDeque;
@ -9420,7 +9427,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ +
+ private final AtomicLong chunkLoadCounter = new AtomicLong(); + private final AtomicLong chunkLoadCounter = new AtomicLong();
+ +
+ public void scheduleTickingState(final int chunkX, final int chunkZ, final ChunkHolder.FullChunkStatus toStatus, + public void scheduleTickingState(final int chunkX, final int chunkZ, final FullChunkStatus toStatus,
+ final boolean addTicket, final PrioritisedExecutor.Priority priority, + final boolean addTicket, final PrioritisedExecutor.Priority priority,
+ final Consumer<LevelChunk> onComplete) { + final Consumer<LevelChunk> onComplete) {
+ if (!TickThread.isTickThread()) { + if (!TickThread.isTickThread()) {
@ -9436,7 +9443,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ throw new IllegalStateException("Cannot schedule chunk loading recursively"); + throw new IllegalStateException("Cannot schedule chunk loading recursively");
+ } + }
+ +
+ if (toStatus == ChunkHolder.FullChunkStatus.INACCESSIBLE) { + if (toStatus == FullChunkStatus.INACCESSIBLE) {
+ throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status"); + throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
+ } + }
+ +
@ -9475,7 +9482,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ scheduled = false; + scheduled = false;
+ chunk = null; + chunk = null;
+ } else { + } else {
+ final ChunkHolder.FullChunkStatus currStatus = chunkHolder.getChunkStatus(); + final FullChunkStatus currStatus = chunkHolder.getChunkStatus();
+ if (currStatus.isOrAfter(toStatus)) { + if (currStatus.isOrAfter(toStatus)) {
+ scheduled = false; + scheduled = false;
+ chunk = (LevelChunk)chunkHolder.getCurrentChunk(); + chunk = (LevelChunk)chunkHolder.getCurrentChunk();
@ -9552,7 +9559,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ if (toStatus == ChunkStatus.FULL) { + if (toStatus == ChunkStatus.FULL) {
+ this.scheduleTickingState(chunkX, chunkZ, ChunkHolder.FullChunkStatus.BORDER, addTicket, priority, (Consumer)onComplete); + this.scheduleTickingState(chunkX, chunkZ, FullChunkStatus.FULL, addTicket, priority, (Consumer)onComplete);
+ return; + return;
+ } + }
+ +
@ -10933,6 +10940,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.CompoundTag;
+import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap;
+import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.TicketType; +import net.minecraft.server.level.TicketType;
+import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity;
@ -11994,58 +12002,58 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // upper 16 bits are pending status, lower 16 bits are current status + // upper 16 bits are pending status, lower 16 bits are current status
+ private volatile long chunkStatus; + private volatile long chunkStatus;
+ private static final long PENDING_STATUS_MASK = Long.MIN_VALUE >> 31; + private static final long PENDING_STATUS_MASK = Long.MIN_VALUE >> 31;
+ private static final ChunkHolder.FullChunkStatus[] CHUNK_STATUS_BY_ID = ChunkHolder.FullChunkStatus.values(); + private static final FullChunkStatus[] CHUNK_STATUS_BY_ID = FullChunkStatus.values();
+ private static final VarHandle CHUNK_STATUS_HANDLE = ConcurrentUtil.getVarHandle(NewChunkHolder.class, "chunkStatus", long.class); + private static final VarHandle CHUNK_STATUS_HANDLE = ConcurrentUtil.getVarHandle(NewChunkHolder.class, "chunkStatus", long.class);
+ +
+ public static ChunkHolder.FullChunkStatus getCurrentChunkStatus(final long encoded) { + public static FullChunkStatus getCurrentChunkStatus(final long encoded) {
+ return CHUNK_STATUS_BY_ID[(int)encoded]; + return CHUNK_STATUS_BY_ID[(int)encoded];
+ } + }
+ +
+ public static ChunkHolder.FullChunkStatus getPendingChunkStatus(final long encoded) { + public static FullChunkStatus getPendingChunkStatus(final long encoded) {
+ return CHUNK_STATUS_BY_ID[(int)(encoded >>> 32)]; + return CHUNK_STATUS_BY_ID[(int)(encoded >>> 32)];
+ } + }
+ +
+ public ChunkHolder.FullChunkStatus getChunkStatus() { + public FullChunkStatus getChunkStatus() {
+ return getCurrentChunkStatus(((long)CHUNK_STATUS_HANDLE.getVolatile((NewChunkHolder)this))); + return getCurrentChunkStatus(((long)CHUNK_STATUS_HANDLE.getVolatile((NewChunkHolder)this)));
+ } + }
+ +
+ public boolean isEntityTickingReady() { + public boolean isEntityTickingReady() {
+ return this.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.ENTITY_TICKING); + return this.getChunkStatus().isOrAfter(FullChunkStatus.ENTITY_TICKING);
+ } + }
+ +
+ public boolean isTickingReady() { + public boolean isTickingReady() {
+ return this.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + return this.getChunkStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING);
+ } + }
+ +
+ public boolean isFullChunkReady() { + public boolean isFullChunkReady() {
+ return this.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + return this.getChunkStatus().isOrAfter(FullChunkStatus.FULL);
+ } + }
+ +
+ private static ChunkHolder.FullChunkStatus getStatusForBitset(final long bitset) { + private static FullChunkStatus getStatusForBitset(final long bitset) {
+ if (areNeighboursFullLoaded(bitset, 2)) { + if (areNeighboursFullLoaded(bitset, 2)) {
+ return ChunkHolder.FullChunkStatus.ENTITY_TICKING; + return FullChunkStatus.ENTITY_TICKING;
+ } else if (areNeighboursFullLoaded(bitset, 1)) { + } else if (areNeighboursFullLoaded(bitset, 1)) {
+ return ChunkHolder.FullChunkStatus.TICKING; + return FullChunkStatus.BLOCK_TICKING;
+ } else if (areNeighboursFullLoaded(bitset, 0)) { + } else if (areNeighboursFullLoaded(bitset, 0)) {
+ return ChunkHolder.FullChunkStatus.BORDER; + return FullChunkStatus.FULL;
+ } else { + } else {
+ return ChunkHolder.FullChunkStatus.INACCESSIBLE; + return FullChunkStatus.INACCESSIBLE;
+ } + }
+ } + }
+ +
+ // note: only while updating ticket level, so holds ticket update lock + scheduling lock + // note: only while updating ticket level, so holds ticket update lock + scheduling lock
+ protected final boolean onTicketUpdate(final ChunkHolder.FullChunkStatus oldState, final ChunkHolder.FullChunkStatus newState) { + protected final boolean onTicketUpdate(final FullChunkStatus oldState, final FullChunkStatus newState) {
+ if (oldState == newState) { + if (oldState == newState) {
+ return false; + return false;
+ } + }
+ +
+ // preserve border request after full status complete, as it does not set anything in the bitset + // preserve border request after full status complete, as it does not set anything in the bitset
+ ChunkHolder.FullChunkStatus byNeighbours = getStatusForBitset(this.fullNeighbourChunksLoadedBitset); + FullChunkStatus byNeighbours = getStatusForBitset(this.fullNeighbourChunksLoadedBitset);
+ if (byNeighbours == ChunkHolder.FullChunkStatus.INACCESSIBLE && newState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && this.currentGenStatus == ChunkStatus.FULL) { + if (byNeighbours == FullChunkStatus.INACCESSIBLE && newState.isOrAfter(FullChunkStatus.FULL) && this.currentGenStatus == ChunkStatus.FULL) {
+ byNeighbours = ChunkHolder.FullChunkStatus.BORDER; + byNeighbours = FullChunkStatus.FULL;
+ } + }
+ +
+ final ChunkHolder.FullChunkStatus toSet; + final FullChunkStatus toSet;
+ +
+ if (newState.isOrAfter(byNeighbours)) { + if (newState.isOrAfter(byNeighbours)) {
+ // must clamp to neighbours level, even though we have the ticket level + // must clamp to neighbours level, even though we have the ticket level
@ -12077,9 +12085,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ protected final boolean onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { + protected final boolean onNeighbourChange(final long bitsetBefore, final long bitsetAfter) {
+ ChunkHolder.FullChunkStatus oldState = getStatusForBitset(bitsetBefore); + FullChunkStatus oldState = getStatusForBitset(bitsetBefore);
+ ChunkHolder.FullChunkStatus newState = getStatusForBitset(bitsetAfter); + FullChunkStatus newState = getStatusForBitset(bitsetAfter);
+ final ChunkHolder.FullChunkStatus currStateTicketLevel = ChunkHolder.getFullChunkStatus(this.oldTicketLevel); + final FullChunkStatus currStateTicketLevel = ChunkHolder.getFullChunkStatus(this.oldTicketLevel);
+ if (oldState.isOrAfter(currStateTicketLevel)) { + if (oldState.isOrAfter(currStateTicketLevel)) {
+ oldState = currStateTicketLevel; + oldState = currStateTicketLevel;
+ } + }
@ -12087,8 +12095,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ newState = currStateTicketLevel; + newState = currStateTicketLevel;
+ } + }
+ // preserve border request after full status complete, as it does not set anything in the bitset + // preserve border request after full status complete, as it does not set anything in the bitset
+ if (newState == ChunkHolder.FullChunkStatus.INACCESSIBLE && currStateTicketLevel.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && this.currentGenStatus == ChunkStatus.FULL) { + if (newState == FullChunkStatus.INACCESSIBLE && currStateTicketLevel.isOrAfter(FullChunkStatus.FULL) && this.currentGenStatus == ChunkStatus.FULL) {
+ newState = ChunkHolder.FullChunkStatus.BORDER; + newState = FullChunkStatus.FULL;
+ } + }
+ +
+ if (oldState == newState) { + if (oldState == newState) {
@ -12110,13 +12118,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ private boolean queueBorderFullStatus(final boolean loaded, final List<NewChunkHolder> changedFullStatus) { + private boolean queueBorderFullStatus(final boolean loaded, final List<NewChunkHolder> changedFullStatus) {
+ final ChunkHolder.FullChunkStatus toStatus = loaded ? ChunkHolder.FullChunkStatus.BORDER : ChunkHolder.FullChunkStatus.INACCESSIBLE; + final FullChunkStatus toStatus = loaded ? FullChunkStatus.FULL : FullChunkStatus.INACCESSIBLE;
+ +
+ int failures = 0; + int failures = 0;
+ for (long curr = (long)CHUNK_STATUS_HANDLE.getVolatile((NewChunkHolder)this);;) { + for (long curr = (long)CHUNK_STATUS_HANDLE.getVolatile((NewChunkHolder)this);;) {
+ final ChunkHolder.FullChunkStatus currPending = getPendingChunkStatus(curr); + final FullChunkStatus currPending = getPendingChunkStatus(curr);
+ if (loaded && currPending != ChunkHolder.FullChunkStatus.INACCESSIBLE) { + if (loaded && currPending != FullChunkStatus.INACCESSIBLE) {
+ throw new IllegalStateException("Expected " + ChunkHolder.FullChunkStatus.INACCESSIBLE + " for pending, but got " + currPending); + throw new IllegalStateException("Expected " + FullChunkStatus.INACCESSIBLE + " for pending, but got " + currPending);
+ } + }
+ +
+ final long update = (curr & ~PENDING_STATUS_MASK) | ((long)toStatus.ordinal() << 32); + final long update = (curr & ~PENDING_STATUS_MASK) | ((long)toStatus.ordinal() << 32);
@ -12153,7 +12161,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ } + }
+ +
+ private ChunkHolder.FullChunkStatus updateCurrentState(final ChunkHolder.FullChunkStatus to) { + private FullChunkStatus updateCurrentState(final FullChunkStatus to) {
+ int failures = 0; + int failures = 0;
+ for (long curr = (long)CHUNK_STATUS_HANDLE.getVolatile((NewChunkHolder)this);;) { + for (long curr = (long)CHUNK_STATUS_HANDLE.getVolatile((NewChunkHolder)this);;) {
+ final long update = (curr & PENDING_STATUS_MASK) | (long)to.ordinal(); + final long update = (curr & PENDING_STATUS_MASK) | (long)to.ordinal();
@ -12168,7 +12176,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ } + }
+ +
+ private void changeEntityChunkStatus(final ChunkHolder.FullChunkStatus toStatus) { + private void changeEntityChunkStatus(final FullChunkStatus toStatus) {
+ this.world.getEntityLookup().chunkStatusChange(this.chunkX, this.chunkZ, toStatus); + this.world.getEntityLookup().chunkStatusChange(this.chunkX, this.chunkZ, toStatus);
+ } + }
+ +
@ -12211,10 +12219,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ try { + try {
+ for (;;) { + for (;;) {
+ final long currStateEncoded = (long)CHUNK_STATUS_HANDLE.getOpaque((NewChunkHolder)this); + final long currStateEncoded = (long)CHUNK_STATUS_HANDLE.getOpaque((NewChunkHolder)this);
+ final ChunkHolder.FullChunkStatus currState = getCurrentChunkStatus(currStateEncoded); + final FullChunkStatus currState = getCurrentChunkStatus(currStateEncoded);
+ ChunkHolder.FullChunkStatus nextState = getPendingChunkStatus(currStateEncoded); + FullChunkStatus nextState = getPendingChunkStatus(currStateEncoded);
+ if (currState == nextState) { + if (currState == nextState) {
+ if (nextState == ChunkHolder.FullChunkStatus.INACCESSIBLE) { + if (nextState == FullChunkStatus.INACCESSIBLE) {
+ this.scheduler.schedulingLock.lock(); + this.scheduler.schedulingLock.lock();
+ try { + try {
+ this.checkUnload(); + this.checkUnload();
@ -12235,47 +12243,47 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // of the chunk system load callbacks are invoked + // of the chunk system load callbacks are invoked
+ if (nextState.isOrAfter(currState)) { + if (nextState.isOrAfter(currState)) {
+ // state upgrade + // state upgrade
+ if (!currState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && nextState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (!currState.isOrAfter(FullChunkStatus.FULL) && nextState.isOrAfter(FullChunkStatus.FULL)) {
+ nextState = this.updateCurrentState(ChunkHolder.FullChunkStatus.BORDER); + nextState = this.updateCurrentState(FullChunkStatus.FULL);
+ holderManager.ensureInAutosave(this); + holderManager.ensureInAutosave(this);
+ chunk.pushChunkIntoLoadedMap(); + chunk.pushChunkIntoLoadedMap();
+ this.changeEntityChunkStatus(ChunkHolder.FullChunkStatus.BORDER); + this.changeEntityChunkStatus(FullChunkStatus.FULL);
+ chunk.onChunkLoad(this); + chunk.onChunkLoad(this);
+ this.onFullChunkLoadChange(true, changedFullStatus); + this.onFullChunkLoadChange(true, changedFullStatus);
+ this.completeFullStatusConsumers(ChunkHolder.FullChunkStatus.BORDER, chunk); + this.completeFullStatusConsumers(FullChunkStatus.FULL, chunk);
+ } + }
+ +
+ if (!currState.isOrAfter(ChunkHolder.FullChunkStatus.TICKING) && nextState.isOrAfter(ChunkHolder.FullChunkStatus.TICKING)) { + if (!currState.isOrAfter(FullChunkStatus.BLOCK_TICKING) && nextState.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
+ nextState = this.updateCurrentState(ChunkHolder.FullChunkStatus.TICKING); + nextState = this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
+ this.changeEntityChunkStatus(ChunkHolder.FullChunkStatus.TICKING); + this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
+ chunk.onChunkTicking(this); + chunk.onChunkTicking(this);
+ this.completeFullStatusConsumers(ChunkHolder.FullChunkStatus.TICKING, chunk); + this.completeFullStatusConsumers(FullChunkStatus.BLOCK_TICKING, chunk);
+ } + }
+ +
+ if (!currState.isOrAfter(ChunkHolder.FullChunkStatus.ENTITY_TICKING) && nextState.isOrAfter(ChunkHolder.FullChunkStatus.ENTITY_TICKING)) { + if (!currState.isOrAfter(FullChunkStatus.ENTITY_TICKING) && nextState.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
+ nextState = this.updateCurrentState(ChunkHolder.FullChunkStatus.ENTITY_TICKING); + nextState = this.updateCurrentState(FullChunkStatus.ENTITY_TICKING);
+ this.changeEntityChunkStatus(ChunkHolder.FullChunkStatus.ENTITY_TICKING); + this.changeEntityChunkStatus(FullChunkStatus.ENTITY_TICKING);
+ chunk.onChunkEntityTicking(this); + chunk.onChunkEntityTicking(this);
+ this.completeFullStatusConsumers(ChunkHolder.FullChunkStatus.ENTITY_TICKING, chunk); + this.completeFullStatusConsumers(FullChunkStatus.ENTITY_TICKING, chunk);
+ } + }
+ } else { + } else {
+ if (currState.isOrAfter(ChunkHolder.FullChunkStatus.ENTITY_TICKING) && !nextState.isOrAfter(ChunkHolder.FullChunkStatus.ENTITY_TICKING)) { + if (currState.isOrAfter(FullChunkStatus.ENTITY_TICKING) && !nextState.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
+ this.changeEntityChunkStatus(ChunkHolder.FullChunkStatus.TICKING); + this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
+ chunk.onChunkNotEntityTicking(this); + chunk.onChunkNotEntityTicking(this);
+ nextState = this.updateCurrentState(ChunkHolder.FullChunkStatus.TICKING); + nextState = this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
+ } + }
+ +
+ if (currState.isOrAfter(ChunkHolder.FullChunkStatus.TICKING) && !nextState.isOrAfter(ChunkHolder.FullChunkStatus.TICKING)) { + if (currState.isOrAfter(FullChunkStatus.BLOCK_TICKING) && !nextState.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
+ this.changeEntityChunkStatus(ChunkHolder.FullChunkStatus.BORDER); + this.changeEntityChunkStatus(FullChunkStatus.FULL);
+ chunk.onChunkNotTicking(this); + chunk.onChunkNotTicking(this);
+ nextState = this.updateCurrentState(ChunkHolder.FullChunkStatus.BORDER); + nextState = this.updateCurrentState(FullChunkStatus.FULL);
+ } + }
+ +
+ if (currState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !nextState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (currState.isOrAfter(FullChunkStatus.FULL) && !nextState.isOrAfter(FullChunkStatus.FULL)) {
+ this.onFullChunkLoadChange(false, changedFullStatus); + this.onFullChunkLoadChange(false, changedFullStatus);
+ this.changeEntityChunkStatus(ChunkHolder.FullChunkStatus.INACCESSIBLE); + this.changeEntityChunkStatus(FullChunkStatus.INACCESSIBLE);
+ chunk.onChunkUnload(this); + chunk.onChunkUnload(this);
+ nextState = this.updateCurrentState(ChunkHolder.FullChunkStatus.INACCESSIBLE); + nextState = this.updateCurrentState(FullChunkStatus.INACCESSIBLE);
+ } + }
+ } + }
+ +
@ -12357,17 +12365,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }, PrioritisedExecutor.Priority.HIGHEST); + }, PrioritisedExecutor.Priority.HIGHEST);
+ } + }
+ +
+ private final Reference2ObjectOpenHashMap<ChunkHolder.FullChunkStatus, List<Consumer<LevelChunk>>> fullStatusWaiters = new Reference2ObjectOpenHashMap<>(); + private final Reference2ObjectOpenHashMap<FullChunkStatus, List<Consumer<LevelChunk>>> fullStatusWaiters = new Reference2ObjectOpenHashMap<>();
+ +
+ void addFullStatusConsumer(final ChunkHolder.FullChunkStatus status, final Consumer<LevelChunk> consumer) { + void addFullStatusConsumer(final FullChunkStatus status, final Consumer<LevelChunk> consumer) {
+ this.fullStatusWaiters.computeIfAbsent(status, (final ChunkHolder.FullChunkStatus keyInMap) -> { + this.fullStatusWaiters.computeIfAbsent(status, (final FullChunkStatus keyInMap) -> {
+ return new ArrayList<>(4); + return new ArrayList<>(4);
+ }).add(consumer); + }).add(consumer);
+ } + }
+ +
+ private void completeFullStatusConsumers(ChunkHolder.FullChunkStatus status, final LevelChunk chunk) { + private void completeFullStatusConsumers(FullChunkStatus status, final LevelChunk chunk) {
+ // need to tell future statuses to complete if cancelled + // need to tell future statuses to complete if cancelled
+ final ChunkHolder.FullChunkStatus max = CHUNK_STATUS_BY_ID[CHUNK_STATUS_BY_ID.length - 1]; + final FullChunkStatus max = CHUNK_STATUS_BY_ID[CHUNK_STATUS_BY_ID.length - 1];
+ +
+ for (;;) { + for (;;) {
+ this.completeFullStatusConsumers0(status, chunk); + this.completeFullStatusConsumers0(status, chunk);
@ -12378,7 +12386,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ } + }
+ +
+ private void completeFullStatusConsumers0(final ChunkHolder.FullChunkStatus status, final LevelChunk chunk) { + private void completeFullStatusConsumers0(final FullChunkStatus status, final LevelChunk chunk) {
+ final List<Consumer<LevelChunk>> consumers; + final List<Consumer<LevelChunk>> consumers;
+ consumers = this.fullStatusWaiters.remove(status); + consumers = this.fullStatusWaiters.remove(status);
+ +
@ -12525,7 +12533,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.lockPriority(); + this.lockPriority();
+ // must use oldTicketLevel, we hold the schedule lock but not the ticket level lock + // must use oldTicketLevel, we hold the schedule lock but not the ticket level lock
+ // however, schedule lock needs to be held for ticket level callback, so we're fine here + // however, schedule lock needs to be held for ticket level callback, so we're fine here
+ if (ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) {
+ this.queueBorderFullStatus(true, changedLoadStatus); + this.queueBorderFullStatus(true, changedLoadStatus);
+ } + }
+ } + }
@ -12884,8 +12892,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ final long chunkStatus = this.chunkStatus; + final long chunkStatus = this.chunkStatus;
+ final int fullChunkStatus = (int)chunkStatus; + final int fullChunkStatus = (int)chunkStatus;
+ final int pendingChunkStatus = (int)(chunkStatus >>> 32); + final int pendingChunkStatus = (int)(chunkStatus >>> 32);
+ final ChunkHolder.FullChunkStatus currentFullStatus = fullChunkStatus < 0 || fullChunkStatus >= CHUNK_STATUS_BY_ID.length ? null : CHUNK_STATUS_BY_ID[fullChunkStatus]; + final FullChunkStatus currentFullStatus = fullChunkStatus < 0 || fullChunkStatus >= CHUNK_STATUS_BY_ID.length ? null : CHUNK_STATUS_BY_ID[fullChunkStatus];
+ final ChunkHolder.FullChunkStatus pendingFullStatus = pendingChunkStatus < 0 || pendingChunkStatus >= CHUNK_STATUS_BY_ID.length ? null : CHUNK_STATUS_BY_ID[pendingChunkStatus]; + final FullChunkStatus pendingFullStatus = pendingChunkStatus < 0 || pendingChunkStatus >= CHUNK_STATUS_BY_ID.length ? null : CHUNK_STATUS_BY_ID[pendingChunkStatus];
+ return "NewChunkHolder{" + + return "NewChunkHolder{" +
+ "world=" + this.world.getWorld().getName() + + "world=" + this.world.getWorld().getName() +
+ ", chunkX=" + this.chunkX + + ", chunkX=" + this.chunkX +
@ -14522,6 +14530,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
+import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.CompoundTag;
+import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.FullChunkStatus;
+import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerLevel;
+import net.minecraft.util.Mth; +import net.minecraft.util.Mth;
+import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity;
@ -14552,7 +14561,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ protected final Reference2ObjectOpenHashMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass; + protected final Reference2ObjectOpenHashMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
+ protected final EntityList entities = new EntityList(); + protected final EntityList entities = new EntityList();
+ +
+ public ChunkHolder.FullChunkStatus status; + public FullChunkStatus status;
+ +
+ protected boolean isTransient; + protected boolean isTransient;
+ +
@ -14566,7 +14575,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ +
+ // TODO implement container search optimisations + // TODO implement container search optimisations
+ +
+ public ChunkEntitySlices(final ServerLevel world, final int chunkX, final int chunkZ, final ChunkHolder.FullChunkStatus status, + public ChunkEntitySlices(final ServerLevel world, final int chunkX, final int chunkZ, final FullChunkStatus status,
+ final int minSection, final int maxSection) { // inclusive, inclusive + final int minSection, final int maxSection) { // inclusive, inclusive
+ this.minSection = minSection; + this.minSection = minSection;
+ this.maxSection = maxSection; + this.maxSection = maxSection;
@ -14694,7 +14703,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.preventStatusUpdates = prev; + this.preventStatusUpdates = prev;
+ } + }
+ +
+ public void updateStatus(final ChunkHolder.FullChunkStatus status, final EntityLookup lookup) { + public void updateStatus(final FullChunkStatus status, final EntityLookup lookup) {
+ this.status = status; + this.status = status;
+ +
+ final Entity[] entities = this.entities.getRawData(); + final Entity[] entities = this.entities.getRawData();
@ -15391,7 +15400,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList(); private static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList();
- private final AtomicReferenceArray<CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> futures; - private final AtomicReferenceArray<CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> futures;
+ // Paper - rewrite chunk system + // Paper - rewrite chunk system
+ private static final ChunkHolder.FullChunkStatus[] FULL_CHUNK_STATUSES = ChunkHolder.FullChunkStatus.values(); + private static final FullChunkStatus[] FULL_CHUNK_STATUSES = FullChunkStatus.values();
+ private static final int BLOCKS_BEFORE_RESEND_FUDGE = 64; + private static final int BLOCKS_BEFORE_RESEND_FUDGE = 64;
+ // Paper - rewrite chunk system + // Paper - rewrite chunk system
private final LevelHeightAccessor levelHeightAccessor; private final LevelHeightAccessor levelHeightAccessor;
@ -15792,8 +15801,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- public void setTicketLevel(int level) { - public void setTicketLevel(int level) {
- this.ticketLevel = level; - this.ticketLevel = level;
+ public static ChunkHolder.FullChunkStatus getFullChunkStatus(int distance) { + public static FullChunkStatus getFullChunkStatus(int distance) {
+ return ChunkHolder.FULL_CHUNK_STATUSES[Mth.clamp(33 - distance + 1, 0, ChunkHolder.FULL_CHUNK_STATUSES.length - 1)]; + return ChunkHolder.FULL_CHUNK_STATUSES[net.minecraft.util.Mth.clamp(33 - distance + 1, 0, ChunkHolder.FULL_CHUNK_STATUSES.length - 1)];
} }
- private void scheduleFullChunkPromotion(ChunkMap playerchunkmap, CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture, Executor executor, FullChunkStatus fullchunkstatus) { - private void scheduleFullChunkPromotion(ChunkMap playerchunkmap, CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture, Executor executor, FullChunkStatus fullchunkstatus) {
@ -18778,7 +18787,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return this.hardCollides; + return this.hardCollides;
+ } + }
+ +
+ public net.minecraft.server.level.ChunkHolder.FullChunkStatus chunkStatus; + public net.minecraft.server.level.FullChunkStatus chunkStatus;
+ +
+ public int sectionX = Integer.MIN_VALUE; + public int sectionX = Integer.MIN_VALUE;
+ public int sectionY = Integer.MIN_VALUE; + public int sectionY = Integer.MIN_VALUE;