ChunkGenerationTask.java

net.minecraft.server.level.ChunkGenerationTask

信息

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

    TODO

字段/常量

  • chunkMap

    • 类型: GeneratingChunkMap
    • 修饰符: private final
    • 源码定位: L17
    • 说明:

      TODO

  • pos

    • 类型: ChunkPos
    • 修饰符: private final
    • 源码定位: L18
    • 说明:

      TODO

  • scheduledStatus

    • 类型: ChunkStatus
    • 修饰符: private
    • 源码定位: L19
    • 说明:

      TODO

  • targetStatus

    • 类型: ChunkStatus
    • 修饰符: public final
    • 源码定位: L20
    • 说明:

      TODO

  • markedForCancellation

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

      TODO

  • scheduledLayer

    • 类型: List<CompletableFuture<ChunkResult<ChunkAccess>>>
    • 修饰符: private final
    • 源码定位: L22
    • 说明:

      TODO

  • cache

    • 类型: StaticCache2D<GenerationChunkHolder>
    • 修饰符: private final
    • 源码定位: L23
    • 说明:

      TODO

  • needsGeneration

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

      TODO

内部类/嵌套类型

构造器

private ChunkGenerationTask(GeneratingChunkMap chunkMap, ChunkStatus targetStatus, ChunkPos pos, StaticCache2D<GenerationChunkHolder> cache) @ L26

  • 构造器名:ChunkGenerationTask
  • 源码定位:L26
  • 修饰符:private

参数:

  • chunkMap: GeneratingChunkMap
  • targetStatus: ChunkStatus
  • pos: ChunkPos
  • cache: StaticCache2D

说明:

TODO

方法

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

public static ChunkGenerationTask create(GeneratingChunkMap chunkMap, ChunkStatus targetStatus, ChunkPos pos) @ L33

  • 方法名:create
  • 源码定位:L33
  • 返回类型:ChunkGenerationTask
  • 修饰符:public static

参数:

  • chunkMap: GeneratingChunkMap
  • targetStatus: ChunkStatus
  • pos: ChunkPos

说明:

TODO

public CompletableFuture<?> runUntilWait() @ L41

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

参数:

说明:

TODO

private void scheduleNextLayer() @ L57

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

参数:

说明:

TODO

public void markForCancellation() @ L72

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

参数:

说明:

TODO

private void releaseClaim() @ L76

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

参数:

说明:

TODO

private boolean canLoadWithoutGeneration() @ L82

  • 方法名:canLoadWithoutGeneration
  • 源码定位:L82
  • 返回类型:boolean
  • 修饰符:private

参数:

说明:

TODO

public GenerationChunkHolder getCenter() @ L109

  • 方法名:getCenter
  • 源码定位:L109
  • 返回类型:GenerationChunkHolder
  • 修饰符:public

参数:

说明:

TODO

private void scheduleLayer(ChunkStatus status, boolean needsGeneration) @ L113

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

参数:

  • status: ChunkStatus
  • needsGeneration: boolean

说明:

TODO

private int getRadiusForLayer(ChunkStatus status, boolean needsGeneration) @ L129

  • 方法名:getRadiusForLayer
  • 源码定位:L129
  • 返回类型:int
  • 修饰符:private

参数:

  • status: ChunkStatus
  • needsGeneration: boolean

说明:

TODO

private boolean scheduleChunkInLayer(ChunkStatus status, boolean needsGeneration, GenerationChunkHolder chunkHolder) @ L134

  • 方法名:scheduleChunkInLayer
  • 源码定位:L134
  • 返回类型:boolean
  • 修饰符:private

参数:

  • status: ChunkStatus
  • needsGeneration: boolean
  • chunkHolder: GenerationChunkHolder

说明:

TODO

private CompletableFuture<?> waitForScheduledLayer() @ L155

  • 方法名:waitForScheduledLayer
  • 源码定位:L155
  • 返回类型:CompletableFuture<?>
  • 修饰符:private

参数:

说明:

TODO

代码

public class ChunkGenerationTask {
    private final GeneratingChunkMap chunkMap;
    private final ChunkPos pos;
    private @Nullable ChunkStatus scheduledStatus = null;
    public final ChunkStatus targetStatus;
    private volatile boolean markedForCancellation;
    private final List<CompletableFuture<ChunkResult<ChunkAccess>>> scheduledLayer = new ArrayList<>();
    private final StaticCache2D<GenerationChunkHolder> cache;
    private boolean needsGeneration;
 
    private ChunkGenerationTask(GeneratingChunkMap chunkMap, ChunkStatus targetStatus, ChunkPos pos, StaticCache2D<GenerationChunkHolder> cache) {
        this.chunkMap = chunkMap;
        this.targetStatus = targetStatus;
        this.pos = pos;
        this.cache = cache;
    }
 
    public static ChunkGenerationTask create(GeneratingChunkMap chunkMap, ChunkStatus targetStatus, ChunkPos pos) {
        int worstCaseRadius = ChunkPyramid.GENERATION_PYRAMID.getStepTo(targetStatus).getAccumulatedRadiusOf(ChunkStatus.EMPTY);
        StaticCache2D<GenerationChunkHolder> cache = StaticCache2D.create(
            pos.x(), pos.z(), worstCaseRadius, (x, z) -> chunkMap.acquireGeneration(ChunkPos.pack(x, z))
        );
        return new ChunkGenerationTask(chunkMap, targetStatus, pos, cache);
    }
 
    public @Nullable CompletableFuture<?> runUntilWait() {
        while (true) {
            CompletableFuture<?> waitingFor = this.waitForScheduledLayer();
            if (waitingFor != null) {
                return waitingFor;
            }
 
            if (this.markedForCancellation || this.scheduledStatus == this.targetStatus) {
                this.releaseClaim();
                return null;
            }
 
            this.scheduleNextLayer();
        }
    }
 
    private void scheduleNextLayer() {
        ChunkStatus statusToSchedule;
        if (this.scheduledStatus == null) {
            statusToSchedule = ChunkStatus.EMPTY;
        } else if (!this.needsGeneration && this.scheduledStatus == ChunkStatus.EMPTY && !this.canLoadWithoutGeneration()) {
            this.needsGeneration = true;
            statusToSchedule = ChunkStatus.EMPTY;
        } else {
            statusToSchedule = ChunkStatus.getStatusList().get(this.scheduledStatus.getIndex() + 1);
        }
 
        this.scheduleLayer(statusToSchedule, this.needsGeneration);
        this.scheduledStatus = statusToSchedule;
    }
 
    public void markForCancellation() {
        this.markedForCancellation = true;
    }
 
    private void releaseClaim() {
        GenerationChunkHolder chunkHolder = this.cache.get(this.pos.x(), this.pos.z());
        chunkHolder.removeTask(this);
        this.cache.forEach(this.chunkMap::releaseGeneration);
    }
 
    private boolean canLoadWithoutGeneration() {
        if (this.targetStatus == ChunkStatus.EMPTY) {
            return true;
        } else {
            ChunkStatus highestGeneratedStatus = this.cache.get(this.pos.x(), this.pos.z()).getPersistedStatus();
            if (highestGeneratedStatus != null && !highestGeneratedStatus.isBefore(this.targetStatus)) {
                ChunkDependencies dependencies = ChunkPyramid.LOADING_PYRAMID.getStepTo(this.targetStatus).accumulatedDependencies();
                int range = dependencies.getRadius();
 
                for (int x = this.pos.x() - range; x <= this.pos.x() + range; x++) {
                    for (int z = this.pos.z() - range; z <= this.pos.z() + range; z++) {
                        int distance = this.pos.getChessboardDistance(x, z);
                        ChunkStatus requiredStatus = dependencies.get(distance);
                        ChunkStatus persistedStatus = this.cache.get(x, z).getPersistedStatus();
                        if (persistedStatus == null || persistedStatus.isBefore(requiredStatus)) {
                            return false;
                        }
                    }
                }
 
                return true;
            } else {
                return false;
            }
        }
    }
 
    public GenerationChunkHolder getCenter() {
        return this.cache.get(this.pos.x(), this.pos.z());
    }
 
    private void scheduleLayer(ChunkStatus status, boolean needsGeneration) {
        try (Zone zone = Profiler.get().zone("scheduleLayer")) {
            zone.addText(status::getName);
            int radius = this.getRadiusForLayer(status, needsGeneration);
 
            for (int x = this.pos.x() - radius; x <= this.pos.x() + radius; x++) {
                for (int z = this.pos.z() - radius; z <= this.pos.z() + radius; z++) {
                    GenerationChunkHolder chunkHolder = this.cache.get(x, z);
                    if (this.markedForCancellation || !this.scheduleChunkInLayer(status, needsGeneration, chunkHolder)) {
                        return;
                    }
                }
            }
        }
    }
 
    private int getRadiusForLayer(ChunkStatus status, boolean needsGeneration) {
        ChunkPyramid pyramid = needsGeneration ? ChunkPyramid.GENERATION_PYRAMID : ChunkPyramid.LOADING_PYRAMID;
        return pyramid.getStepTo(this.targetStatus).getAccumulatedRadiusOf(status);
    }
 
    private boolean scheduleChunkInLayer(ChunkStatus status, boolean needsGeneration, GenerationChunkHolder chunkHolder) {
        ChunkStatus persistedStatus = chunkHolder.getPersistedStatus();
        boolean generate = persistedStatus != null && status.isAfter(persistedStatus);
        ChunkPyramid pyramid = generate ? ChunkPyramid.GENERATION_PYRAMID : ChunkPyramid.LOADING_PYRAMID;
        if (generate && !needsGeneration) {
            throw new IllegalStateException("Can't load chunk, but didn't expect to need to generate");
        } else {
            CompletableFuture<ChunkResult<ChunkAccess>> future = chunkHolder.applyStep(pyramid.getStepTo(status), this.chunkMap, this.cache);
            ChunkResult<ChunkAccess> now = future.getNow(null);
            if (now == null) {
                this.scheduledLayer.add(future);
                return true;
            } else if (now.isSuccess()) {
                return true;
            } else {
                this.markForCancellation();
                return false;
            }
        }
    }
 
    private @Nullable CompletableFuture<?> waitForScheduledLayer() {
        while (!this.scheduledLayer.isEmpty()) {
            CompletableFuture<ChunkResult<ChunkAccess>> lastFuture = this.scheduledLayer.getLast();
            ChunkResult<ChunkAccess> resultNow = lastFuture.getNow(null);
            if (resultNow == null) {
                return lastFuture;
            }
 
            this.scheduledLayer.removeLast();
            if (!resultNow.isSuccess()) {
                this.markForCancellation();
            }
        }
 
        return null;
    }
}

引用的其他类

  • ChunkResult

    • 引用位置: 字段
  • GeneratingChunkMap

    • 引用位置: 参数/字段
  • GenerationChunkHolder

    • 引用位置: 参数/字段/返回值
  • StaticCache2D

    • 引用位置: 参数/字段/方法调用
    • 关联成员: StaticCache2D.create()
  • Profiler

    • 引用位置: 方法调用
    • 关联成员: Profiler.get()
  • ChunkPos

    • 引用位置: 参数/字段/方法调用
    • 关联成员: ChunkPos.pack()
  • ChunkAccess

    • 引用位置: 字段
  • ChunkStatus

    • 引用位置: 参数/字段/方法调用
    • 关联成员: ChunkStatus.getStatusList()