ViaMCP 公司
ViaVersion版本切换器用于Minecraft编码器包(MCP)
- 设置 - 主要班级 - 网络管理器 - 版本控制 - 版本滑块 - 客户端修复 - 攻击顺序修复 - 阻止声音修复 - 1.17的交易修复+ - 1.21.2的客户端勾选修复+ - Hypixel加入修复 - 发送原始数据包(例如1.9交互) - 导出时不使用JAR文件
现有用户的更新通知(如果您是ViaMCP的新手,可以忽略此通知)
ViaVersion 4.10.0对ProtocolVersion API进行了一些更改,如果您使用过ViaLoadingBase类,则必须更新您自己的代码:
// Old
ViaLoadingBase.getInstance().getTargetVersion().isOlderThan(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().isNewerThan(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().isNewerThanOrEqualTo(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().isOlderThanOrEqualTo(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().getIndex();
// New
ViaLoadingBase.getInstance().getTargetVersion().olderThan(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().newerThan(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_8);
ViaLoadingBase.getInstance().getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8);
ViaLoadingBase.PROTOCOLS.indexOf(ViaLoadingBase.getInstance().getTargetVersion());除此之外 *可比协议版本* 类已被删除,其方法已被移动到 *协议版本* 类。
设置
首先,您需要将列出的库添加到IntelliJ或Eclipse中的依赖项中
依赖关系(包括在内 libraries 文件夹)
ViaVersion-[ver]-downgraded.jar > ViaVersion > https://github.com/ViaVersion/ViaVersion
ViaBackwards-[ver]-downgraded.jar > ViaBackwards > https://github.com/ViaVersion/ViaBackwards
ViaRewind-[ver]-downgraded.jar > ViaRewind > https://github.com/ViaVersion/ViaRewind其次,您需要添加允许您实际使用ViaMCP的代码(选择与客户端版本对应的版本文件夹)
对于1.8.x和1.12.2以外的其他版本,您需要修改代码以适应您的客户端版本。你可以看到以下名称 其他主要版本 这里
注: ViaVersion 5.0.0+不再支持Java 8,因此在自己更新库时,您需要下载
主要班级
将其添加到客户端的主类中(也称为注入函数)
try {
ViaMCP.create();
// In case you want a version slider like in the Minecraft options, you can use this code here, please choose one of those:
ViaMCP.INSTANCE.initAsyncSlider(); // For top left aligned slider
ViaMCP.INSTANCE.initAsyncSlider(x, y, width (min. 110), height (recommended 20)); // For custom position and size slider
} catch (Exception e) {
e.printStackTrace();
}网络管理器
您需要修改NetworkManager.java中的2个方法
1.将ViaVersion钩入Netty管道
找到方法,即 func_181124_a, createNetworkManagerAndConnect 或包含 (Bootstrap)((Bootstrap)((Bootstrap)(new Bootstrap()).group((EventLoopGroup)lazyloadbase.getValue())
查找vanilla网络管道调用:
// 1.8.x client
p_initChannel_1_.pipeline().addLast((String)"timeout", (ChannelHandler)(new ReadTimeoutHandler(30))).addLast((String)"splitter", (ChannelHandler)(new MessageDeserializer2())).addLast((String)"decoder", (ChannelHandler)(new MessageDeserializer(EnumPacketDirection.CLIENTBOUND))).addLast((String)"prepender", (ChannelHandler)(new MessageSerializer2())).addLast((String)"encoder", (ChannelHandler)(new MessageSerializer(EnumPacketDirection.SERVERBOUND))).addLast((String)"packet_handler", (ChannelHandler)networkmanager);
// 1.12.x client
p_initChannel_1_.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("splitter", new NettyVarint21FrameDecoder()).addLast("decoder", new NettyPacketDecoder(EnumPacketDirection.CLIENTBOUND)).addLast("prepender", new NettyVarint21FrameEncoder()).addLast("encoder", new NettyPacketEncoder(EnumPacketDirection.SERVERBOUND)).addLast("packet_handler", networkmanager);在vanilla网络管道调用后,添加ViaMCP协议管道挂钩:
if (p_initChannel_1_ instanceof SocketChannel && ViaLoadingBase.getInstance().getTargetVersion().getVersion() != ViaMCP.NATIVE_VERSION) {
final UserConnection user = new UserConnectionImpl(p_initChannel_1_, true);
new ProtocolPipelineImpl(user);
p_initChannel_1_.pipeline().addLast(new MCPVLBPipeline(user));
}之后你的代码应该看起来像这样(例如1.8.x),vanilla网络管道调用不应该被注释掉,ViaMCP协议管道钩子应该在vanilla网路管道调用之后:
p_initChannel_1_.pipeline().addLast((String)"timeout", (ChannelHandler)(new ReadTimeoutHandler(30))).addLast((String)"splitter", (ChannelHandler)(new MessageDeserializer2())).addLast((String)"decoder", (ChannelHandler)(new MessageDeserializer(EnumPacketDirection.CLIENTBOUND))).addLast((String)"prepender", (ChannelHandler)(new MessageSerializer2())).addLast((String)"encoder", (ChannelHandler)(new MessageSerializer(EnumPacketDirection.SERVERBOUND))).addLast((String)"packet_handler", (ChannelHandler)networkmanager);
if (p_initChannel_1_ instanceof SocketChannel && ViaLoadingBase.getInstance().getTargetVersion().getVersion() != ViaMCP.NATIVE_VERSION) {
final UserConnection user = new UserConnectionImpl(p_initChannel_1_, true);
new ProtocolPipelineImpl(user);
p_initChannel_1_.pipeline().addLast(new MCPVLBPipeline(user));
}旁注:如果你想发送自定义数据包,你必须将UserConnection实例存储在一个变量中以备后用,重要的是这个变量不是静态的,因为它也用于ping服务器!
2.修复NetworkManager#setCompressionTreshold函数中的压缩问题
只需在Minecraft的方法末尾调用以下代码:
this.channel.pipeline().fireUserEventTriggered(new CompressionReorderEvent());版本控制
您需要添加一个按钮来访问协议切换器(或者使用本节下的版本滑块)
在 addSingleplayerMultiplayerButtons() 功能添加(如果在GuiMainMenu中):
this.buttonList.add(new GuiButton(69, 5, 5, 90, 20, "Version"));在 actionPerformed() 功能添加:
if (button.id == 69)
{
this.mc.displayGuiScreen(new GuiProtocolSelector(this));
}版本滑块
您还可以使用版本滑块来控制ViaMCP版本
this.buttonList.add(ViaMCP.INSTANCE.getAsyncVersionSlider());客户端修复
攻击顺序修复
类别:Minecraft.java
功能:点击鼠标()
1.8.x
替换 this.thePlayer.swingItem(); if条款第1行:
AttackOrder.sendConditionalSwing(this.objectMouseOver);替换 this.playerController.attackEntity(this.thePlayer, this.objectMouseOver.entityHit); 在开关的情况下 ENTITY 与:
AttackOrder.sendFixedAttack(this.thePlayer, this.objectMouseOver.entityHit);1.12.2
替换 this.player.swingArm(EnumHand.MAIN_HAND); 在else if子句的最后一行:
AttackOrder.sendConditionalSwing(this.objectMouseOver, EnumHand.MAIN_HAND);替换 this.playerController.attackEntity(this.player, this.objectMouseOver.entityHit); 在开关的情况下 ENTITY 与:
AttackOrder.sendFixedAttack(this.thePlayer, this.objectMouseOver.entityHit, EnumHand.MAIN_HAND);阻止声音修复
区块布局
替换中的所有代码 onItemUse 功能在 ItemBlock 类与:
return FixedSoundEngine.onItemUse(this, stack, playerIn, worldIn, pos, side, hitX, hitY, hitZ);断块
替换中的所有代码 destroyBlock 功能在 World 类与:
return FixedSoundEngine.destroyBlock(this, pos, dropBlock);1.17的交易修复+
打电话给 fixTransactions(); 在 ViaMCP 类文件,因此ViaVersion不会重新映射事务数据包中的任何内容。 之后,您需要对游戏代码进行一些更改:
类:S32PacketConfirmTransaction.java
函数:readPacketData()
用以下方法替换代码:
public void readPacketData(PacketBuffer buf) throws IOException {
if (ViaLoadingBase.getInstance().getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_17)) {
this.windowId = buf.readInt();
} else {
this.windowId = buf.readUnsignedByte();
this.actionNumber = buf.readShort();
this.accepted = buf.readBoolean();
}
}类:C0FPacketConfirmTransaction.java
函数:writePacketData()
用以下方法替换代码:
public void writePacketData(PacketBuffer buf) throws IOException {
if (ViaLoadingBase.getInstance().getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_17)) {
buf.writeInt(this.windowId);
} else {
buf.writeByte(this.windowId);
buf.writeShort(this.uid);
buf.writeByte(this.accepted ? 1 : 0);
}
}注意:此代码可能因映射和游戏版本而异,您只需确保 它只读取窗口id,不读取数据包的其余部分,因为我们之前删除了 ViaVersion处理程序会处理数据包的其余部分。
类:NetHandlerPlayClient.java
函数:handleConfirmTransaction()
在checkThreadAndEnqueue函数调用后添加以下代码:
if (ViaLoadingBase.getInstance().getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_17)) {
this.addToSendQueue(new C0FPacketConfirmTransaction(packetIn.getWindowId(), 0, false));
return;
}1.21.2的客户端勾选修复+
在函数末尾插入以下代码 runTick() 在课堂上 Minecraft:
if (ViaLoadingBase.getInstance().getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_2)) {
UserConnection connection = Via.getManager().getConnectionManager().getConnections().iterator().next();
PacketWrapper packet = PacketWrapper.create(ServerboundPackets1_21_2.CLIENT_TICK_END, null, connection);
packet.sendToServer(Protocol1_21_2To1_21.class);
}Hypixel加入修复
打电话给 fixHypixelLogin(); 在 ViaMCP 类文件
然后在头部插入以下代码 runTick() 类中的函数 Minecraft:
PacketWrapperImpl packet = null;
PacketWrapperImpl packetInfo = null;
int modelParts = 0;
// Hypixel only allow 1.21.4+ client to login.
if (ViaLoadingBase.getInstance().getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4)) {
packet = (PacketWrapperImpl) PacketWrapper.create(ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD, ViaMCP.INSTANCE.user);
packet.write(Types.STRING, "minecraft:brand");
packet.write(Types.STRING, "vanilla");
packet.sendToServer(Protocol1_20_3To1_20_2.class);
packetInfo = (PacketWrapperImpl) PacketWrapper.create(ServerboundConfigurationPackets1_20_2.CLIENT_INFORMATION, ViaMCP.INSTANCE.user);
packetInfo.write(Types.STRING, Minecraft.getMinecraft().gameSettings.language.toLowerCase());
packetInfo.write(Types.BYTE, (byte) Minecraft.getMinecraft().gameSettings.renderDistanceChunks);
packetInfo.write(Types.VAR_INT, Minecraft.getMinecraft().gameSettings.chatVisibility.ordinal());
packetInfo.write(Types.BOOLEAN, Minecraft.getMinecraft().gameSettings.chatColours);
for (EnumPlayerModelParts parts : Minecraft.getMinecraft().gameSettings.getModelParts()) {
modelParts |= parts.getPartMask();
}
packetInfo.write(Types.UNSIGNED_BYTE, (short) modelParts);
packetInfo.write(Types.VAR_INT, 1);
packetInfo.write(Types.BOOLEAN, true);
packetInfo.write(Types.BOOLEAN, true);
packetInfo.sendToServer(Protocol1_20_3To1_20_2.class);
}发送原始数据包(例如1.9交互)
您可以使用ViaMCP发送原始数据包,您可以使用以下代码发送原始数据包包送:
final PacketWrapper blockPlace = PacketWrapper.create(ServerboundPackets1_9.PLAYER_BLOCK_PLACEMENT, null); // Replace null with your stored UserConnection, see NetworkManager tutorial above
blockPlace.write(Type.POSITION1_8, new Position(0, 0, 0)); // Replace with the block position
blockPlace.write(Type.VAR_INT, 0); // Replace with the block face, see https://wiki.vg/index.php?title=Protocol&oldid=7617#Player_Digging
blockPlace.write(Type.VAR_INT, 0); // Replace with the hand, 0 for main hand, 1 for off hand
blockPlace.write(Type.UNSIGNED_BYTE, (short) 0); // The x pos of the crosshair, from 0 to 15 increasing from west to east
blockPlace.write(Type.UNSIGNED_BYTE, (short) 0); // The y pos of the crosshair, from 0 to 15 increasing from bottom to top
blockPlace.write(Type.UNSIGNED_BYTE, (short) 0); // The z pos of the crosshair, from 0 to 15 increasing from north to south
try {
blockPlace.sendToServer(Protocol1_9To1_8.class); // Protocol class names are: server -> client version
} catch (Exception e) {
// Packet sending failed
throw new RuntimeException(e);
}导出时不使用JAR文件
这应该可以解决大多数人的依赖关系问题(通常是NoClassDefFoundError或ClassNotFoundException)
- 首先正常导出您的客户
- 使用归档程序(例如winrar或7zip)打开您的客户端.jar文件
- 还可以使用所选的存档程序(ViaVersion、ViaBackwards、ViaRewind和SnakeYaml)打开所有库
- 从ViaVersion、ViaBackwards和ViaRewind拖放
assets,com和us将文件夹添加到client.jar - 然后保存并关闭,现在您的客户端应该正常工作了;)
