Avoid resets

This commit is contained in:
Adrian Bergqvist 2023-11-28 00:13:06 +01:00
parent ba3132c1bd
commit 55e0a66122
No known key found for this signature in database
GPG Key ID: FAE7D8EDE225E686
5 changed files with 76 additions and 24 deletions

View File

@ -2,25 +2,19 @@ package org.adde0109.ambassador.forge;
import org.adde0109.ambassador.forge.packet.ModListPacket;
import org.adde0109.ambassador.forge.packet.ModListReplyPacket;
import org.adde0109.ambassador.forge.packet.RegistryPacket;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.Checksum;
public class ForgeHandshake {
private ModListPacket modListPacket;
private ModListReplyPacket modListReplyPacket;
private final Checksum registryChecksum = new Adler32();
public ForgeHandshake() {
}
public ModListPacket getModListPacket() {
return modListPacket;
}
public void setModListPacket(ModListPacket modListPacket) {
this.modListPacket = modListPacket;
}
public ModListReplyPacket getModListReplyPacket() {
return modListReplyPacket;
}
@ -28,4 +22,12 @@ public class ForgeHandshake {
public void setModListReplyPacket(ModListReplyPacket modListReplyPacket) {
this.modListReplyPacket = modListReplyPacket;
}
public void addRegistry(RegistryPacket packet) {
registryChecksum.update(packet.getSnapshot());
}
public Checksum getRegistryChecksum() {
return registryChecksum;
}
}

View File

@ -9,10 +9,15 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.AvailableCommands;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import org.adde0109.ambassador.forge.packet.Context;
import org.adde0109.ambassador.forge.packet.IForgeLoginWrapperPacket;
import org.adde0109.ambassador.forge.packet.*;
import org.adde0109.ambassador.forge.pipeline.CommandDecoderErrorCatcher;
import org.adde0109.ambassador.forge.pipeline.ForgeLoginWrapperCodec;
import org.checkerframework.checker.units.qual.A;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.zip.Adler32;
import java.util.zip.Checksum;
public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhase {
NOT_STARTED() {
@ -54,7 +59,8 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
}
};
public Checksum registryChecksum;
CountDownLatch remainingRegistries;
VelocityForgeBackendConnectionPhase() {
}
@ -66,17 +72,46 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
//Reset client if not ready to receive new handshake
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
if (clientPhase != VelocityForgeClientConnectionPhase.NOT_STARTED) {
if (clientPhase == VelocityForgeClientConnectionPhase.RESETTABLE) {
//Initial Forge
//Forge -> Forge
clientPhase.resetConnectionPhase(player);
if (clientPhase == VelocityForgeClientConnectionPhase.COMPLETE)
{
//Do not continue if the client can't reset.
return;
}
if (clientPhase != VelocityForgeClientConnectionPhase.COMPLETE) {
if (message instanceof ModListPacket modListPacket) {
clientPhase.forgeHandshake = new ForgeHandshake();
}
if (message instanceof RegistryPacket registryPacket) {
clientPhase.forgeHandshake.addRegistry(registryPacket);
}
player.getConnection().write(message);
} else {
if (message instanceof ModListPacket modListPacket) {
registryChecksum = new Adler32();
remainingRegistries = new CountDownLatch(modListPacket.getRegistries().size());
CompletableFuture.runAsync(() -> {
try {
remainingRegistries.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).thenAcceptAsync((v) -> {
if (clientPhase.forgeHandshake.getRegistryChecksum().getValue() == registryChecksum.getValue()) {
server.ensureConnected().write(clientPhase.forgeHandshake.getModListReplyPacket());
} else {
//Player needs to be kicked in order to continue.
server.disconnect();
}
}, server.ensureConnected().eventLoop());
} else if (message instanceof RegistryPacket registryPacket) {
server.getConnection().write(new ACKPacket(Context.createContext(message.getContext().getResponseID(), true)));
registryChecksum.update(registryPacket.getSnapshot());
remainingRegistries.countDown();
} else if (message instanceof ConfigDataPacket) {
server.getConnection().write(new ACKPacket(Context.createContext(message.getContext().getResponseID(), true)));
}
}
player.getConnection().write(message);
//Forge server
//To avoid unnecessary resets, we wait until we get the handshake even if we know that we should
//reset because that the previous server was Forge.

View File

@ -22,6 +22,7 @@ import org.adde0109.ambassador.velocity.client.FML2CRPMResetCompleteDecoder;
import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
import javax.swing.*;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
@ -144,18 +145,20 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
public boolean consideredComplete() {
return true;
}
public void complete(ConnectedPlayer player, boolean resettable) { }
};
public ModListReplyPacket clientModList;
public ForgeHandshake forgeHandshake = new ForgeHandshake();
public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket<Context.ClientContext> msg, VelocityServerConnection server) {
player.setPhase(nextPhase());
if (msg instanceof ModListReplyPacket replyPacket) {
ModInfo modInfo = new ModInfo("FML2", replyPacket.getMods().stream().map(
(v) -> new ModInfo.Mod(v,"1")).toList());
player.setModInfo(modInfo);
this.clientModList = replyPacket;
forgeHandshake.setModListReplyPacket(replyPacket);
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
complete(player);
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true);
@ -165,6 +168,10 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
}
player.getConnectionInFlight().getConnection().write(msg);
player.setPhase(nextPhase());
nextPhase().forgeHandshake = this.forgeHandshake;
return true;
}
@ -181,11 +188,11 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
if (resettable) {
player.setPhase(RESETTABLE);
RESETTABLE.onTransitionToNewPhase(player);
RESETTABLE.clientModList = clientModList;
RESETTABLE.forgeHandshake = forgeHandshake;
} else {
player.setPhase(COMPLETE);
COMPLETE.onTransitionToNewPhase(player);
COMPLETE.clientModList = clientModList;
COMPLETE.forgeHandshake = forgeHandshake;
}
}

View File

@ -95,5 +95,8 @@ public class ModListPacket implements IForgeLoginWrapperPacket<Context> {
return channels;
}
public List<String> getRegistries() {
return registries;
}
}

View File

@ -7,6 +7,7 @@ import io.netty.buffer.Unpooled;
public class RegistryPacket implements IForgeLoginWrapperPacket<Context> {
private final String registryName;
private final byte[] snapshot;
private final Context context;
@ -48,4 +49,8 @@ public class RegistryPacket implements IForgeLoginWrapperPacket<Context> {
public Context getContext() {
return context;
}
public byte[] getSnapshot() {
return snapshot;
}
}