Skip to content

Commit

Permalink
Move the registry sync earlier (#363)
Browse files Browse the repository at this point in the history
* Move Registry Sync to the first configuration task that runs.

* Remove extra print

* Move more stuff around. Works in theory now. Not tested

* Better system for task ordering. Fix #362. Fix issue with resource test mod

* Fix vanilla or non-supported clients not being able to connect and issue with regsync always applying

* Bump Version
  • Loading branch information
OroArmor authored Feb 11, 2024
1 parent 5da1018 commit e95b440
Show file tree
Hide file tree
Showing 14 changed files with 287 additions and 53 deletions.
4 changes: 2 additions & 2 deletions build-logic/src/main/java/qsl/internal/Versions.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public final class Versions {
/**
* The QSL version
*/
public static final String QSL_VERSION = "7.0.0-alpha.9";
public static final String QSL_VERSION = "7.0.0-alpha.10";

/**
* The target Minecraft version.
Expand All @@ -43,7 +43,7 @@ public final class Versions {
/**
* The version of Quilt Loader to use.
*/
public static final String LOADER_VERSION = "0.23.0";
public static final String LOADER_VERSION = "0.23.1";

/**
* The target Java version.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ public interface ServerConfigurationTaskManager {
*/
void addTask(ConfigurationTask task);

/**
* Adds a task to the handler that must complete before joining.
* This task will be executed next regardless of whatever other tasks exist.
* This method is useful when you have one task you want to run right after another finishes, like in a state machine.
* This will throw if there is already an immediate task to run.
*
* @param task the task to add
*/
void addImmediateTask(ConfigurationTask task);

/**
* Adds a task with a higher priority to the handler that must complete before joining.
* Priority tasks are executed in the order they are added to the handler.
* All priority tasks will be finished before normal tasks begin executing again.
* If a priority task is added during normal task execution, the handler will switch to executing the priority tasks.
*
* <p>
* Calling this during the {@link ServerConfigurationConnectionEvents#INIT} event might add your tasks before registry sync.
*
* @param task the task to add
*/
void addPriorityTask(ConfigurationTask task);

/**
* Finishes the task of the specified type. Will throw an error if a different or no task is running.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,26 @@
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.payload.CustomPayload;
import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket;
import net.minecraft.network.packet.s2c.common.PingS2CPacket;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;

import org.quiltmc.qsl.networking.api.S2CConfigurationChannelEvents;
import org.quiltmc.qsl.networking.api.ServerConfigurationConnectionEvents;
import org.quiltmc.qsl.networking.api.ServerConfigurationNetworking;
import org.quiltmc.qsl.networking.api.ServerConfigurationTaskManager;
import org.quiltmc.qsl.networking.impl.AbstractChanneledNetworkAddon;
import org.quiltmc.qsl.networking.impl.ChannelInfoHolder;
import org.quiltmc.qsl.networking.impl.NetworkingImpl;
import org.quiltmc.qsl.networking.impl.payload.ChannelPayload;
import org.quiltmc.qsl.networking.mixin.accessor.AbstractServerPacketHandlerAccessor;
import org.quiltmc.qsl.networking.mixin.accessor.ServerConfigurationPacketHandlerAccessor;

@ApiStatus.Internal
public final class ServerConfigurationNetworkAddon extends AbstractChanneledNetworkAddon<ServerConfigurationNetworking.CustomChannelReceiver<?>> {
private final ServerConfigurationPacketHandler handler;
private final MinecraftServer server;
private boolean sentInitialRegisterPacket = false;
public static int PING_ID = 0x0C147; // Somewhat looks like QUILT?

public ServerConfigurationNetworkAddon(ServerConfigurationPacketHandler handler, MinecraftServer server) {
super(ServerNetworkingImpl.CONFIGURATION, ((AbstractServerPacketHandlerAccessor) handler).getConnection(), "ServerConfigurationNetworkAddon for " + handler.getHost().getName());
Expand All @@ -71,14 +73,15 @@ public void onConfigureReady() {
ServerConfigurationConnectionEvents.READY.invoker().onConfigurationReady(this.handler, this, this.server);

this.sendInitialChannelRegistrationPacket();
this.sendPacket(new PingS2CPacket(PING_ID)); // If we get pong before channels, its a vanilla or non-supported client.
this.sentInitialRegisterPacket = true;
}

@Override
public <T extends CustomPayload> boolean handle(T payload) {
boolean handled = super.handle(payload);
if (handled && payload.id().equals(NetworkingImpl.REGISTER_CHANNEL)) {
((ServerConfigurationPacketHandlerAccessor) this.handler).invokeFinishCurrentTask(SendChannelsTask.TYPE);
((ServerConfigurationTaskManager) this.handler).finishTask(SendChannelsTask.TYPE);
}

return handled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import net.minecraft.network.ClientConnection;
import net.minecraft.network.ServerConfigurationPacketHandler;
import net.minecraft.network.listener.AbstractServerPacketHandler;
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
import net.minecraft.network.packet.c2s.common.PongC2SPacket;
import net.minecraft.server.MinecraftServer;

import org.quiltmc.qsl.networking.api.ServerConfigurationTaskManager;
import org.quiltmc.qsl.networking.impl.AbstractChanneledNetworkAddon;
import org.quiltmc.qsl.networking.impl.NetworkHandlerExtensions;
import org.quiltmc.qsl.networking.impl.server.SendChannelsTask;
import org.quiltmc.qsl.networking.impl.server.ServerConfigurationNetworkAddon;

// We want to apply a bit earlier than other mods which may not use us in order to prevent refCount issues
@Mixin(value = AbstractServerPacketHandler.class, priority = 999)
Expand All @@ -50,4 +55,13 @@ private void handleCustomPayloadReceivedAsync(CustomPayloadC2SPacket packet, Cal
ci.cancel();
}
}

@Inject(method = "onPlayPong", at = @At("TAIL"))
private void handlePong(PongC2SPacket packet, CallbackInfo ci) {
if (((Object) this) instanceof ServerConfigurationPacketHandler configurationHandler && packet.getParameter() == ServerConfigurationNetworkAddon.PING_ID) {
if (((ServerConfigurationTaskManager) configurationHandler).getCurrentTask() instanceof SendChannelsTask) {
((ServerConfigurationTaskManager) configurationHandler).finishTask(SendChannelsTask.TYPE); // Vanilla or non-supported client connection.
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
package org.quiltmc.qsl.networking.mixin;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;

import com.llamalad7.mixinextras.injector.ModifyReceiver;
import com.llamalad7.mixinextras.injector.WrapWithCondition;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
Expand All @@ -44,8 +49,9 @@
import org.quiltmc.qsl.networking.impl.server.ServerConfigurationNetworkAddon;

// We want to apply a bit earlier than other mods which may not use us in order to prevent refCount issues
@Mixin(value = ServerConfigurationPacketHandler.class, priority = 999)
@Mixin(value = ServerConfigurationPacketHandler.class, priority = 900)
abstract class ServerConfigurationPacketHandlerMixin extends AbstractServerPacketHandler implements NetworkHandlerExtensions, DisconnectPacketSource, ServerConfigurationTaskManager {
@Mutable
@Shadow
@Final
private Queue<ConfigurationTask> tasks;
Expand All @@ -56,9 +62,24 @@ abstract class ServerConfigurationPacketHandlerMixin extends AbstractServerPacke
@Shadow
protected abstract void finishCurrentTask(ConfigurationTask.Type taskType);

@Shadow
public abstract void startConfiguration();

@Shadow
protected abstract void startNextTask();

@Unique
private ServerConfigurationNetworkAddon addon;

@Unique
private boolean sentConfiguration = false;

@Unique
private ConfigurationTask immediateTask = null;

@Unique
private Queue<ConfigurationTask> priorityTasks = new ConcurrentLinkedQueue<>();

ServerConfigurationPacketHandlerMixin(MinecraftServer server, ClientConnection connection, C_eyqfalbd c_eyqfalbd) {
super(server, connection, c_eyqfalbd);
}
Expand All @@ -70,9 +91,51 @@ private void initAddon(CallbackInfo ci) {
this.addon.lateInit();
}

@Inject(method = "startConfiguration", at = @At("HEAD"))
@Inject(method = "startConfiguration", at = @At("HEAD"), cancellable = true)
private void start(CallbackInfo ci) {
this.tasks.add(new SendChannelsTask(this.addon));
if (!this.sentConfiguration) {
this.addImmediateTask(new SendChannelsTask(this.addon));

this.addPriorityTask(new ConfigurationTask() {
static final Type TYPE = new Type("minecraft:start_configuration");

@Override
public void start(Consumer<Packet<?>> task) {
ServerConfigurationPacketHandlerMixin.this.startConfiguration();
ServerConfigurationPacketHandlerMixin.this.finishTask(TYPE);
}

@Override
public Type getType() {
return TYPE;
}
});

this.sentConfiguration = true;
this.startNextTask();
ci.cancel();
}
}

@WrapWithCondition(method = "startConfiguration", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ServerConfigurationPacketHandler;startNextTask()V"))
private boolean doNotCallStart(ServerConfigurationPacketHandler handler) {
return false;
}

@ModifyReceiver(method = "startNextTask", at = @At(value = "INVOKE", target = "Ljava/util/Queue;poll()Ljava/lang/Object;"))
private Queue<ConfigurationTask> modifyTaskQueue(Queue<ConfigurationTask> originalQueue) {
if (this.immediateTask != null) {
var singleQueue = new ConcurrentLinkedQueue<ConfigurationTask>();
singleQueue.add(this.immediateTask);
this.immediateTask = null;
return singleQueue;
}

if (!this.priorityTasks.isEmpty()) {
return this.priorityTasks;
}

return originalQueue;
}

@Inject(method = "onDisconnected", at = @At("HEAD"))
Expand All @@ -95,6 +158,23 @@ public void addTask(ConfigurationTask task) {
this.tasks.add(task);
}

@Override
public void addPriorityTask(ConfigurationTask task) {
this.priorityTasks.add(task);
}

@Override
public void addImmediateTask(ConfigurationTask task) {
if (this.immediateTask != null) {
throw new RuntimeException(
"Cannot add an immediate task of type: \"" + task.getType()
+ "\" when there is already an immediate task of type: \"" + this.immediateTask.getType() + "\"."
);
}

this.immediateTask = task;
}

@Override
public void finishTask(ConfigurationTask.Type type) {
this.finishCurrentTask(type);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"accessor.CustomPayloadC2SPacketAccessor",
"accessor.CustomPayloadS2CPacketAccessor",
"accessor.EntityTrackerAccessor",
"accessor.ServerConfigurationPacketHandlerAccessor",
"accessor.ServerLoginNetworkHandlerAccessor",
"accessor.ThreadedChunkManagerAccessor"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public void onInitialize(ModContainer mod) {
Registries.VILLAGER_PROFESSION
);

ServerConfigurationConnectionEvents.ADD_TASKS.register((handler, server) -> {
((ServerConfigurationTaskManager) handler).addTask(new SetupSyncTask(handler));
ServerConfigurationConnectionEvents.INIT.register((handler, server) -> {
((ServerConfigurationTaskManager) handler).addPriorityTask(new SetupSyncTask(handler));
});

ServerRegistrySync.registerHandlers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ private static void handleModProtocol(MinecraftClient client, ClientConfiguratio
for (var protocol : modProtocol.protocols()) {
var local = ModProtocolImpl.getVersion(protocol.id());
var latest = protocol.latestMatchingVersion(local);
System.out.println(latest);
if (latest != ProtocolVersions.NO_PROTOCOL) {
values.put(protocol.id(), latest);
} else if (!protocol.optional()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,17 @@ public record SetupSyncTask(ServerConfigurationPacketHandler handler) implements

@Override
public void start(Consumer<Packet<?>> task) {
// First check if Quilt sync is available
if (ServerConfigurationNetworking.getSendable(this.handler).contains(ServerPackets.Handshake.ID)) {
((ServerConfigurationTaskManager) this.handler).addTask(new QuiltSyncTask(this.handler, ((AbstractServerPacketHandlerAccessor) this.handler).getConnection()));
} else if (ServerRegistrySync.forceFabricFallback || (ServerRegistrySync.supportFabric && ServerConfigurationNetworking.getSendable(this.handler).contains(ServerFabricRegistrySync.ID))) {
FabricSyncTask fabricSyncTask = new FabricSyncTask(this.handler);
ServerConfigurationNetworking.registerReceiver(this.handler, ServerFabricRegistrySync.SYNC_COMPLETE_ID, (server, handler, buf, responseSender) -> fabricSyncTask.handleComplete());
((ServerConfigurationTaskManager) this.handler).addTask(fabricSyncTask);
} else {
((AbstractServerPacketHandlerAccessor) this.handler).getConnection().disconnect(ServerRegistrySync.noRegistrySyncMessage);
if (ServerRegistrySync.shouldSync()) {
// First check if Quilt sync is available
if (ServerConfigurationNetworking.getSendable(this.handler).contains(ServerPackets.Handshake.ID)) {
((ServerConfigurationTaskManager) this.handler).addImmediateTask(new QuiltSyncTask(this.handler, ((AbstractServerPacketHandlerAccessor) this.handler).getConnection()));
} else if (ServerRegistrySync.forceFabricFallback || (ServerRegistrySync.supportFabric && ServerConfigurationNetworking.getSendable(this.handler).contains(ServerFabricRegistrySync.ID))) {
FabricSyncTask fabricSyncTask = new FabricSyncTask(this.handler);
ServerConfigurationNetworking.registerReceiver(this.handler, ServerFabricRegistrySync.SYNC_COMPLETE_ID, (server, handler, buf, responseSender) -> fabricSyncTask.handleComplete());
((ServerConfigurationTaskManager) this.handler).addImmediateTask(fabricSyncTask);
} else {
((AbstractServerPacketHandlerAccessor) this.handler).getConnection().disconnect(ServerRegistrySync.noRegistrySyncMessage);
}
}

((ServerConfigurationTaskManager) this.handler).finishTask(TYPE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
public class MultiplayerServerListPingerMixin {
@ModifyArgs(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/lang/String;ILnet/minecraft/network/listener/ClientQueryPacketListener;)V"))
private void quilt$attachModProtocol(Args args, ServerInfo entry, Runnable pinger) {
var queryPacketListener = (ClientQueryPacketListener) args.get(0);
args.set(0, new ClientQueryPacketListener() {
var queryPacketListener = (ClientQueryPacketListener) args.get(2);
args.set(2, new ClientQueryPacketListener() {
@Override
public void onServerMetadata(ServerMetadataS2CPacket packet) {
if (packet.status().version().isPresent()) {
Expand Down
Loading

0 comments on commit e95b440

Please sign in to comment.