GenerationChunkHolder.java
net.minecraft.server.level.GenerationChunkHolder
信息
- 全限定名:net.minecraft.server.level.GenerationChunkHolder
- 类型:public abstract class
- 包:net.minecraft.server.level
- 源码路径:src/main/java/net/minecraft/server/level/GenerationChunkHolder.java
- 起始行号:L23
- 职责:
TODO
字段/常量
-
CHUNK_STATUSES- 类型:
List<ChunkStatus> - 修饰符:
private static final - 源码定位:
L24 - 说明:
TODO
- 类型:
-
NOT_DONE_YET- 类型:
ChunkResult<ChunkAccess> - 修饰符:
private static final - 源码定位:
L25 - 说明:
TODO
- 类型:
-
UNLOADED_CHUNK- 类型:
ChunkResult<ChunkAccess> - 修饰符:
public static final - 源码定位:
L26 - 说明:
TODO
- 类型:
-
UNLOADED_CHUNK_FUTURE- 类型:
CompletableFuture<ChunkResult<ChunkAccess>> - 修饰符:
public static final - 源码定位:
L27 - 说明:
TODO
- 类型:
-
pos- 类型:
ChunkPos - 修饰符:
protected final - 源码定位:
L28 - 说明:
TODO
- 类型:
-
highestAllowedStatus- 类型:
ChunkStatus - 修饰符:
private volatile - 源码定位:
L29 - 说明:
TODO
- 类型:
-
startedWork- 类型:
AtomicReference<ChunkStatus> - 修饰符:
private final - 源码定位:
L30 - 说明:
TODO
- 类型:
-
futures- 类型:
AtomicReferenceArray<CompletableFuture<ChunkResult<ChunkAccess>>> - 修饰符:
private final - 源码定位:
L31 - 说明:
TODO
- 类型:
-
task- 类型:
AtomicReference<ChunkGenerationTask> - 修饰符:
private final - 源码定位:
L32 - 说明:
TODO
- 类型:
-
generationRefCount- 类型:
AtomicInteger - 修饰符:
private final - 源码定位:
L33 - 说明:
TODO
- 类型:
-
generationSaveSyncFuture- 类型:
CompletableFuture<Void> - 修饰符:
private volatile - 源码定位:
L34 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public GenerationChunkHolder(ChunkPos pos) @ L36
- 构造器名:GenerationChunkHolder
- 源码定位:L36
- 修饰符:public
参数:
- pos: ChunkPos
说明:
TODO
方法
下面的方法块按源码顺序生成。
public CompletableFuture<ChunkResult<ChunkAccess>> scheduleChunkGenerationTask(ChunkStatus status, ChunkMap scheduler) @ L43
- 方法名:scheduleChunkGenerationTask
- 源码定位:L43
- 返回类型:CompletableFuture<ChunkResult
> - 修饰符:public
参数:
- status: ChunkStatus
- scheduler: ChunkMap
说明:
TODO
CompletableFuture<ChunkResult<ChunkAccess>> applyStep(ChunkStep step, GeneratingChunkMap chunkMap, StaticCache2D<GenerationChunkHolder> cache) @ L61
- 方法名:applyStep
- 源码定位:L61
- 返回类型:CompletableFuture<ChunkResult
> - 修饰符:package-private
参数:
- step: ChunkStep
- chunkMap: GeneratingChunkMap
- cache: StaticCache2D
说明:
TODO
protected void updateHighestAllowedStatus(ChunkMap scheduler) @ L78
- 方法名:updateHighestAllowedStatus
- 源码定位:L78
- 返回类型:void
- 修饰符:protected
参数:
- scheduler: ChunkMap
说明:
TODO
public void replaceProtoChunk(ImposterProtoChunk chunk) @ L91
- 方法名:replaceProtoChunk
- 源码定位:L91
- 返回类型:void
- 修饰符:public
参数:
- chunk: ImposterProtoChunk
说明:
TODO
void removeTask(ChunkGenerationTask task) @ L108
- 方法名:removeTask
- 源码定位:L108
- 返回类型:void
- 修饰符:package-private
参数:
- task: ChunkGenerationTask
说明:
TODO
private void rescheduleChunkTask(ChunkMap scheduler, ChunkStatus status) @ L112
- 方法名:rescheduleChunkTask
- 源码定位:L112
- 返回类型:void
- 修饰符:private
参数:
- scheduler: ChunkMap
- status: ChunkStatus
说明:
TODO
private CompletableFuture<ChunkResult<ChunkAccess>> getOrCreateFuture(ChunkStatus status) @ L126
- 方法名:getOrCreateFuture
- 源码定位:L126
- 返回类型:CompletableFuture<ChunkResult
> - 修饰符:private
参数:
- status: ChunkStatus
说明:
TODO
private void failAndClearPendingFuturesBetween(ChunkStatus fromExclusive, ChunkStatus toInclusive) @ L150
- 方法名:failAndClearPendingFuturesBetween
- 源码定位:L150
- 返回类型:void
- 修饰符:private
参数:
- fromExclusive: ChunkStatus
- toInclusive: ChunkStatus
说明:
TODO
private void failAndClearPendingFuture(int index, CompletableFuture<ChunkResult<ChunkAccess>> previous) @ L162
- 方法名:failAndClearPendingFuture
- 源码定位:L162
- 返回类型:void
- 修饰符:private
参数:
- index: int
- previous: CompletableFuture<ChunkResult
>
说明:
TODO
private void completeFuture(ChunkStatus status, ChunkAccess chunk) @ L168
- 方法名:completeFuture
- 源码定位:L168
- 返回类型:void
- 修饰符:private
参数:
- status: ChunkStatus
- chunk: ChunkAccess
说明:
TODO
private ChunkStatus findHighestStatusWithPendingFuture(ChunkStatus newStatus) @ L192
- 方法名:findHighestStatusWithPendingFuture
- 源码定位:L192
- 返回类型:ChunkStatus
- 修饰符:private
参数:
- newStatus: ChunkStatus
说明:
TODO
private boolean acquireStatusBump(ChunkStatus status) @ L215
- 方法名:acquireStatusBump
- 源码定位:L215
- 返回类型:boolean
- 修饰符:private
参数:
- status: ChunkStatus
说明:
TODO
private boolean isStatusDisallowed(ChunkStatus status) @ L227
- 方法名:isStatusDisallowed
- 源码定位:L227
- 返回类型:boolean
- 修饰符:private
参数:
- status: ChunkStatus
说明:
TODO
protected abstract void addSaveDependency(CompletableFuture<?> sync) @ L232
- 方法名:addSaveDependency
- 源码定位:L232
- 返回类型:void
- 修饰符:protected abstract
参数:
- sync: CompletableFuture<?>
说明:
TODO
public void increaseGenerationRefCount() @ L234
- 方法名:increaseGenerationRefCount
- 源码定位:L234
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void decreaseGenerationRefCount() @ L241
- 方法名:decreaseGenerationRefCount
- 源码定位:L241
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public ChunkAccess getChunkIfPresentUnchecked(ChunkStatus status) @ L253
- 方法名:getChunkIfPresentUnchecked
- 源码定位:L253
- 返回类型:ChunkAccess
- 修饰符:public
参数:
- status: ChunkStatus
说明:
TODO
public ChunkAccess getChunkIfPresent(ChunkStatus status) @ L258
- 方法名:getChunkIfPresent
- 源码定位:L258
- 返回类型:ChunkAccess
- 修饰符:public
参数:
- status: ChunkStatus
说明:
TODO
public ChunkAccess getLatestChunk() @ L262
- 方法名:getLatestChunk
- 源码定位:L262
- 返回类型:ChunkAccess
- 修饰符:public
参数:
- 无
说明:
TODO
public ChunkStatus getPersistedStatus() @ L272
- 方法名:getPersistedStatus
- 源码定位:L272
- 返回类型:ChunkStatus
- 修饰符:public
参数:
- 无
说明:
TODO
public ChunkPos getPos() @ L278
- 方法名:getPos
- 源码定位:L278
- 返回类型:ChunkPos
- 修饰符:public
参数:
- 无
说明:
TODO
public FullChunkStatus getFullStatus() @ L282
- 方法名:getFullStatus
- 源码定位:L282
- 返回类型:FullChunkStatus
- 修饰符:public
参数:
- 无
说明:
TODO
public abstract int getTicketLevel() @ L286
- 方法名:getTicketLevel
- 源码定位:L286
- 返回类型:int
- 修饰符:public abstract
参数:
- 无
说明:
TODO
public abstract int getQueueLevel() @ L288
- 方法名:getQueueLevel
- 源码定位:L288
- 返回类型:int
- 修饰符:public abstract
参数:
- 无
说明:
TODO
public List<Pair<ChunkStatus,CompletableFuture<ChunkResult<ChunkAccess>>>> getAllFutures() @ L290
- 方法名:getAllFutures
- 源码定位:L290
- 返回类型:List<Pair<ChunkStatus,CompletableFuture<ChunkResult
>>> - 修饰符:public
参数:
- 无
说明:
TODO
public ChunkStatus getLatestStatus() @ L301
- 方法名:getLatestStatus
- 源码定位:L301
- 返回类型:ChunkStatus
- 修饰符:public
参数:
- 无
说明:
TODO
代码
public abstract class GenerationChunkHolder {
private static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList();
private static final ChunkResult<ChunkAccess> NOT_DONE_YET = ChunkResult.error("Not done yet");
public static final ChunkResult<ChunkAccess> UNLOADED_CHUNK = ChunkResult.error("Unloaded chunk");
public static final CompletableFuture<ChunkResult<ChunkAccess>> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(UNLOADED_CHUNK);
protected final ChunkPos pos;
private volatile @Nullable ChunkStatus highestAllowedStatus;
private final AtomicReference<@Nullable ChunkStatus> startedWork = new AtomicReference<>();
private final AtomicReferenceArray<@Nullable CompletableFuture<ChunkResult<ChunkAccess>>> futures = new AtomicReferenceArray<>(CHUNK_STATUSES.size());
private final AtomicReference<@Nullable ChunkGenerationTask> task = new AtomicReference<>();
private final AtomicInteger generationRefCount = new AtomicInteger();
private volatile CompletableFuture<Void> generationSaveSyncFuture = CompletableFuture.completedFuture(null);
public GenerationChunkHolder(ChunkPos pos) {
this.pos = pos;
if (!pos.isValid()) {
throw new IllegalStateException("Trying to create chunk out of reasonable bounds: " + pos);
}
}
public CompletableFuture<ChunkResult<ChunkAccess>> scheduleChunkGenerationTask(ChunkStatus status, ChunkMap scheduler) {
if (this.isStatusDisallowed(status)) {
return UNLOADED_CHUNK_FUTURE;
} else {
CompletableFuture<ChunkResult<ChunkAccess>> future = this.getOrCreateFuture(status);
if (future.isDone()) {
return future;
} else {
ChunkGenerationTask task = this.task.get();
if (task == null || status.isAfter(task.targetStatus)) {
this.rescheduleChunkTask(scheduler, status);
}
return future;
}
}
}
CompletableFuture<ChunkResult<ChunkAccess>> applyStep(ChunkStep step, GeneratingChunkMap chunkMap, StaticCache2D<GenerationChunkHolder> cache) {
if (this.isStatusDisallowed(step.targetStatus())) {
return UNLOADED_CHUNK_FUTURE;
} else {
return this.acquireStatusBump(step.targetStatus()) ? chunkMap.applyStep(this, step, cache).handle((chunk, exception) -> {
if (exception != null) {
CrashReport report = CrashReport.forThrowable(exception, "Exception chunk generation/loading");
BlockableEventLoop.relayDelayCrash(report);
} else {
this.completeFuture(step.targetStatus(), chunk);
}
return ChunkResult.of(chunk);
}) : this.getOrCreateFuture(step.targetStatus());
}
}
protected void updateHighestAllowedStatus(ChunkMap scheduler) {
ChunkStatus oldStatus = this.highestAllowedStatus;
ChunkStatus newStatus = ChunkLevel.generationStatus(this.getTicketLevel());
this.highestAllowedStatus = newStatus;
boolean statusDropped = oldStatus != null && (newStatus == null || newStatus.isBefore(oldStatus));
if (statusDropped) {
this.failAndClearPendingFuturesBetween(newStatus, oldStatus);
if (this.task.get() != null) {
this.rescheduleChunkTask(scheduler, this.findHighestStatusWithPendingFuture(newStatus));
}
}
}
public void replaceProtoChunk(ImposterProtoChunk chunk) {
CompletableFuture<ChunkResult<ChunkAccess>> imposterFuture = CompletableFuture.completedFuture(ChunkResult.of(chunk));
for (int i = 0; i < this.futures.length() - 1; i++) {
CompletableFuture<ChunkResult<ChunkAccess>> future = this.futures.get(i);
Objects.requireNonNull(future);
ChunkAccess maybeProtoChunk = future.getNow(NOT_DONE_YET).orElse(null);
if (!(maybeProtoChunk instanceof ProtoChunk)) {
throw new IllegalStateException("Trying to replace a ProtoChunk, but found " + maybeProtoChunk);
}
if (!this.futures.compareAndSet(i, future, imposterFuture)) {
throw new IllegalStateException("Future changed by other thread while trying to replace it");
}
}
}
void removeTask(ChunkGenerationTask task) {
this.task.compareAndSet(task, null);
}
private void rescheduleChunkTask(ChunkMap scheduler, @Nullable ChunkStatus status) {
ChunkGenerationTask newTask;
if (status != null) {
newTask = scheduler.scheduleGenerationTask(status, this.getPos());
} else {
newTask = null;
}
ChunkGenerationTask oldTask = this.task.getAndSet(newTask);
if (oldTask != null) {
oldTask.markForCancellation();
}
}
private CompletableFuture<ChunkResult<ChunkAccess>> getOrCreateFuture(ChunkStatus status) {
if (this.isStatusDisallowed(status)) {
return UNLOADED_CHUNK_FUTURE;
} else {
int index = status.getIndex();
CompletableFuture<ChunkResult<ChunkAccess>> future = this.futures.get(index);
while (future == null) {
CompletableFuture<ChunkResult<ChunkAccess>> newValue = new CompletableFuture<>();
future = this.futures.compareAndExchange(index, null, newValue);
if (future == null) {
if (this.isStatusDisallowed(status)) {
this.failAndClearPendingFuture(index, newValue);
return UNLOADED_CHUNK_FUTURE;
}
return newValue;
}
}
return future;
}
}
private void failAndClearPendingFuturesBetween(@Nullable ChunkStatus fromExclusive, ChunkStatus toInclusive) {
int start = fromExclusive == null ? 0 : fromExclusive.getIndex() + 1;
int end = toInclusive.getIndex();
for (int i = start; i <= end; i++) {
CompletableFuture<ChunkResult<ChunkAccess>> previous = this.futures.get(i);
if (previous != null) {
this.failAndClearPendingFuture(i, previous);
}
}
}
private void failAndClearPendingFuture(int index, CompletableFuture<ChunkResult<ChunkAccess>> previous) {
if (previous.complete(UNLOADED_CHUNK) && !this.futures.compareAndSet(index, previous, null)) {
throw new IllegalStateException("Nothing else should replace the future here");
}
}
private void completeFuture(ChunkStatus status, ChunkAccess chunk) {
ChunkResult<ChunkAccess> result = ChunkResult.of(chunk);
int index = status.getIndex();
while (true) {
CompletableFuture<ChunkResult<ChunkAccess>> future = this.futures.get(index);
if (future == null) {
if (this.futures.compareAndSet(index, null, CompletableFuture.completedFuture(result))) {
return;
}
} else {
if (future.complete(result)) {
return;
}
if (future.getNow(NOT_DONE_YET).isSuccess()) {
throw new IllegalStateException("Trying to complete a future but found it to be completed successfully already");
}
Thread.yield();
}
}
}
private @Nullable ChunkStatus findHighestStatusWithPendingFuture(@Nullable ChunkStatus newStatus) {
if (newStatus == null) {
return null;
} else {
ChunkStatus highestStatus = newStatus;
for (ChunkStatus alreadyStarted = this.startedWork.get();
alreadyStarted == null || highestStatus.isAfter(alreadyStarted);
highestStatus = highestStatus.getParent()
) {
if (this.futures.get(highestStatus.getIndex()) != null) {
return highestStatus;
}
if (highestStatus == ChunkStatus.EMPTY) {
break;
}
}
return null;
}
}
private boolean acquireStatusBump(ChunkStatus status) {
ChunkStatus parent = status == ChunkStatus.EMPTY ? null : status.getParent();
ChunkStatus previousStarted = this.startedWork.compareAndExchange(parent, status);
if (previousStarted == parent) {
return true;
} else if (previousStarted != null && !status.isAfter(previousStarted)) {
return false;
} else {
throw new IllegalStateException("Unexpected last startedWork status: " + previousStarted + " while trying to start: " + status);
}
}
private boolean isStatusDisallowed(ChunkStatus status) {
ChunkStatus highestAllowedStatus = this.highestAllowedStatus;
return highestAllowedStatus == null || status.isAfter(highestAllowedStatus);
}
protected abstract void addSaveDependency(final CompletableFuture<?> sync);
public void increaseGenerationRefCount() {
if (this.generationRefCount.getAndIncrement() == 0) {
this.generationSaveSyncFuture = new CompletableFuture<>();
this.addSaveDependency(this.generationSaveSyncFuture);
}
}
public void decreaseGenerationRefCount() {
CompletableFuture<Void> future = this.generationSaveSyncFuture;
int newValue = this.generationRefCount.decrementAndGet();
if (newValue == 0) {
future.complete(null);
}
if (newValue < 0) {
throw new IllegalStateException("More releases than claims. Count: " + newValue);
}
}
public @Nullable ChunkAccess getChunkIfPresentUnchecked(ChunkStatus status) {
CompletableFuture<ChunkResult<ChunkAccess>> future = this.futures.get(status.getIndex());
return future == null ? null : future.getNow(NOT_DONE_YET).orElse(null);
}
public @Nullable ChunkAccess getChunkIfPresent(ChunkStatus status) {
return this.isStatusDisallowed(status) ? null : this.getChunkIfPresentUnchecked(status);
}
public @Nullable ChunkAccess getLatestChunk() {
ChunkStatus status = this.startedWork.get();
if (status == null) {
return null;
} else {
ChunkAccess chunk = this.getChunkIfPresentUnchecked(status);
return chunk != null ? chunk : this.getChunkIfPresentUnchecked(status.getParent());
}
}
public @Nullable ChunkStatus getPersistedStatus() {
CompletableFuture<ChunkResult<ChunkAccess>> future = this.futures.get(ChunkStatus.EMPTY.getIndex());
ChunkAccess chunkAccess = future == null ? null : future.getNow(NOT_DONE_YET).orElse(null);
return chunkAccess == null ? null : chunkAccess.getPersistedStatus();
}
public ChunkPos getPos() {
return this.pos;
}
public FullChunkStatus getFullStatus() {
return ChunkLevel.fullStatus(this.getTicketLevel());
}
public abstract int getTicketLevel();
public abstract int getQueueLevel();
@VisibleForDebug
public List<Pair<ChunkStatus, @Nullable CompletableFuture<ChunkResult<ChunkAccess>>>> getAllFutures() {
List<Pair<ChunkStatus, CompletableFuture<ChunkResult<ChunkAccess>>>> result = new ArrayList<>();
for (int i = 0; i < CHUNK_STATUSES.size(); i++) {
result.add(Pair.of(CHUNK_STATUSES.get(i), this.futures.get(i)));
}
return result;
}
@VisibleForDebug
public @Nullable ChunkStatus getLatestStatus() {
ChunkStatus status = this.startedWork.get();
if (status == null) {
return null;
} else {
ChunkAccess chunk = this.getChunkIfPresentUnchecked(status);
return chunk != null ? status : status.getParent();
}
}
}引用的其他类
-
- 引用位置:
方法调用 - 关联成员:
CrashReport.forThrowable()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ChunkLevel.fullStatus(), ChunkLevel.generationStatus()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/方法调用/返回值 - 关联成员:
ChunkResult.error(), ChunkResult.of()
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
BlockableEventLoop.relayDelayCrash()
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/字段/方法调用/返回值 - 关联成员:
ChunkStatus.getStatusList()
- 引用位置:
-
- 引用位置:
参数
- 引用位置: