发送LoginStart数据包后Minecraft服务器返回IndexOutOfBoundsException错误
排查Minecraft LoginStart数据包发送导致的IndexOutOfBoundsException错误
服务器返回的错误明确指向Netty解码时的索引越界:readerIndex(27) + length(8) exceeds writerIndex(34),说明服务器尝试从数据包的27索引位读取8字节数据,但数据包总长度仅34字节,数据量不足。结合你怀疑的OutputPacketContainer#writeUUID方法,大概率是UUID的编码逻辑不符合Minecraft协议规范。
核心问题分析
根据Minecraft登录协议规范,LoginStart数据包中的UUID字段必须按以下规则编码:
- 无论在线/离线模式,都需要将UUID拆分为高64位整数和低64位整数,分别以**大端序(Big-Endian)**写入数据包
- 离线模式登录时,需写入全零的UUID(即两个64位的0值)
排查与修复步骤
检查
writeUUID方法的实现逻辑
错误示例(直接转字节数组或用小端序写入):// 错误写法:不符合MC协议对UUID的拆分编码要求 public void writeUUID(UUID uuid) { byte[] bytes = ByteBuffer.allocate(16) .putLong(uuid.getMostSignificantBits()) .putLong(uuid.getLeastSignificantBits()) .array(); writeBytes(bytes); }正确实现(拆分高低位并按大端序写入):
// 正确写法:按MC协议要求分别写入UUID的高低64位 public void writeUUID(UUID uuid) { writeLong(uuid.getMostSignificantBits()); // 写入高64位 writeLong(uuid.getLeastSignificantBits()); // 写入低64位 }验证
writeLong方法的字节序
Minecraft协议所有多字节整数均要求大端序,确保你的writeLong方法不是小端序实现:public void writeLong(long value) { byte[] bytes = ByteBuffer.allocate(8) .order(ByteOrder.BIG_ENDIAN) .putLong(value) .array(); buffer.writeBytes(bytes); }检查LoginStart数据包的整体结构
确认数据包字段无遗漏或长度编码错误:- 数据包长度(VarInt编码)
- 数据包ID(固定为0x00,VarInt编码)
- 用户名(VarInt编码的长度 + UTF-8字节)
- UUID(必须存在,离线模式填全零UUID)
验证
修改writeUUID方法为符合协议的实现后,重新发送LoginStart数据包,服务器应能正常解析,不会再触发索引越界错误。若问题仍存在,需排查VarInt编码逻辑(比如数据包长度、用户名长度的VarInt是否符合可变长度编码规范)。
内容的提问来源于stack exchange,提问作者Lite Mix-Ray
相关产品推荐
相关产品推荐

