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

View File

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

View File

@ -4,31 +4,38 @@ public class Context {
private final int responseID;
private Context(int responseID) {
private final String channelName;
private Context(int responseID, String channelName) {
this.responseID = responseID;
this.channelName = channelName;
}
public static Context createContext(int responseID) {
return new Context(responseID);
public static Context createContext(int responseID, String channelName) {
return new Context(responseID, channelName);
}
public static ClientContext createClientContext(int responseID, boolean clientSuccess) {
return new ClientContext(responseID,clientSuccess);
public static ClientContext createClientContext(int responseID, boolean clientSuccess, String channelName) {
return new ClientContext(responseID, clientSuccess, channelName);
}
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() {
return responseID;
}
public String getChannelName() {
return channelName;
}
public static class ClientContext extends Context {
private final boolean clientSuccess;
ClientContext(int responseID, boolean clientSuccess) {
super(responseID);
ClientContext(int responseID, boolean clientSuccess, String channelName) {
super(responseID, channelName);
this.clientSuccess = clientSuccess;
}

View File

@ -9,7 +9,7 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageCodec;
import org.adde0109.ambassador.forge.ForgeHandshakeUtils;
import org.adde0109.ambassador.Ambassador;
import org.adde0109.ambassador.forge.packet.*;
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 {
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();
String channel;
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")) {
throw new DecoderException();
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
} else {
int length = ProtocolUtils.readVarInt(buf);
int packetID = ProtocolUtils.readVarInt(buf);
@ -55,7 +61,7 @@ public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBu
out.add(new ACKPacket(clientContext));
break;
default:
throw new DecoderException();
throw new DecoderException("Unrecognised packet ID: " + packetID);
}
} else {
switch (packetID) {
@ -75,39 +81,33 @@ public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBu
break;
}
default:
throw new DecoderException();
throw new DecoderException("Unrecognised packet ID: " + packetID);
}
}
}
} catch (DecoderException e) {
buf.readerIndex(originalReaderIndex);
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
} catch (DecoderException exception) {
Ambassador.getInstance().logger.error("Failed to decode a wrapped Forge login packet: ", exception);
}
}
@Override
protected void encode(ChannelHandlerContext ctx, IForgeLoginWrapperPacket<?> msg, List<Object> out) throws Exception {
ByteBuf wrapped;
if (msg instanceof GenericForgeLoginWrapperPacket<?>) {
wrapped = msg.encode();
} else {
String channel = "fml:handshake";
if (msg instanceof ForgeHandshakeUtils.SilentGearUtils.ACKPacket) {
channel = "silentgear:network";
}
wrapped = Unpooled.buffer();
ByteBuf encoded = msg.encode();
ProtocolUtils.writeString(wrapped, channel);
ProtocolUtils.writeVarInt(wrapped, encoded.readableBytes());
wrapped.writeBytes(encoded);
encoded.release();
}
String channel = msg.getContext().getChannelName();
wrapped = Unpooled.buffer();
ByteBuf encoded = msg.encode();
ProtocolUtils.writeString(wrapped, channel);
ProtocolUtils.writeVarInt(wrapped, encoded.readableBytes());
wrapped.writeBytes(encoded);
encoded.release();
if (msg.getContext() instanceof Context.ClientContext clientContext) {
out.add(new LoginPluginResponsePacket(clientContext.getResponseID(), clientContext.success(), wrapped));
} else {
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());
}
}