Move 441 chunk loading to after join game packets are sent on integrated server
This commit is contained in:
parent
cb6399e820
commit
bc5b85efcc
|
|
@ -1,14 +1,33 @@
|
|||
package org.embeddedt.modernfix;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.ConnectScreen;
|
||||
import net.minecraft.client.gui.screens.LevelLoadingScreen;
|
||||
import net.minecraft.client.gui.screens.ProgressScreen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.minecraft.client.server.IntegratedServer;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.*;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.ForcedChunksSavedData;
|
||||
import net.minecraftforge.client.event.GuiOpenEvent;
|
||||
import net.minecraftforge.common.world.ForgeChunkManager;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
|
||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
import org.embeddedt.modernfix.screen.DeferredLevelLoadingScreen;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
public class ModernFixClient {
|
||||
|
||||
|
|
@ -42,4 +61,78 @@ public class ModernFixClient {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasFirstPlayerJoined = false;
|
||||
|
||||
@SubscribeEvent
|
||||
public void serverWillStart(FMLServerAboutToStartEvent event) {
|
||||
hasFirstPlayerJoined = false;
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
if(!hasFirstPlayerJoined && integratedWorldLoadListener != null) {
|
||||
hasFirstPlayerJoined = true;
|
||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
||||
if(server instanceof IntegratedServer) {
|
||||
handleInitialChunkLoad();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onWorldShow(GuiOpenEvent event) {
|
||||
if(ServerLifecycleHooks.getCurrentServer() instanceof IntegratedServer && integratedWorldLoadListener != null) {
|
||||
if(event.getGui() == null && Minecraft.getInstance().level != null) {
|
||||
/* this means the world is being displayed, check if 441 initialized */
|
||||
ServerChunkCache provider = ServerLifecycleHooks.getCurrentServer().overworld().getChunkSource();
|
||||
BooleanSupplier worldLoadDone = () -> provider.getTickingGenerated() >= 441;
|
||||
if(!worldLoadDone.getAsBoolean()) {
|
||||
DeferredLevelLoadingScreen newScreen = new DeferredLevelLoadingScreen(Minecraft.getInstance().progressListener.get(), worldLoadDone);
|
||||
event.setGui(newScreen);
|
||||
}
|
||||
} else if(event.getGui() instanceof LevelLoadingScreen && Minecraft.getInstance().level == null) {
|
||||
ProgressScreen loadscreen = new ProgressScreen();
|
||||
loadscreen.progressStartNoAbort(new TranslatableComponent("connect.joining"));
|
||||
event.setGui(loadscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ChunkProgressListener integratedWorldLoadListener;
|
||||
|
||||
private void handleInitialChunkLoad() {
|
||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
||||
ServerLevel overworld = server.overworld();
|
||||
ServerChunkCache provider = overworld.getChunkSource();
|
||||
provider.getLightEngine().setTaskPerBatch(500);
|
||||
provider.addRegionTicket(TicketType.START, new ChunkPos(overworld.getSharedSpawnPos()), 11, Unit.INSTANCE);
|
||||
while(provider.getTickingGenerated() < 441) {
|
||||
server.runAllTasks();
|
||||
Thread.yield();
|
||||
LockSupport.parkNanos("waiting for world load", 100000L);
|
||||
server.nextTickTime = Util.getMillis() + 10;
|
||||
}
|
||||
for(ServerLevel serverworld1 : server.getAllLevels()) {
|
||||
ForcedChunksSavedData forcedchunkssavedata = serverworld1.getDataStorage().get(ForcedChunksSavedData::new, "chunks");
|
||||
if (forcedchunkssavedata != null) {
|
||||
LongIterator longiterator = forcedchunkssavedata.getChunks().iterator();
|
||||
|
||||
while(longiterator.hasNext()) {
|
||||
long i = longiterator.nextLong();
|
||||
ChunkPos chunkpos = new ChunkPos(i);
|
||||
serverworld1.getChunkSource().updateChunkForced(chunkpos, true);
|
||||
}
|
||||
|
||||
ForgeChunkManager.reinstatePersistentChunks(serverworld1, forcedchunkssavedata);
|
||||
}
|
||||
}
|
||||
server.runAllTasks();
|
||||
server.nextTickTime = Util.getMillis() + 10;
|
||||
provider.getLightEngine().setTaskPerBatch(5);
|
||||
if(integratedWorldLoadListener != null) {
|
||||
integratedWorldLoadListener.stop();
|
||||
integratedWorldLoadListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public class ModernFixEarlyConfig {
|
|||
this.addMixinRule("perf.async_locator", true);
|
||||
this.addMixinRule("perf.faster_texture_stitching", true);
|
||||
this.addMixinRule("perf.kubejs", true);
|
||||
this.addMixinRule("perf.faster_singleplayer_load", true);
|
||||
/* Keep this off if JEI isn't installed to prevent breaking vanilla gameplay */
|
||||
this.addMixinRule("perf.blast_search_trees", FMLLoader.getLoadingModList().getModFileById("jei") != null);
|
||||
this.addMixinRule("safety", true);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package org.embeddedt.modernfix.mixin.perf.faster_singleplayer_load;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.server.IntegratedServer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MinecraftServer.class)
|
||||
public abstract class MinecraftServerMixin {
|
||||
@Shadow protected long nextTickTime;
|
||||
|
||||
@Shadow public abstract ServerLevel overworld();
|
||||
|
||||
@Shadow protected abstract void updateMobSpawningFlags();
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason defer the 441 chunk load until *after* join game packets are sent to the client, in order to allow
|
||||
* mods that process advancements, etc. to work on that at the same time
|
||||
*/
|
||||
@Inject(method = "prepareLevels", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getChunkSource()Lnet/minecraft/server/level/ServerChunkCache;", ordinal = 0), cancellable = true)
|
||||
private void skipInitialChunkLoad(ChunkProgressListener arg, CallbackInfo ci) {
|
||||
if(((Object)this) instanceof IntegratedServer) {
|
||||
ci.cancel();
|
||||
ModernFixClient.integratedWorldLoadListener = arg;
|
||||
this.nextTickTime = Util.getMillis();
|
||||
this.overworld().getChunkSource().getLightEngine().setTaskPerBatch(5);
|
||||
this.updateMobSpawningFlags();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package org.embeddedt.modernfix.screen;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.screens.LevelLoadingScreen;
|
||||
import net.minecraft.server.level.progress.StoringChunkProgressListener;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
public class DeferredLevelLoadingScreen extends LevelLoadingScreen {
|
||||
private final BooleanSupplier worldLoadFinished;
|
||||
public DeferredLevelLoadingScreen(StoringChunkProgressListener arg, BooleanSupplier worldLoadFinished) {
|
||||
super(arg);
|
||||
this.worldLoadFinished = worldLoadFinished;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if(this.worldLoadFinished.getAsBoolean())
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBackground(PoseStack matrixStack, int vOffset) {
|
||||
renderDirtBackground(vOffset);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,4 +5,7 @@ public net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase$Cache
|
|||
public net.minecraft.world.phys.shapes.VoxelShape <init>(Lnet/minecraft/util/math/shapes/VoxelShapePart;)V # <init>
|
||||
public net.minecraft.client.resources.model.ModelBakery$BlockStateDefinitionException
|
||||
public net.minecraft.client.renderer.model.ModelBakery field_217849_F # unbakedCache
|
||||
public net.minecraft.client.renderer.texture.Stitcher$Holder
|
||||
public net.minecraft.client.renderer.texture.Stitcher$Holder
|
||||
public net.minecraft.util.concurrent.ThreadTaskExecutor func_213160_bf()V # runAllTasks
|
||||
public net.minecraft.server.MinecraftServer field_211151_aa # nextTickTime
|
||||
public net.minecraft.client.Minecraft field_213277_ad # progressListener
|
||||
|
|
@ -83,7 +83,8 @@
|
|||
"perf.cache_model_materials.MultipartMixin",
|
||||
"perf.faster_texture_stitching.StitcherMixin",
|
||||
"bugfix.packet_leak.ClientPlayNetHandlerMixin",
|
||||
"bugfix.packet_leak.SCustomPayloadPlayPacketMixin"
|
||||
"bugfix.packet_leak.SCustomPayloadPlayPacketMixin",
|
||||
"perf.faster_singleplayer_load.MinecraftServerMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user