Merge remote-tracking branch 'origin/1.18' into 1.19.2
This commit is contained in:
commit
117232687a
|
|
@ -63,6 +63,7 @@ public class ModernFixEarlyConfig {
|
||||||
this.addMixinRule("perf.fast_forge_dummies", true);
|
this.addMixinRule("perf.fast_forge_dummies", true);
|
||||||
this.addMixinRule("perf.dynamic_structure_manager", true);
|
this.addMixinRule("perf.dynamic_structure_manager", true);
|
||||||
this.addMixinRule("bugfix.chunk_deadlock", true);
|
this.addMixinRule("bugfix.chunk_deadlock", true);
|
||||||
|
this.addMixinRule("bugfix.paper_chunk_patches", true);
|
||||||
this.addMixinRule("perf.thread_priorities", true);
|
this.addMixinRule("perf.thread_priorities", true);
|
||||||
this.addMixinRule("perf.scan_cache", true);
|
this.addMixinRule("perf.scan_cache", true);
|
||||||
this.addMixinRule("perf.kubejs", modPresent("kubejs"));
|
this.addMixinRule("perf.kubejs", modPresent("kubejs"));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.embeddedt.modernfix.duck;
|
||||||
|
|
||||||
|
public interface IPaperChunkHolder {
|
||||||
|
boolean mfix$canAdvanceStatus();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.bugfix.paper_chunk_patches;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Either;
|
||||||
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import org.embeddedt.modernfix.duck.IPaperChunkHolder;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@Mixin(ChunkHolder.class)
|
||||||
|
public abstract class ChunkHolderMixin implements IPaperChunkHolder {
|
||||||
|
|
||||||
|
@Shadow public abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getFutureIfPresentUnchecked(ChunkStatus arg);
|
||||||
|
|
||||||
|
@Shadow @Final private static List<ChunkStatus> CHUNK_STATUSES;
|
||||||
|
|
||||||
|
public ChunkStatus mfix$getChunkHolderStatus() {
|
||||||
|
for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) {
|
||||||
|
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = this.getFutureIfPresentUnchecked(curr);
|
||||||
|
Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = future.getNow(null);
|
||||||
|
if (either == null || !either.left().isPresent()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkAccess mfix$getAvailableChunkNow() {
|
||||||
|
// TODO can we just getStatusFuture(EMPTY)?
|
||||||
|
for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) {
|
||||||
|
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = this.getFutureIfPresentUnchecked(curr);
|
||||||
|
Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = future.getNow(null);
|
||||||
|
if (either == null || !either.left().isPresent()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return either.left().get();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChunkStatus mfix$getNextStatus(ChunkStatus status) {
|
||||||
|
if (status == ChunkStatus.FULL) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return CHUNK_STATUSES.get(status.getIndex() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mfix$canAdvanceStatus() {
|
||||||
|
ChunkStatus status = mfix$getChunkHolderStatus();
|
||||||
|
ChunkAccess chunk = mfix$getAvailableChunkNow();
|
||||||
|
return chunk != null && (status == null || chunk.getStatus().isOrAfter(mfix$getNextStatus(status)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.bugfix.paper_chunk_patches;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Either;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.level.*;
|
||||||
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
|
import net.minecraft.util.thread.BlockableEventLoop;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||||
|
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||||
|
import org.embeddedt.modernfix.duck.IPaperChunkHolder;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
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.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
|
||||||
|
@Mixin(ChunkMap.class)
|
||||||
|
public abstract class ChunkMapMixin {
|
||||||
|
@Shadow @Final private BlockableEventLoop<Runnable> mainThreadExecutor;
|
||||||
|
|
||||||
|
@Shadow @Final private ChunkMap.DistanceManager distanceManager;
|
||||||
|
|
||||||
|
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> protoChunkToFullChunk(ChunkHolder arg);
|
||||||
|
|
||||||
|
@Shadow @Final private ServerLevel level;
|
||||||
|
@Shadow @Final private ThreadedLevelLightEngine lightEngine;
|
||||||
|
@Shadow @Final private ChunkProgressListener progressListener;
|
||||||
|
|
||||||
|
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> scheduleChunkGeneration(ChunkHolder chunkHolder, ChunkStatus chunkStatus);
|
||||||
|
|
||||||
|
@Shadow @Final private StructureTemplateManager structureTemplateManager;
|
||||||
|
private Executor mainInvokingExecutor;
|
||||||
|
|
||||||
|
@Inject(method = "<init>", at = @At("RETURN"), cancellable = true)
|
||||||
|
private void setup(CallbackInfo ci) {
|
||||||
|
this.mainInvokingExecutor = (runnable) -> {
|
||||||
|
if(ServerLifecycleHooks.getCurrentServer().isSameThread())
|
||||||
|
runnable.run();
|
||||||
|
else
|
||||||
|
this.mainThreadExecutor.execute(runnable);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* https://github.com/PaperMC/Paper/blob/ver/1.17.1/patches/server/0752-Fix-chunks-refusing-to-unload-at-low-TPS.patch */
|
||||||
|
@ModifyArg(method = "prepareAccessibleChunk", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenApplyAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 1)
|
||||||
|
private Executor useMainThreadExecutor(Executor executor) {
|
||||||
|
return this.mainThreadExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://github.com/PaperMC/Paper/blob/master/patches/removed/1.19.2-legacy-chunksystem/0482-Improve-Chunk-Status-Transition-Speed.patch */
|
||||||
|
@ModifyArg(method = "prepareEntityTickingChunk", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenApplyAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 1)
|
||||||
|
private Executor useMainInvokingExecutor(Executor executor) {
|
||||||
|
return this.mainInvokingExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Redirect(method = "scheduleChunkGeneration", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenComposeAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
|
||||||
|
private CompletableFuture skipWorkerIfPossible(CompletableFuture inputFuture, Function function, Executor executor, ChunkHolder holder) {
|
||||||
|
Executor targetExecutor = (runnable) -> {
|
||||||
|
if(((IPaperChunkHolder)holder).mfix$canAdvanceStatus()) {
|
||||||
|
this.mainInvokingExecutor.execute(runnable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
executor.execute(runnable);
|
||||||
|
};
|
||||||
|
return inputFuture.thenComposeAsync(function, targetExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author embeddedt
|
||||||
|
* @reason revert 1.17 chunk system changes, significantly reduces time and RAM needed to load chunks
|
||||||
|
*/
|
||||||
|
@Inject(method = "schedule", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void useLegacySchedulingLogic(ChunkHolder holder, ChunkStatus requiredStatus, CallbackInfoReturnable<CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> cir) {
|
||||||
|
if(requiredStatus != ChunkStatus.EMPTY) {
|
||||||
|
ChunkPos chunkpos = holder.getPos();
|
||||||
|
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = holder.getOrScheduleFuture(requiredStatus.getParent(), (ChunkMap)(Object)this);
|
||||||
|
cir.setReturnValue(future.thenComposeAsync((either) -> {
|
||||||
|
Optional<ChunkAccess> optional = either.left();
|
||||||
|
if(!optional.isPresent())
|
||||||
|
return CompletableFuture.completedFuture(either);
|
||||||
|
|
||||||
|
if (requiredStatus == ChunkStatus.LIGHT) {
|
||||||
|
this.distanceManager.addTicket(TicketType.LIGHT, chunkpos, 33 + ChunkStatus.getDistance(ChunkStatus.LIGHT), chunkpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// from original method
|
||||||
|
if (optional.get().getStatus().isOrAfter(requiredStatus)) {
|
||||||
|
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = requiredStatus.load(this.level, this.structureTemplateManager, this.lightEngine, (arg2) -> {
|
||||||
|
return this.protoChunkToFullChunk(holder);
|
||||||
|
}, (ChunkAccess)optional.get());
|
||||||
|
this.progressListener.onStatusChange(chunkpos, requiredStatus);
|
||||||
|
return completablefuture;
|
||||||
|
} else {
|
||||||
|
return this.scheduleChunkGeneration(holder, requiredStatus);
|
||||||
|
}
|
||||||
|
}, this.mainThreadExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainThreadExecutor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.bugfix.paper_chunk_patches;
|
||||||
|
|
||||||
|
import net.minecraft.util.SortedArraySet;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import java.util.AbstractSet;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@Mixin(SortedArraySet.class)
|
||||||
|
public abstract class SortedArraySetMixin<T> extends AbstractSet<T> {
|
||||||
|
@Shadow private int size;
|
||||||
|
|
||||||
|
@Shadow private T[] contents;
|
||||||
|
|
||||||
|
// Paper start - optimise removeIf
|
||||||
|
@Override
|
||||||
|
public boolean removeIf(Predicate<? super T> filter) {
|
||||||
|
// prev. impl used an iterator, which could be n^2 and creates garbage
|
||||||
|
int i = 0, len = this.size;
|
||||||
|
T[] backingArray = this.contents;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (i >= len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!filter.test(backingArray[i])) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only want to write back to backingArray if we really need to
|
||||||
|
|
||||||
|
int lastIndex = i; // this is where new elements are shifted to
|
||||||
|
|
||||||
|
for (; i < len; ++i) {
|
||||||
|
T curr = backingArray[i];
|
||||||
|
if (!filter.test(curr)) { // if test throws we're screwed
|
||||||
|
backingArray[lastIndex++] = curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup end
|
||||||
|
Arrays.fill(backingArray, lastIndex, len, null);
|
||||||
|
this.size = lastIndex;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,11 @@ public abstract class LegacyUnicodeBitmapsProviderMixin {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/NativeImage;close()V"))
|
||||||
|
private void skipCloseNativeImage(NativeImage image) {
|
||||||
|
/* we can't close here, as the image has been stored for use later */
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void clearLocation(CallbackInfo ci) {
|
private void clearLocation(CallbackInfo ci) {
|
||||||
currentCharIdx = null;
|
currentCharIdx = null;
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,5 @@ public net.minecraft.world.level.block.state.BlockBehaviour$Properties f_60888_
|
||||||
public net.minecraft.server.level.ServerChunkCache$MainThreadExecutor
|
public net.minecraft.server.level.ServerChunkCache$MainThreadExecutor
|
||||||
public net.minecraft.nbt.CompoundTag <init>(Ljava/util/Map;)V # <init>
|
public net.minecraft.nbt.CompoundTag <init>(Ljava/util/Map;)V # <init>
|
||||||
public net.minecraft.client.renderer.texture.TextureAtlasSprite <init>(Lnet/minecraft/client/renderer/texture/TextureAtlas;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$Info;IIIIILcom/mojang/blaze3d/platform/NativeImage;)V # <init>
|
public net.minecraft.client.renderer.texture.TextureAtlasSprite <init>(Lnet/minecraft/client/renderer/texture/TextureAtlas;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$Info;IIIIILcom/mojang/blaze3d/platform/NativeImage;)V # <init>
|
||||||
|
public net.minecraft.server.level.DistanceManager m_140792_(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V # addTicket
|
||||||
|
public net.minecraft.server.level.ChunkMap$DistanceManager
|
||||||
|
|
@ -11,6 +11,9 @@
|
||||||
"perf.modern_resourcepacks.VanillaPackResourcesMixin",
|
"perf.modern_resourcepacks.VanillaPackResourcesMixin",
|
||||||
"perf.modern_resourcepacks.PathPackResourcesMixin",
|
"perf.modern_resourcepacks.PathPackResourcesMixin",
|
||||||
"perf.modern_resourcepacks.ResourceCacheManagerMixin",
|
"perf.modern_resourcepacks.ResourceCacheManagerMixin",
|
||||||
|
"bugfix.paper_chunk_patches.ChunkMapMixin",
|
||||||
|
"bugfix.paper_chunk_patches.ChunkHolderMixin",
|
||||||
|
"bugfix.paper_chunk_patches.SortedArraySetMixin",
|
||||||
"perf.dynamic_structure_manager.StructureManagerMixin",
|
"perf.dynamic_structure_manager.StructureManagerMixin",
|
||||||
"bugfix.chunk_deadlock.ServerChunkCacheMixin",
|
"bugfix.chunk_deadlock.ServerChunkCacheMixin",
|
||||||
"perf.dedicated_reload_executor.MinecraftServerMixin",
|
"perf.dedicated_reload_executor.MinecraftServerMixin",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user