ChunkHolder.java

net.minecraft.server.level.ChunkHolder

信息

  • 全限定名:net.minecraft.server.level.ChunkHolder
  • 类型:public class
  • 包:net.minecraft.server.level
  • 源码路径:src/main/java/net/minecraft/server/level/ChunkHolder.java
  • 起始行号:L32
  • 继承:GenerationChunkHolder
  • 职责:

    TODO

字段/常量

  • UNLOADED_LEVEL_CHUNK

    • 类型: ChunkResult<LevelChunk>
    • 修饰符: public static final
    • 源码定位: L33
    • 说明:

      TODO

  • UNLOADED_LEVEL_CHUNK_FUTURE

    • 类型: CompletableFuture<ChunkResult<LevelChunk>>
    • 修饰符: private static final
    • 源码定位: L34
    • 说明:

      TODO

  • levelHeightAccessor

    • 类型: LevelHeightAccessor
    • 修饰符: private final
    • 源码定位: L35
    • 说明:

      TODO

  • fullChunkFuture

    • 类型: CompletableFuture<ChunkResult<LevelChunk>>
    • 修饰符: private volatile
    • 源码定位: L36
    • 说明:

      TODO

  • tickingChunkFuture

    • 类型: CompletableFuture<ChunkResult<LevelChunk>>
    • 修饰符: private volatile
    • 源码定位: L37
    • 说明:

      TODO

  • entityTickingChunkFuture

    • 类型: CompletableFuture<ChunkResult<LevelChunk>>
    • 修饰符: private volatile
    • 源码定位: L38
    • 说明:

      TODO

  • oldTicketLevel

    • 类型: int
    • 修饰符: private
    • 源码定位: L39
    • 说明:

      TODO

  • ticketLevel

    • 类型: int
    • 修饰符: private
    • 源码定位: L40
    • 说明:

      TODO

  • queueLevel

    • 类型: int
    • 修饰符: private
    • 源码定位: L41
    • 说明:

      TODO

  • hasChangedSections

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L42
    • 说明:

      TODO

  • changedBlocksPerSection

    • 类型: ShortSet[]
    • 修饰符: private final
    • 源码定位: L43
    • 说明:

      TODO

  • blockChangedLightSectionFilter

    • 类型: BitSet
    • 修饰符: private final
    • 源码定位: L44
    • 说明:

      TODO

  • skyChangedLightSectionFilter

    • 类型: BitSet
    • 修饰符: private final
    • 源码定位: L45
    • 说明:

      TODO

  • lightEngine

    • 类型: LevelLightEngine
    • 修饰符: private final
    • 源码定位: L46
    • 说明:

      TODO

  • onLevelChange

    • 类型: ChunkHolder.LevelChangeListener
    • 修饰符: private final
    • 源码定位: L47
    • 说明:

      TODO

  • playerProvider

    • 类型: ChunkHolder.PlayerProvider
    • 修饰符: private final
    • 源码定位: L48
    • 说明:

      TODO

  • wasAccessibleSinceLastSave

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L49
    • 说明:

      TODO

  • pendingFullStateConfirmation

    • 类型: CompletableFuture<?>
    • 修饰符: private
    • 源码定位: L50
    • 说明:

      TODO

  • sendSync

    • 类型: CompletableFuture<?>
    • 修饰符: private
    • 源码定位: L51
    • 说明:

      TODO

  • saveSync

    • 类型: CompletableFuture<?>
    • 修饰符: private
    • 源码定位: L52
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.server.level.ChunkHolder.LevelChangeListener

    • 类型: interface
    • 修饰符: public
    • 源码定位: L337
    • 说明:

      TODO

  • net.minecraft.server.level.ChunkHolder.PlayerProvider

    • 类型: interface
    • 修饰符: public
    • 源码定位: L341
    • 说明:

      TODO

构造器

public ChunkHolder(ChunkPos pos, int ticketLevel, LevelHeightAccessor levelHeightAccessor, LevelLightEngine lightEngine, ChunkHolder.LevelChangeListener onLevelChange, ChunkHolder.PlayerProvider playerProvider) @ L54

  • 构造器名:ChunkHolder
  • 源码定位:L54
  • 修饰符:public

参数:

  • pos: ChunkPos
  • ticketLevel: int
  • levelHeightAccessor: LevelHeightAccessor
  • lightEngine: LevelLightEngine
  • onLevelChange: ChunkHolder.LevelChangeListener
  • playerProvider: ChunkHolder.PlayerProvider

说明:

TODO

方法

下面的方法块按源码顺序生成。

public CompletableFuture<ChunkResult<LevelChunk>> getTickingChunkFuture() @ L74

  • 方法名:getTickingChunkFuture
  • 源码定位:L74
  • 返回类型:CompletableFuture<ChunkResult>
  • 修饰符:public

参数:

说明:

TODO

public CompletableFuture<ChunkResult<LevelChunk>> getEntityTickingChunkFuture() @ L78

  • 方法名:getEntityTickingChunkFuture
  • 源码定位:L78
  • 返回类型:CompletableFuture<ChunkResult>
  • 修饰符:public

参数:

说明:

TODO

public CompletableFuture<ChunkResult<LevelChunk>> getFullChunkFuture() @ L82

  • 方法名:getFullChunkFuture
  • 源码定位:L82
  • 返回类型:CompletableFuture<ChunkResult>
  • 修饰符:public

参数:

说明:

TODO

public LevelChunk getTickingChunk() @ L86

  • 方法名:getTickingChunk
  • 源码定位:L86
  • 返回类型:LevelChunk
  • 修饰符:public

参数:

说明:

TODO

public LevelChunk getChunkToSend() @ L90

  • 方法名:getChunkToSend
  • 源码定位:L90
  • 返回类型:LevelChunk
  • 修饰符:public

参数:

说明:

TODO

public CompletableFuture<?> getSendSyncFuture() @ L94

  • 方法名:getSendSyncFuture
  • 源码定位:L94
  • 返回类型:CompletableFuture<?>
  • 修饰符:public

参数:

说明:

TODO

public void addSendDependency(CompletableFuture<?> sync) @ L98

  • 方法名:addSendDependency
  • 源码定位:L98
  • 返回类型:void
  • 修饰符:public

参数:

  • sync: CompletableFuture<?>

说明:

TODO

public CompletableFuture<?> getSaveSyncFuture() @ L106

  • 方法名:getSaveSyncFuture
  • 源码定位:L106
  • 返回类型:CompletableFuture<?>
  • 修饰符:public

参数:

说明:

TODO

public boolean isReadyForSaving() @ L110

  • 方法名:isReadyForSaving
  • 源码定位:L110
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

protected void addSaveDependency(CompletableFuture<?> sync) @ L114

  • 方法名:addSaveDependency
  • 源码定位:L114
  • 返回类型:void
  • 修饰符:protected

参数:

  • sync: CompletableFuture<?>

说明:

TODO

public boolean blockChanged(BlockPos pos) @ L123

  • 方法名:blockChanged
  • 源码定位:L123
  • 返回类型:boolean
  • 修饰符:public

参数:

  • pos: BlockPos

说明:

TODO

public boolean sectionLightChanged(LightLayer layer, int chunkY) @ L142

  • 方法名:sectionLightChanged
  • 源码定位:L142
  • 返回类型:boolean
  • 修饰符:public

参数:

  • layer: LightLayer
  • chunkY: int

说明:

TODO

public boolean hasChangesToBroadcast() @ L170

  • 方法名:hasChangesToBroadcast
  • 源码定位:L170
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public void broadcastChanges(LevelChunk chunk) @ L174

  • 方法名:broadcastChanges
  • 源码定位:L174
  • 返回类型:void
  • 修饰符:public

参数:

  • chunk: LevelChunk

说明:

TODO

private void broadcastBlockEntityIfNeeded(List<ServerPlayer> players, Level level, BlockPos pos, BlockState state) @ L220

  • 方法名:broadcastBlockEntityIfNeeded
  • 源码定位:L220
  • 返回类型:void
  • 修饰符:private

参数:

  • players: List
  • level: Level
  • pos: BlockPos
  • state: BlockState

说明:

TODO

private void broadcastBlockEntity(List<ServerPlayer> players, Level level, BlockPos blockPos) @ L226

  • 方法名:broadcastBlockEntity
  • 源码定位:L226
  • 返回类型:void
  • 修饰符:private

参数:

  • players: List
  • level: Level
  • blockPos: BlockPos

说明:

TODO

private void broadcast(List<ServerPlayer> players, Packet<?> packet) @ L236

  • 方法名:broadcast
  • 源码定位:L236
  • 返回类型:void
  • 修饰符:private

参数:

  • players: List
  • packet: Packet<?>

说明:

TODO

public int getTicketLevel() @ L240

  • 方法名:getTicketLevel
  • 源码定位:L240
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public int getQueueLevel() @ L245

  • 方法名:getQueueLevel
  • 源码定位:L245
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

private void setQueueLevel(int queueLevel) @ L250

  • 方法名:setQueueLevel
  • 源码定位:L250
  • 返回类型:void
  • 修饰符:private

参数:

  • queueLevel: int

说明:

TODO

public void setTicketLevel(int ticketLevel) @ L254

  • 方法名:setTicketLevel
  • 源码定位:L254
  • 返回类型:void
  • 修饰符:public

参数:

  • ticketLevel: int

说明:

TODO

private void scheduleFullChunkPromotion(ChunkMap scheduler, CompletableFuture<ChunkResult<LevelChunk>> task, Executor mainThreadExecutor, FullChunkStatus status) @ L258

  • 方法名:scheduleFullChunkPromotion
  • 源码定位:L258
  • 返回类型:void
  • 修饰符:private

参数:

  • scheduler: ChunkMap
  • task: CompletableFuture<ChunkResult>
  • mainThreadExecutor: Executor
  • status: FullChunkStatus

说明:

TODO

private void demoteFullChunk(ChunkMap scheduler, FullChunkStatus status) @ L268

  • 方法名:demoteFullChunk
  • 源码定位:L268
  • 返回类型:void
  • 修饰符:private

参数:

  • scheduler: ChunkMap
  • status: FullChunkStatus

说明:

TODO

protected void updateFutures(ChunkMap scheduler, Executor mainThreadExecutor) @ L273

  • 方法名:updateFutures
  • 源码定位:L273
  • 返回类型:void
  • 修饰符:protected

参数:

  • scheduler: ChunkMap
  • mainThreadExecutor: Executor

说明:

TODO

public boolean wasAccessibleSinceLastSave() @ L328

  • 方法名:wasAccessibleSinceLastSave
  • 源码定位:L328
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public void refreshAccessibility() @ L332

  • 方法名:refreshAccessibility
  • 源码定位:L332
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

代码

public class ChunkHolder extends GenerationChunkHolder {
    public static final ChunkResult<LevelChunk> UNLOADED_LEVEL_CHUNK = ChunkResult.error("Unloaded level chunk");
    private static final CompletableFuture<ChunkResult<LevelChunk>> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(UNLOADED_LEVEL_CHUNK);
    private final LevelHeightAccessor levelHeightAccessor;
    private volatile CompletableFuture<ChunkResult<LevelChunk>> fullChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE;
    private volatile CompletableFuture<ChunkResult<LevelChunk>> tickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE;
    private volatile CompletableFuture<ChunkResult<LevelChunk>> entityTickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE;
    private int oldTicketLevel;
    private int ticketLevel;
    private int queueLevel;
    private boolean hasChangedSections;
    private final @Nullable ShortSet[] changedBlocksPerSection;
    private final BitSet blockChangedLightSectionFilter = new BitSet();
    private final BitSet skyChangedLightSectionFilter = new BitSet();
    private final LevelLightEngine lightEngine;
    private final ChunkHolder.LevelChangeListener onLevelChange;
    private final ChunkHolder.PlayerProvider playerProvider;
    private boolean wasAccessibleSinceLastSave;
    private CompletableFuture<?> pendingFullStateConfirmation = CompletableFuture.completedFuture(null);
    private CompletableFuture<?> sendSync = CompletableFuture.completedFuture(null);
    private CompletableFuture<?> saveSync = CompletableFuture.completedFuture(null);
 
    public ChunkHolder(
        ChunkPos pos,
        int ticketLevel,
        LevelHeightAccessor levelHeightAccessor,
        LevelLightEngine lightEngine,
        ChunkHolder.LevelChangeListener onLevelChange,
        ChunkHolder.PlayerProvider playerProvider
    ) {
        super(pos);
        this.levelHeightAccessor = levelHeightAccessor;
        this.lightEngine = lightEngine;
        this.onLevelChange = onLevelChange;
        this.playerProvider = playerProvider;
        this.oldTicketLevel = ChunkLevel.MAX_LEVEL + 1;
        this.ticketLevel = this.oldTicketLevel;
        this.queueLevel = this.oldTicketLevel;
        this.setTicketLevel(ticketLevel);
        this.changedBlocksPerSection = new ShortSet[levelHeightAccessor.getSectionsCount()];
    }
 
    public CompletableFuture<ChunkResult<LevelChunk>> getTickingChunkFuture() {
        return this.tickingChunkFuture;
    }
 
    public CompletableFuture<ChunkResult<LevelChunk>> getEntityTickingChunkFuture() {
        return this.entityTickingChunkFuture;
    }
 
    public CompletableFuture<ChunkResult<LevelChunk>> getFullChunkFuture() {
        return this.fullChunkFuture;
    }
 
    public @Nullable LevelChunk getTickingChunk() {
        return this.getTickingChunkFuture().getNow(UNLOADED_LEVEL_CHUNK).orElse(null);
    }
 
    public @Nullable LevelChunk getChunkToSend() {
        return !this.sendSync.isDone() ? null : this.getTickingChunk();
    }
 
    public CompletableFuture<?> getSendSyncFuture() {
        return this.sendSync;
    }
 
    public void addSendDependency(CompletableFuture<?> sync) {
        if (this.sendSync.isDone()) {
            this.sendSync = sync;
        } else {
            this.sendSync = this.sendSync.thenCombine((CompletionStage<? extends Object>)sync, (a, b) -> null);
        }
    }
 
    public CompletableFuture<?> getSaveSyncFuture() {
        return this.saveSync;
    }
 
    public boolean isReadyForSaving() {
        return this.saveSync.isDone();
    }
 
    @Override
    protected void addSaveDependency(CompletableFuture<?> sync) {
        if (this.saveSync.isDone()) {
            this.saveSync = sync;
        } else {
            this.saveSync = this.saveSync.thenCombine((CompletionStage<? extends Object>)sync, (a, b) -> null);
        }
    }
 
    public boolean blockChanged(BlockPos pos) {
        LevelChunk chunk = this.getTickingChunk();
        if (chunk == null) {
            return false;
        } else {
            boolean hadChangedSections = this.hasChangedSections;
            int sectionIndex = this.levelHeightAccessor.getSectionIndex(pos.getY());
            ShortSet changedBlocksInSection = this.changedBlocksPerSection[sectionIndex];
            if (changedBlocksInSection == null) {
                this.hasChangedSections = true;
                changedBlocksInSection = new ShortOpenHashSet();
                this.changedBlocksPerSection[sectionIndex] = changedBlocksInSection;
            }
 
            changedBlocksInSection.add(SectionPos.sectionRelativePos(pos));
            return !hadChangedSections;
        }
    }
 
    public boolean sectionLightChanged(LightLayer layer, int chunkY) {
        ChunkAccess chunk = this.getChunkIfPresent(ChunkStatus.INITIALIZE_LIGHT);
        if (chunk == null) {
            return false;
        } else {
            chunk.markUnsaved();
            LevelChunk tickingChunk = this.getTickingChunk();
            if (tickingChunk == null) {
                return false;
            } else {
                int minLightSection = this.lightEngine.getMinLightSection();
                int maxLightSection = this.lightEngine.getMaxLightSection();
                if (chunkY >= minLightSection && chunkY <= maxLightSection) {
                    BitSet filter = layer == LightLayer.SKY ? this.skyChangedLightSectionFilter : this.blockChangedLightSectionFilter;
                    int index = chunkY - minLightSection;
                    if (!filter.get(index)) {
                        filter.set(index);
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
        }
    }
 
    public boolean hasChangesToBroadcast() {
        return this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty();
    }
 
    public void broadcastChanges(LevelChunk chunk) {
        if (this.hasChangesToBroadcast()) {
            Level level = chunk.getLevel();
            if (!this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) {
                List<ServerPlayer> borderPlayers = this.playerProvider.getPlayers(this.pos, true);
                if (!borderPlayers.isEmpty()) {
                    ClientboundLightUpdatePacket lightPacket = new ClientboundLightUpdatePacket(
                        chunk.getPos(), this.lightEngine, this.skyChangedLightSectionFilter, this.blockChangedLightSectionFilter
                    );
                    this.broadcast(borderPlayers, lightPacket);
                }
 
                this.skyChangedLightSectionFilter.clear();
                this.blockChangedLightSectionFilter.clear();
            }
 
            if (this.hasChangedSections) {
                List<ServerPlayer> players = this.playerProvider.getPlayers(this.pos, false);
 
                for (int sectionIndex = 0; sectionIndex < this.changedBlocksPerSection.length; sectionIndex++) {
                    ShortSet changedBlocks = this.changedBlocksPerSection[sectionIndex];
                    if (changedBlocks != null) {
                        this.changedBlocksPerSection[sectionIndex] = null;
                        if (!players.isEmpty()) {
                            int sectionY = this.levelHeightAccessor.getSectionYFromSectionIndex(sectionIndex);
                            SectionPos sectionPos = SectionPos.of(chunk.getPos(), sectionY);
                            if (changedBlocks.size() == 1) {
                                BlockPos pos = sectionPos.relativeToBlockPos(changedBlocks.iterator().nextShort());
                                BlockState state = level.getBlockState(pos);
                                this.broadcast(players, new ClientboundBlockUpdatePacket(pos, state));
                                this.broadcastBlockEntityIfNeeded(players, level, pos, state);
                            } else {
                                LevelChunkSection section = chunk.getSection(sectionIndex);
                                ClientboundSectionBlocksUpdatePacket packet = new ClientboundSectionBlocksUpdatePacket(sectionPos, changedBlocks, section);
                                this.broadcast(players, packet);
                                packet.runUpdates((pos, state) -> this.broadcastBlockEntityIfNeeded(players, level, pos, state));
                            }
                        }
                    }
                }
 
                this.hasChangedSections = false;
            }
        }
    }
 
    private void broadcastBlockEntityIfNeeded(List<ServerPlayer> players, Level level, BlockPos pos, BlockState state) {
        if (state.hasBlockEntity()) {
            this.broadcastBlockEntity(players, level, pos);
        }
    }
 
    private void broadcastBlockEntity(List<ServerPlayer> players, Level level, BlockPos blockPos) {
        BlockEntity blockEntity = level.getBlockEntity(blockPos);
        if (blockEntity != null) {
            Packet<?> packet = blockEntity.getUpdatePacket();
            if (packet != null) {
                this.broadcast(players, packet);
            }
        }
    }
 
    private void broadcast(List<ServerPlayer> players, Packet<?> packet) {
        players.forEach(player -> player.connection.send(packet));
    }
 
    @Override
    public int getTicketLevel() {
        return this.ticketLevel;
    }
 
    @Override
    public int getQueueLevel() {
        return this.queueLevel;
    }
 
    private void setQueueLevel(int queueLevel) {
        this.queueLevel = queueLevel;
    }
 
    public void setTicketLevel(int ticketLevel) {
        this.ticketLevel = ticketLevel;
    }
 
    private void scheduleFullChunkPromotion(
        ChunkMap scheduler, CompletableFuture<ChunkResult<LevelChunk>> task, Executor mainThreadExecutor, FullChunkStatus status
    ) {
        this.pendingFullStateConfirmation.cancel(false);
        CompletableFuture<Void> confirmation = new CompletableFuture<>();
        confirmation.thenRunAsync(() -> scheduler.onFullChunkStatusChange(this.pos, status), mainThreadExecutor);
        this.pendingFullStateConfirmation = confirmation;
        task.thenAccept(r -> r.ifSuccess(l -> confirmation.complete(null)));
    }
 
    private void demoteFullChunk(ChunkMap scheduler, FullChunkStatus status) {
        this.pendingFullStateConfirmation.cancel(false);
        scheduler.onFullChunkStatusChange(this.pos, status);
    }
 
    protected void updateFutures(ChunkMap scheduler, Executor mainThreadExecutor) {
        FullChunkStatus oldFullStatus = ChunkLevel.fullStatus(this.oldTicketLevel);
        FullChunkStatus newFullStatus = ChunkLevel.fullStatus(this.ticketLevel);
        boolean wasAccessible = oldFullStatus.isOrAfter(FullChunkStatus.FULL);
        boolean isAccessible = newFullStatus.isOrAfter(FullChunkStatus.FULL);
        this.wasAccessibleSinceLastSave |= isAccessible;
        if (!wasAccessible && isAccessible) {
            this.fullChunkFuture = scheduler.prepareAccessibleChunk(this);
            this.scheduleFullChunkPromotion(scheduler, this.fullChunkFuture, mainThreadExecutor, FullChunkStatus.FULL);
            this.addSaveDependency(this.fullChunkFuture);
        }
 
        if (wasAccessible && !isAccessible) {
            this.fullChunkFuture.complete(UNLOADED_LEVEL_CHUNK);
            this.fullChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE;
        }
 
        boolean wasTicking = oldFullStatus.isOrAfter(FullChunkStatus.BLOCK_TICKING);
        boolean isTicking = newFullStatus.isOrAfter(FullChunkStatus.BLOCK_TICKING);
        if (!wasTicking && isTicking) {
            this.tickingChunkFuture = scheduler.prepareTickingChunk(this);
            this.scheduleFullChunkPromotion(scheduler, this.tickingChunkFuture, mainThreadExecutor, FullChunkStatus.BLOCK_TICKING);
            this.addSaveDependency(this.tickingChunkFuture);
        }
 
        if (wasTicking && !isTicking) {
            this.tickingChunkFuture.complete(UNLOADED_LEVEL_CHUNK);
            this.tickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE;
        }
 
        boolean wasEntityTicking = oldFullStatus.isOrAfter(FullChunkStatus.ENTITY_TICKING);
        boolean isEntityTicking = newFullStatus.isOrAfter(FullChunkStatus.ENTITY_TICKING);
        if (!wasEntityTicking && isEntityTicking) {
            if (this.entityTickingChunkFuture != UNLOADED_LEVEL_CHUNK_FUTURE) {
                throw (IllegalStateException)Util.pauseInIde(new IllegalStateException());
            }
 
            this.entityTickingChunkFuture = scheduler.prepareEntityTickingChunk(this);
            this.scheduleFullChunkPromotion(scheduler, this.entityTickingChunkFuture, mainThreadExecutor, FullChunkStatus.ENTITY_TICKING);
            this.addSaveDependency(this.entityTickingChunkFuture);
        }
 
        if (wasEntityTicking && !isEntityTicking) {
            this.entityTickingChunkFuture.complete(UNLOADED_LEVEL_CHUNK);
            this.entityTickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE;
        }
 
        if (!newFullStatus.isOrAfter(oldFullStatus)) {
            this.demoteFullChunk(scheduler, newFullStatus);
        }
 
        this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel);
        this.oldTicketLevel = this.ticketLevel;
    }
 
    public boolean wasAccessibleSinceLastSave() {
        return this.wasAccessibleSinceLastSave;
    }
 
    public void refreshAccessibility() {
        this.wasAccessibleSinceLastSave = ChunkLevel.fullStatus(this.ticketLevel).isOrAfter(FullChunkStatus.FULL);
    }
 
    @FunctionalInterface
    public interface LevelChangeListener {
        void onLevelChange(ChunkPos pos, IntSupplier oldLevel, int newLevel, IntConsumer setQueueLevel);
    }
 
    public interface PlayerProvider {
        List<ServerPlayer> getPlayers(ChunkPos pos, boolean borderOnly);
    }
}

引用的其他类