Ensure exceptions thrown in chunk load events are not dropped
This commit is contained in:
parent
bee4536c1a
commit
ac8d93d5b9
|
|
@ -4,6 +4,8 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
|||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.util.thread.BlockableEventLoop;
|
||||
|
|
@ -19,10 +21,12 @@ import org.spongepowered.asm.mixin.Unique;
|
|||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
|
@ -39,6 +43,9 @@ public abstract class ChunkMapLoadMixin {
|
|||
@Unique
|
||||
private static final ThreadLocal<CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> MFIX_SURROGATE_FUTURE = new ThreadLocal<>();
|
||||
|
||||
@Unique
|
||||
private final ConcurrentLinkedQueue<Throwable> mfix$promotionExceptions = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason This redirect makes several changes to how full chunk promotion works. First of all, promotion runs
|
||||
|
|
@ -72,7 +79,14 @@ public abstract class ChunkMapLoadMixin {
|
|||
}
|
||||
}, this.mainThreadExecutor).whenComplete((either, throwable) -> {
|
||||
if (throwable != null) {
|
||||
surrogate.completeExceptionally(throwable);
|
||||
if (!surrogate.isDone()) {
|
||||
surrogate.completeExceptionally(throwable);
|
||||
} else {
|
||||
// The chunk has already become visible at FULL status, so we
|
||||
// track the exception ourselves and manually rethrow it at the right point
|
||||
// to trigger a server crash
|
||||
this.mfix$promotionExceptions.add(throwable);
|
||||
}
|
||||
} else {
|
||||
surrogate.complete(either);
|
||||
}
|
||||
|
|
@ -95,6 +109,19 @@ public abstract class ChunkMapLoadMixin {
|
|||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick()V", at = @At("HEAD"))
|
||||
private void reportDeferredPromotionException(CallbackInfo ci) {
|
||||
var throwable = this.mfix$promotionExceptions.poll();
|
||||
if (throwable == null) {
|
||||
return;
|
||||
}
|
||||
if (throwable instanceof ReportedException e) {
|
||||
throw e;
|
||||
} else {
|
||||
throw new ReportedException(CrashReport.forThrowable(throwable, "Exception during promotion of chunk to FULL status"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we also preserve the legacy currentlyLoading field to keep Forge parity
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user