Added handler for third party registry messages

This commit is contained in:
Adrian Bergqvist 2024-02-12 12:18:41 +01:00
parent 89372a4a3c
commit 4b838990a6
No known key found for this signature in database
GPG Key ID: 3B3DA43224B79417
4 changed files with 94 additions and 66 deletions

View File

@ -6,8 +6,8 @@ import com.google.common.io.ByteStreams;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.handler.codec.DecoderException;
import org.adde0109.ambassador.forge.packet.Context; import org.adde0109.ambassador.forge.packet.Context;
import org.adde0109.ambassador.forge.packet.GenericForgeLoginWrapperPacket;
import org.adde0109.ambassador.forge.packet.IForgeLoginWrapperPacket; import org.adde0109.ambassador.forge.packet.IForgeLoginWrapperPacket;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -117,37 +117,59 @@ public class ForgeHandshakeUtils {
return stream.toByteArray(); return stream.toByteArray();
} }
public static class SilentGearUtils { public static class ThirdPartyRegistryUtils {
public static boolean isSilentGearPacket(byte[] data) {
ByteBuf buf = Unpooled.wrappedBuffer(data); static enum ThirdPartyChannel {
String channel = null; SILENTGEAR_NETWORK {
try { @Override
channel = ProtocolUtils.readString(buf); public ThirdPartyRegistryUtils.ACKPacket generateResponsePacket(Context.ClientContext context) {
} catch (DecoderException e) { return new ACKPacket(context, 3);
} finally { }
buf.release(); },
} ZETA_MAIN {
return channel != null && channel.equals("silentgear:network"); @Override
public ThirdPartyRegistryUtils.ACKPacket generateResponsePacket(Context.ClientContext context) {
return new ACKPacket(context, 99);
}
};
abstract public ACKPacket generateResponsePacket(Context.ClientContext context);
} }
public static class ACKPacket implements IForgeLoginWrapperPacket<Context.ClientContext> { static boolean isThirdPartyPacket(GenericForgeLoginWrapperPacket<Context> packet) {
private final Context.ClientContext context; try {
Enum.valueOf(ThirdPartyChannel.class,
public ACKPacket(Context.ClientContext context) { packet.getContext().getChannelName().replace(':', '_').toUpperCase());
this.context = context; return true;
} catch (IllegalArgumentException e) {
return false;
} }
@Override }
static ThirdPartyChannel getThirdPartyChannel(GenericForgeLoginWrapperPacket<Context> packet) {
return Enum.valueOf(ThirdPartyChannel.class,
packet.getContext().getChannelName().replace(':', '_').toUpperCase());
}
static class ACKPacket implements IForgeLoginWrapperPacket<Context.ClientContext> {
private final Context.ClientContext context;
private final int packetID;
ACKPacket(Context.ClientContext context, int packetID) {
this.context = context;
this.packetID = packetID;
}
public ByteBuf encode() { public ByteBuf encode() {
ByteBuf buf = Unpooled.buffer(); ByteBuf buf = Unpooled.buffer();
ProtocolUtils.writeVarInt(buf, 3); ProtocolUtils.writeVarInt(buf, packetID);
return buf; return buf;
} }
@Override @Override
public Context.ClientContext getContext() { public Context.ClientContext getContext() {
return context; return null;
} }
} }
} }

View File

@ -62,7 +62,7 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
VelocityForgeBackendConnectionPhase() { VelocityForgeBackendConnectionPhase() {
} }
public void handle(VelocityServerConnection server, ConnectedPlayer player, IForgeLoginWrapperPacket message) { public void handle(VelocityServerConnection server, ConnectedPlayer player, IForgeLoginWrapperPacket<Context> message) {
VelocityForgeBackendConnectionPhase newPhase = getNewPhase(server,message); VelocityForgeBackendConnectionPhase newPhase = getNewPhase(server,message);
server.setConnectionPhase(newPhase); server.setConnectionPhase(newPhase);
@ -137,10 +137,9 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
remainingRegistries.countDown(); remainingRegistries.countDown();
} else if (message instanceof ConfigDataPacket) { } else if (message instanceof ConfigDataPacket) {
server.getConnection().write(new ACKPacket(Context.fromContext(message.getContext(), true))); server.getConnection().write(new ACKPacket(Context.fromContext(message.getContext(), true)));
} else if (message instanceof GenericForgeLoginWrapperPacket<?> packet } else if (message instanceof GenericForgeLoginWrapperPacket<Context> packet
&& ForgeHandshakeUtils.SilentGearUtils.isSilentGearPacket(packet.getContent())) { && ForgeHandshakeUtils.ThirdPartyRegistryUtils.isThirdPartyPacket(packet)) {
server.getConnection().write(new ForgeHandshakeUtils.SilentGearUtils.ACKPacket( server.getConnection().write(ForgeHandshakeUtils.ThirdPartyRegistryUtils.getThirdPartyChannel(packet));
Context.fromContext(message.getContext(), true)));
} }
} }
//Forge server //Forge server

View File

@ -4,31 +4,38 @@ public class Context {
private final int responseID; private final int responseID;
private Context(int responseID) { private final String channelName;
private Context(int responseID, String channelName) {
this.responseID = responseID; this.responseID = responseID;
this.channelName = channelName;
} }
public static Context createContext(int responseID) { public static Context createContext(int responseID, String channelName) {
return new Context(responseID); return new Context(responseID, channelName);
} }
public static ClientContext createClientContext(int responseID, boolean clientSuccess) { public static ClientContext createClientContext(int responseID, boolean clientSuccess, String channelName) {
return new ClientContext(responseID,clientSuccess); return new ClientContext(responseID, clientSuccess, channelName);
} }
public static ClientContext fromContext(Context context, boolean clientSuccess) { public static ClientContext fromContext(Context context, boolean clientSuccess) {
return new ClientContext(context.responseID,clientSuccess); return new ClientContext(context.responseID, clientSuccess, context.channelName);
} }
public int getResponseID() { public int getResponseID() {
return responseID; return responseID;
} }
public String getChannelName() {
return channelName;
}
public static class ClientContext extends Context { public static class ClientContext extends Context {
private final boolean clientSuccess; private final boolean clientSuccess;
ClientContext(int responseID, boolean clientSuccess) { ClientContext(int responseID, boolean clientSuccess, String channelName) {
super(responseID); super(responseID, channelName);
this.clientSuccess = clientSuccess; this.clientSuccess = clientSuccess;
} }

View File

@ -9,7 +9,7 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageCodec; import io.netty.handler.codec.MessageToMessageCodec;
import org.adde0109.ambassador.forge.ForgeHandshakeUtils; import org.adde0109.ambassador.Ambassador;
import org.adde0109.ambassador.forge.packet.*; import org.adde0109.ambassador.forge.packet.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -28,21 +28,27 @@ public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBu
protected void decode(ChannelHandlerContext ctx, DeferredByteBufHolder in, List<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, DeferredByteBufHolder in, List<Object> out) throws Exception {
ByteBuf buf = in.content(); ByteBuf buf = in.content();
Context context;
if (in instanceof LoginPluginMessagePacket msg && msg.getChannel().equals("fml:loginwrapper")) {
context = Context.createContext(msg.getId());
} else if (in instanceof LoginPluginResponsePacket msg && loginWrapperIDs.remove(Integer.valueOf(msg.getId()))) {
context = Context.createClientContext(msg.getId(), msg.isSuccess());
} else {
ctx.fireChannelRead(in.retain());
return;
}
int originalReaderIndex = buf.readerIndex(); int originalReaderIndex = buf.readerIndex();
String channel;
try { try {
String channel = ProtocolUtils.readString(buf); Context context;
if (in instanceof LoginPluginMessagePacket msg && msg.getChannel().equals("fml:loginwrapper")) {
channel = ProtocolUtils.readString(buf);
context = Context.createContext(msg.getId(), channel);
} else if (in instanceof LoginPluginResponsePacket msg && loginWrapperIDs.remove(Integer.valueOf(msg.getId()))) {
channel = ProtocolUtils.readString(buf);
context = Context.createClientContext(msg.getId(), msg.isSuccess(), channel);
} else {
//Not a loginWrapperPacket
buf.readerIndex(originalReaderIndex);
ctx.fireChannelRead(in.retain());
return;
}
if (!channel.equals("fml:handshake")) { if (!channel.equals("fml:handshake")) {
throw new DecoderException(); out.add(GenericForgeLoginWrapperPacket.read(buf, context));
} else { } else {
int length = ProtocolUtils.readVarInt(buf); int length = ProtocolUtils.readVarInt(buf);
int packetID = ProtocolUtils.readVarInt(buf); int packetID = ProtocolUtils.readVarInt(buf);
@ -55,7 +61,7 @@ public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBu
out.add(new ACKPacket(clientContext)); out.add(new ACKPacket(clientContext));
break; break;
default: default:
throw new DecoderException(); throw new DecoderException("Unrecognised packet ID: " + packetID);
} }
} else { } else {
switch (packetID) { switch (packetID) {
@ -75,39 +81,33 @@ public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBu
break; break;
} }
default: default:
throw new DecoderException(); throw new DecoderException("Unrecognised packet ID: " + packetID);
} }
} }
} }
} catch (DecoderException e) { } catch (DecoderException exception) {
buf.readerIndex(originalReaderIndex); Ambassador.getInstance().logger.error("Failed to decode a wrapped Forge login packet: ", exception);
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
} }
} }
@Override @Override
protected void encode(ChannelHandlerContext ctx, IForgeLoginWrapperPacket<?> msg, List<Object> out) throws Exception { protected void encode(ChannelHandlerContext ctx, IForgeLoginWrapperPacket<?> msg, List<Object> out) throws Exception {
ByteBuf wrapped; ByteBuf wrapped;
if (msg instanceof GenericForgeLoginWrapperPacket<?>) {
wrapped = msg.encode(); String channel = msg.getContext().getChannelName();
} else {
String channel = "fml:handshake"; wrapped = Unpooled.buffer();
if (msg instanceof ForgeHandshakeUtils.SilentGearUtils.ACKPacket) { ByteBuf encoded = msg.encode();
channel = "silentgear:network"; ProtocolUtils.writeString(wrapped, channel);
} ProtocolUtils.writeVarInt(wrapped, encoded.readableBytes());
wrapped = Unpooled.buffer(); wrapped.writeBytes(encoded);
ByteBuf encoded = msg.encode(); encoded.release();
ProtocolUtils.writeString(wrapped, channel);
ProtocolUtils.writeVarInt(wrapped, encoded.readableBytes());
wrapped.writeBytes(encoded);
encoded.release();
}
if (msg.getContext() instanceof Context.ClientContext clientContext) { if (msg.getContext() instanceof Context.ClientContext clientContext) {
out.add(new LoginPluginResponsePacket(clientContext.getResponseID(), clientContext.success(), wrapped)); out.add(new LoginPluginResponsePacket(clientContext.getResponseID(), clientContext.success(), wrapped));
} else { } else {
out.add(new LoginPluginMessagePacket(msg.getContext().getResponseID(), "fml:loginwrapper", wrapped)); out.add(new LoginPluginMessagePacket(msg.getContext().getResponseID(), "fml:loginwrapper", wrapped));
if (!(msg instanceof ModDataPacket)) { if (!(msg instanceof ModDataPacket)) { //ModDataPacket doesn't require a response
this.loginWrapperIDs.add(msg.getContext().getResponseID()); this.loginWrapperIDs.add(msg.getContext().getResponseID());
} }
} }