2025-11-24 22:52:51 +03:00

165 lines
5.5 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.mojang.logging.LogUtils
* org.jspecify.annotations.Nullable
* org.slf4j.Logger
*/
package net.minecraft.client.multiplayer;
import com.mojang.logging.LogUtils;
import java.util.concurrent.TimeUnit;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.progress.ChunkLoadStatusView;
import net.minecraft.server.level.progress.LevelLoadListener;
import net.minecraft.server.level.progress.LevelLoadProgressTracker;
import net.minecraft.util.Util;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class LevelLoadTracker
implements LevelLoadListener {
private static final Logger LOGGER = LogUtils.getLogger();
private static final long CLIENT_WAIT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(30L);
public static final long LEVEL_LOAD_CLOSE_DELAY_MS = 500L;
private final LevelLoadProgressTracker serverProgressTracker = new LevelLoadProgressTracker(true);
private @Nullable ChunkLoadStatusView serverChunkStatusView;
private volatile @Nullable LevelLoadListener.Stage serverStage;
private @Nullable ClientState clientState;
private final long closeDelayMs;
public LevelLoadTracker() {
this(0L);
}
public LevelLoadTracker(long closeDelayMs) {
this.closeDelayMs = closeDelayMs;
}
public void setServerChunkStatusView(ChunkLoadStatusView serverChunkStatusView) {
this.serverChunkStatusView = serverChunkStatusView;
}
public void startClientLoad(LocalPlayer player, ClientLevel level, LevelRenderer levelRenderer) {
this.clientState = new WaitingForServer(player, level, levelRenderer, Util.getMillis() + CLIENT_WAIT_TIMEOUT_MS);
}
public void tickClientLoad() {
if (this.clientState != null) {
this.clientState = this.clientState.tick();
}
}
/*
* Enabled force condition propagation
* Lifted jumps to return sites
*/
public boolean isLevelReady() {
long readyAt;
ClientState clientState = this.clientState;
if (!(clientState instanceof ClientLevelReady)) return false;
ClientLevelReady clientLevelReady = (ClientLevelReady)clientState;
try {
long l;
readyAt = l = clientLevelReady.readyAt();
}
catch (Throwable throwable) {
throw new MatchException(throwable.toString(), throwable);
}
if (Util.getMillis() < readyAt + this.closeDelayMs) return false;
return true;
}
public void loadingPacketsReceived() {
if (this.clientState != null) {
this.clientState = this.clientState.loadingPacketsReceived();
}
}
@Override
public void start(LevelLoadListener.Stage stage, int totalChunks) {
this.serverProgressTracker.start(stage, totalChunks);
this.serverStage = stage;
}
@Override
public void update(LevelLoadListener.Stage stage, int currentChunks, int totalChunks) {
this.serverProgressTracker.update(stage, currentChunks, totalChunks);
}
@Override
public void finish(LevelLoadListener.Stage stage) {
this.serverProgressTracker.finish(stage);
}
@Override
public void updateFocus(ResourceKey<Level> dimension, ChunkPos chunkPos) {
if (this.serverChunkStatusView != null) {
this.serverChunkStatusView.moveTo(dimension, chunkPos);
}
}
public @Nullable ChunkLoadStatusView statusView() {
return this.serverChunkStatusView;
}
public float serverProgress() {
return this.serverProgressTracker.get();
}
public boolean hasProgress() {
return this.serverStage != null;
}
private record WaitingForServer(LocalPlayer player, ClientLevel level, LevelRenderer levelRenderer, long timeoutAfter) implements ClientState
{
@Override
public ClientState loadingPacketsReceived() {
return new WaitingForPlayerChunk(this.player, this.level, this.levelRenderer, this.timeoutAfter);
}
}
private static sealed interface ClientState
permits WaitingForServer, WaitingForPlayerChunk, ClientLevelReady {
default public ClientState tick() {
return this;
}
default public ClientState loadingPacketsReceived() {
return this;
}
}
private record ClientLevelReady(long readyAt) implements ClientState
{
}
private record WaitingForPlayerChunk(LocalPlayer player, ClientLevel level, LevelRenderer levelRenderer, long timeoutAfter) implements ClientState
{
@Override
public ClientState tick() {
return this.isReady() ? new ClientLevelReady(Util.getMillis()) : this;
}
private boolean isReady() {
if (Util.getMillis() > this.timeoutAfter) {
LOGGER.warn("Timed out while waiting for the client to load chunks, letting the player into the world anyway");
return true;
}
BlockPos playerPos = this.player.blockPosition();
if (this.level.isOutsideBuildHeight(playerPos.getY()) || this.player.isSpectator() || !this.player.isAlive()) {
return true;
}
return this.levelRenderer.isSectionCompiledAndVisible(playerPos);
}
}
}