Fixed codec

This commit is contained in:
Adrian Bergqvist 2024-02-13 01:26:33 +01:00
parent 5ffea5bc96
commit b91d767163
No known key found for this signature in database
GPG Key ID: 3B3DA43224B79417
3 changed files with 124 additions and 64 deletions

View File

@ -5,7 +5,7 @@ plugins {
}
group = "org.adde0109"
version = "1.5.0"
version = "1.5.0-tst12"
repositories {
mavenCentral()

View File

@ -1,10 +1,39 @@
package org.adde0109.ambassador.forge.packet;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
public class ModDataPacket extends GenericForgeLoginWrapperPacket<Context> {
public class ModDataPacket implements IForgeLoginWrapperPacket<Context> {
private final byte[] content;
private final Context context;
ModDataPacket(byte[] content, Context context) {
super(content, context);
this.content = content;
this.context = context;
}
static public ModDataPacket read(ByteBuf input, Context context) {
byte[] content = new byte[input.readableBytes()];
input.readBytes(content);
return new ModDataPacket(content, context);
}
@Override
public ByteBuf encode() {
ByteBuf buf = Unpooled.buffer();
ProtocolUtils.writeVarInt(buf, 5); //PacketID
buf.writeBytes(content);
return buf;
}
public byte[] getContent() {
return content;
}
@Override
public Context getContext() {
return context;
}
}

View File

@ -9,84 +9,108 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.ReferenceCountUtil;
import org.adde0109.ambassador.Ambassador;
import org.adde0109.ambassador.forge.packet.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBufHolder, IForgeLoginWrapperPacket<?>> {
private final boolean FML3;
private final List<Integer> loginWrapperIDs = new ArrayList<>();
private final Map<Integer, Context> loginWrapperContexts = new HashMap<>();
public ForgeLoginWrapperCodec(boolean fml3) {
FML3 = fml3;
}
@Override
public boolean acceptInboundMessage(Object msg) throws Exception {
return (msg instanceof LoginPluginMessagePacket
&& ((LoginPluginMessagePacket) msg).getChannel().equals("fml:loginwrapper"))
|| (msg instanceof LoginPluginResponsePacket
&& loginWrapperContexts.containsKey(((LoginPluginResponsePacket) msg).getId()));
}
@Override
protected void decode(ChannelHandlerContext ctx, DeferredByteBufHolder in, List<Object> out) throws Exception {
ByteBuf buf = in.content();
Context context;
if (in instanceof LoginPluginResponsePacket msg) {
//Continue from stored context
context = Context.fromContext(
loginWrapperContexts.remove(((LoginPluginResponsePacket) msg).getId()), msg.isSuccess());
if (!msg.isSuccess()) {
//Nothing to read, just create an empty packet.
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
return;
} else {
String channel = ProtocolUtils.readString(buf); //Read the channel even though we know the channel by context.
Ambassador.getInstance();
}
} else {
//New context.
LoginPluginMessagePacket msg = (LoginPluginMessagePacket) in;
String channel = ProtocolUtils.readString(buf);
context = Context.createContext(msg.getId(), channel);
}
//Decoding of data starts here - channel already read
int originalReaderIndex = buf.readerIndex();
String channel;
try {
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);
if (!context.getChannelName().equals("fml:handshake")) {
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
} else {
int length = ProtocolUtils.readVarInt(buf);
int packetID = ProtocolUtils.readVarInt(buf);
if (context instanceof Context.ClientContext clientContext) {
switch (packetID) {
case 2:
out.add(ModListReplyPacket.read(buf, clientContext));
break;
case 99:
out.add(new ACKPacket(clientContext));
break;
default:
//Undo decoding
buf.readerIndex(originalReaderIndex);
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
if (Ambassador.getInstance().config.isDebugMode()) {
Ambassador.getInstance().logger.warn(
"Unrecognised packet id received from client on fml:handshake: " + packetID);
}
}
} else {
//Not a loginWrapperPacket
buf.readerIndex(originalReaderIndex);
ctx.fireChannelRead(in.retain());
return;
}
if (!channel.equals("fml:handshake")) {
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
} else {
int length = ProtocolUtils.readVarInt(buf);
int packetID = ProtocolUtils.readVarInt(buf);
if (context instanceof Context.ClientContext clientContext) {
switch (packetID) {
case 2:
out.add(ModListReplyPacket.read(buf, clientContext));
switch (packetID) {
case 1:
out.add(ModListPacket.read(buf, context, FML3));
break;
case 3:
out.add(RegistryPacket.read(buf, context, FML3));
break;
case 4:
out.add(ConfigDataPacket.read(buf, context, FML3));
break;
case 5:
if (FML3) {
out.add(ModDataPacket.read(buf, context));
break;
case 99:
out.add(new ACKPacket(clientContext));
break;
default:
throw new DecoderException("Unrecognised packet ID: " + packetID);
}
} else {
switch (packetID) {
case 1:
out.add(ModListPacket.read(buf, context, FML3));
break;
case 3:
out.add(RegistryPacket.read(buf, context, FML3));
break;
case 4:
out.add(ConfigDataPacket.read(buf, context, FML3));
break;
case 5:
if (FML3) {
buf.readerIndex(originalReaderIndex);
out.add(ModDataPacket.read(buf, context));
break;
}
default:
throw new DecoderException("Unrecognised packet ID: " + packetID);
}
}
default:
//Undo decoding
buf.readerIndex(originalReaderIndex);
out.add(GenericForgeLoginWrapperPacket.read(buf, context));
if (Ambassador.getInstance().config.isDebugMode()) {
Ambassador.getInstance().logger.warn(
"Unrecognised packet id received from server on fml:handshake: " + packetID);
}
}
}
} catch (DecoderException exception) {
Ambassador.getInstance().logger.error("Failed to decode a wrapped Forge login packet: ", exception);
}
}
@ -94,21 +118,28 @@ public class ForgeLoginWrapperCodec extends MessageToMessageCodec<DeferredByteBu
protected void encode(ChannelHandlerContext ctx, IForgeLoginWrapperPacket<?> msg, List<Object> out) throws Exception {
ByteBuf wrapped;
boolean data = !(msg.getContext() instanceof Context.ClientContext clientContext && !clientContext.success());
boolean includeLength = !(msg instanceof GenericForgeLoginWrapperPacket);
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 (data) {
ByteBuf encoded = msg.encode();
ProtocolUtils.writeString(wrapped, channel);
if (includeLength)
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)) { //ModDataPacket doesn't require a response
this.loginWrapperIDs.add(msg.getContext().getResponseID());
this.loginWrapperContexts.put(msg.getContext().getResponseID(), msg.getContext());
}
}
}