Avoid resets
This commit is contained in:
parent
ba3132c1bd
commit
55e0a66122
|
|
@ -2,25 +2,19 @@ package org.adde0109.ambassador.forge;
|
||||||
|
|
||||||
import org.adde0109.ambassador.forge.packet.ModListPacket;
|
import org.adde0109.ambassador.forge.packet.ModListPacket;
|
||||||
import org.adde0109.ambassador.forge.packet.ModListReplyPacket;
|
import org.adde0109.ambassador.forge.packet.ModListReplyPacket;
|
||||||
|
import org.adde0109.ambassador.forge.packet.RegistryPacket;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.zip.Adler32;
|
||||||
|
import java.util.zip.Checksum;
|
||||||
|
|
||||||
public class ForgeHandshake {
|
public class ForgeHandshake {
|
||||||
|
|
||||||
private ModListPacket modListPacket;
|
|
||||||
private ModListReplyPacket modListReplyPacket;
|
private ModListReplyPacket modListReplyPacket;
|
||||||
|
private final Checksum registryChecksum = new Adler32();
|
||||||
|
|
||||||
public ForgeHandshake() {
|
public ForgeHandshake() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModListPacket getModListPacket() {
|
|
||||||
return modListPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModListPacket(ModListPacket modListPacket) {
|
|
||||||
this.modListPacket = modListPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModListReplyPacket getModListReplyPacket() {
|
public ModListReplyPacket getModListReplyPacket() {
|
||||||
return modListReplyPacket;
|
return modListReplyPacket;
|
||||||
}
|
}
|
||||||
|
|
@ -28,4 +22,12 @@ public class ForgeHandshake {
|
||||||
public void setModListReplyPacket(ModListReplyPacket modListReplyPacket) {
|
public void setModListReplyPacket(ModListReplyPacket modListReplyPacket) {
|
||||||
this.modListReplyPacket = modListReplyPacket;
|
this.modListReplyPacket = modListReplyPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addRegistry(RegistryPacket packet) {
|
||||||
|
registryChecksum.update(packet.getSnapshot());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Checksum getRegistryChecksum() {
|
||||||
|
return registryChecksum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,15 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.protocol.packet.AvailableCommands;
|
import com.velocitypowered.proxy.protocol.packet.AvailableCommands;
|
||||||
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
|
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
|
||||||
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
||||||
import org.adde0109.ambassador.forge.packet.Context;
|
import org.adde0109.ambassador.forge.packet.*;
|
||||||
import org.adde0109.ambassador.forge.packet.IForgeLoginWrapperPacket;
|
|
||||||
import org.adde0109.ambassador.forge.pipeline.CommandDecoderErrorCatcher;
|
import org.adde0109.ambassador.forge.pipeline.CommandDecoderErrorCatcher;
|
||||||
import org.adde0109.ambassador.forge.pipeline.ForgeLoginWrapperCodec;
|
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 {
|
public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhase {
|
||||||
NOT_STARTED() {
|
NOT_STARTED() {
|
||||||
|
|
@ -54,7 +59,8 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public Checksum registryChecksum;
|
||||||
|
CountDownLatch remainingRegistries;
|
||||||
|
|
||||||
VelocityForgeBackendConnectionPhase() {
|
VelocityForgeBackendConnectionPhase() {
|
||||||
}
|
}
|
||||||
|
|
@ -66,17 +72,46 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
|
||||||
|
|
||||||
//Reset client if not ready to receive new handshake
|
//Reset client if not ready to receive new handshake
|
||||||
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
|
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
|
||||||
if (clientPhase != VelocityForgeClientConnectionPhase.NOT_STARTED) {
|
if (clientPhase == VelocityForgeClientConnectionPhase.RESETTABLE) {
|
||||||
//Initial Forge
|
//Initial Forge
|
||||||
//Forge -> Forge
|
//Forge -> Forge
|
||||||
clientPhase.resetConnectionPhase(player);
|
clientPhase.resetConnectionPhase(player);
|
||||||
if (clientPhase == VelocityForgeClientConnectionPhase.COMPLETE)
|
}
|
||||||
{
|
|
||||||
//Do not continue if the client can't reset.
|
if (clientPhase != VelocityForgeClientConnectionPhase.COMPLETE) {
|
||||||
return;
|
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
|
//Forge server
|
||||||
//To avoid unnecessary resets, we wait until we get the handshake even if we know that we should
|
//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.
|
//reset because that the previous server was Forge.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import org.adde0109.ambassador.velocity.client.FML2CRPMResetCompleteDecoder;
|
||||||
import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
|
import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
|
||||||
import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
|
import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
@ -144,18 +145,20 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
||||||
public boolean consideredComplete() {
|
public boolean consideredComplete() {
|
||||||
return true;
|
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) {
|
public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket<Context.ClientContext> msg, VelocityServerConnection server) {
|
||||||
player.setPhase(nextPhase());
|
|
||||||
|
|
||||||
if (msg instanceof ModListReplyPacket replyPacket) {
|
if (msg instanceof ModListReplyPacket replyPacket) {
|
||||||
ModInfo modInfo = new ModInfo("FML2", replyPacket.getMods().stream().map(
|
ModInfo modInfo = new ModInfo("FML2", replyPacket.getMods().stream().map(
|
||||||
(v) -> new ModInfo.Mod(v,"1")).toList());
|
(v) -> new ModInfo.Mod(v,"1")).toList());
|
||||||
player.setModInfo(modInfo);
|
player.setModInfo(modInfo);
|
||||||
this.clientModList = replyPacket;
|
forgeHandshake.setModListReplyPacket(replyPacket);
|
||||||
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
|
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
|
||||||
complete(player);
|
complete(player);
|
||||||
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true);
|
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true);
|
||||||
|
|
@ -165,6 +168,10 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
||||||
}
|
}
|
||||||
|
|
||||||
player.getConnectionInFlight().getConnection().write(msg);
|
player.getConnectionInFlight().getConnection().write(msg);
|
||||||
|
|
||||||
|
player.setPhase(nextPhase());
|
||||||
|
nextPhase().forgeHandshake = this.forgeHandshake;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,11 +188,11 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
||||||
if (resettable) {
|
if (resettable) {
|
||||||
player.setPhase(RESETTABLE);
|
player.setPhase(RESETTABLE);
|
||||||
RESETTABLE.onTransitionToNewPhase(player);
|
RESETTABLE.onTransitionToNewPhase(player);
|
||||||
RESETTABLE.clientModList = clientModList;
|
RESETTABLE.forgeHandshake = forgeHandshake;
|
||||||
} else {
|
} else {
|
||||||
player.setPhase(COMPLETE);
|
player.setPhase(COMPLETE);
|
||||||
COMPLETE.onTransitionToNewPhase(player);
|
COMPLETE.onTransitionToNewPhase(player);
|
||||||
COMPLETE.clientModList = clientModList;
|
COMPLETE.forgeHandshake = forgeHandshake;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,5 +95,8 @@ public class ModListPacket implements IForgeLoginWrapperPacket<Context> {
|
||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getRegistries() {
|
||||||
|
return registries;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import io.netty.buffer.Unpooled;
|
||||||
public class RegistryPacket implements IForgeLoginWrapperPacket<Context> {
|
public class RegistryPacket implements IForgeLoginWrapperPacket<Context> {
|
||||||
|
|
||||||
private final String registryName;
|
private final String registryName;
|
||||||
|
|
||||||
private final byte[] snapshot;
|
private final byte[] snapshot;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
@ -48,4 +49,8 @@ public class RegistryPacket implements IForgeLoginWrapperPacket<Context> {
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] getSnapshot() {
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user