Make integrated server treat game as paused while singleplayer client is still loading
This commit is contained in:
parent
38288d5e6a
commit
f79eae8b83
|
|
@ -0,0 +1,36 @@
|
|||
package org.embeddedt.modernfix.common.mixin.perf.suspend_integrated_server_during_load;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.duck.suspend_integrated_server_during_load.IDeferrableIntegratedServer;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ClientPacketListener.class)
|
||||
@ClientOnlyMixin
|
||||
public class ClientPacketListenerMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private Minecraft minecraft;
|
||||
|
||||
@Inject(method = "handleCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
private void detectClientLoadSentinel(ClientboundCustomPayloadPacket packet, CallbackInfo ci) {
|
||||
if (packet.getIdentifier().equals(IDeferrableIntegratedServer.CLIENT_LOAD_SENTINEL)) {
|
||||
// Important: flag must be changed on the client thread, as later packets can start decoding
|
||||
// while earlier ones are still being applied.
|
||||
this.minecraft.executeIfPossible(() -> {
|
||||
packet.getData().release();
|
||||
if (this.minecraft.hasSingleplayerServer()) {
|
||||
((IDeferrableIntegratedServer)this.minecraft.getSingleplayerServer()).mfix$markClientLoadFinished();
|
||||
}
|
||||
});
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package org.embeddedt.modernfix.common.mixin.perf.suspend_integrated_server_during_load;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.server.IntegratedServer;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.duck.suspend_integrated_server_during_load.IDeferrableIntegratedServer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@Mixin(IntegratedServer.class)
|
||||
@ClientOnlyMixin
|
||||
public abstract class IntegratedServerMixin implements IDeferrableIntegratedServer {
|
||||
private final AtomicBoolean mfix$hasPrimaryClientJoined = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Wait to be finished processing all expensive packets (recipes, tags, etc.)
|
||||
* before continuing to tick the integrated server.
|
||||
*/
|
||||
@WrapOperation(method = "tickServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;isPaused()Z", ordinal = 0))
|
||||
private boolean preventTicks(Minecraft instance, Operation<Boolean> original) {
|
||||
return !mfix$hasPrimaryClientJoined.get() || original.call(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mfix$markClientLoadFinished() {
|
||||
mfix$hasPrimaryClientJoined.set(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.embeddedt.modernfix.common.mixin.perf.suspend_integrated_server_during_load;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.duck.suspend_integrated_server_during_load.IDeferrableIntegratedServer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerList.class)
|
||||
@ClientOnlyMixin
|
||||
public class PlayerListMixin {
|
||||
@Inject(method = "placeNewPlayer", at = @At("RETURN"))
|
||||
private void sendConfigFinishedSentinelPacket(Connection connection, ServerPlayer player, CallbackInfo ci) {
|
||||
if (connection.isMemoryConnection()) {
|
||||
FriendlyByteBuf friendlybytebuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
player.connection.send(new ClientboundCustomPayloadPacket(IDeferrableIntegratedServer.CLIENT_LOAD_SENTINEL, friendlybytebuf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.embeddedt.modernfix.duck.suspend_integrated_server_during_load;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
|
||||
public interface IDeferrableIntegratedServer {
|
||||
ResourceLocation CLIENT_LOAD_SENTINEL = new ResourceLocation(ModernFix.MODID, "mark_client_load_finished");
|
||||
|
||||
void mfix$markClientLoadFinished();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user