diff --git a/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java b/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java index 8edc1f35..3e322990 100644 --- a/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java +++ b/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java @@ -49,7 +49,6 @@ import java.util.concurrent.CompletableFuture; * - Older versions don't clamp positions when teleporting (Is this important?) * * TODO | Port - * - Readd MixinCustomPayloadS2CPacket * - Readd item fixes: MixinItemStack, MixinDrawContext, MixinPacketByteBuf */ public class ViaFabricPlus { diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/VFPProtocol.java b/src/main/java/de/florianmichael/viafabricplus/fixes/VFPProtocol.java new file mode 100644 index 00000000..fcedad27 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/VFPProtocol.java @@ -0,0 +1,108 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2024 FlorianMichael/EnZaXD and RK_01/RaphiMC + * Copyright (C) 2023-2024 contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.florianmichael.viafabricplus.fixes; + +import com.viaversion.viaversion.api.protocol.AbstractSimpleProtocol; +import com.viaversion.viaversion.api.protocol.packet.*; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import com.viaversion.viaversion.api.type.Type; +import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ClientboundPackets1_20_5; +import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPackets1_20_5; +import com.viaversion.viaversion.util.Key; +import net.minecraft.network.packet.BrandCustomPayload; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.network.packet.s2c.custom.DebugGameTestAddMarkerCustomPayload; +import net.minecraft.network.packet.s2c.custom.DebugGameTestClearCustomPayload; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import net.raphimc.vialegacy.api.LegacyProtocolVersion; + +import java.util.HashMap; +import java.util.Map; + +// Protocol to handle error handling changes in older protocols, always last element of the pipeline +public class VFPProtocol extends AbstractSimpleProtocol { + + public static final VFPProtocol INSTANCE = new VFPProtocol(); + + private final Map> payloadDiff = new HashMap<>(); + + public VFPProtocol() { + registerMapping(BrandCustomPayload.ID, LegacyProtocolVersion.c0_0_15a_1, wrapper -> wrapper.passthrough(Type.STRING)); + registerMapping(DebugGameTestAddMarkerCustomPayload.ID, ProtocolVersion.v1_14, wrapper -> { + wrapper.passthrough(Type.POSITION1_14); + wrapper.passthrough(Type.INT); + wrapper.passthrough(Type.STRING); + wrapper.passthrough(Type.INT); + }); + registerMapping(DebugGameTestClearCustomPayload.ID, ProtocolVersion.v1_14, wrapper -> {}); + } + + @Override + protected void registerPackets() { + registerClientbound(State.PLAY, getPluginMessagePacket().getId(), getPluginMessagePacket().getId(), wrapper -> { + final String channel = Key.namespaced(wrapper.passthrough(Type.STRING)); + if (!channel.startsWith(Identifier.DEFAULT_NAMESPACE)) { + // Mods might add custom payloads that we don't want to filter, so we check for the namespace. + // Mods should NEVER use the default namespace of the game, not only to not break this code, + // but also to not break other mods and the game itself. + return; + } + + final ProtocolVersion version = wrapper.user().getProtocolInfo().serverProtocolVersion(); + if (!payloadDiff.containsKey(channel) || version.olderThan(payloadDiff.get(channel).getLeft())) { + // Technically it's wrong to just drop all payloads, but ViaVersion doesn't translate them and the server can't detect if + // we handled the payload or not, so dropping them is easier than adding a bunch of useless translations for payloads + // which doesn't do anything on the client anyway. + wrapper.cancel(); + return; + } + + if (version.olderThanOrEqualTo(ProtocolVersion.v1_20)) { + // Skip remaining bytes after reading the payload and cancel if the payload fails to read + final PacketReader reader = payloadDiff.get(channel).getRight(); + try { + reader.read(wrapper); + wrapper.read(Type.REMAINING_BYTES); + } catch (Exception ignored) { + wrapper.cancel(); + } + } + }); + } + + private void registerMapping(final CustomPayload.Id id, final ProtocolVersion version, final PacketReader reader) { + payloadDiff.put(id.id().toString(), new Pair<>(version, reader)); + } + + public static ServerboundPacketType getCreativeInventoryActionPacket() { + return ServerboundPackets1_20_5.CREATIVE_INVENTORY_ACTION; + } + + public static ClientboundPacketType getPluginMessagePacket() { + return ClientboundPackets1_20_5.PLUGIN_MESSAGE; + } + + @FunctionalInterface + interface PacketReader { + + void read(PacketWrapper wrapper) throws Exception; + } +} diff --git a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/ProtocolTranslator.java b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/ProtocolTranslator.java index e466fcfe..915375e6 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/ProtocolTranslator.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/ProtocolTranslator.java @@ -35,7 +35,7 @@ import com.viaversion.viaversion.connection.UserConnectionImpl; import com.viaversion.viaversion.protocol.ProtocolPipelineImpl; import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.Protocol1_20_5To1_20_3; import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback; -import de.florianmichael.viafabricplus.event.PostViaVersionLoadCallback; +import de.florianmichael.viafabricplus.fixes.VFPProtocol; import de.florianmichael.viafabricplus.injection.access.IClientConnection; import de.florianmichael.viafabricplus.protocoltranslator.impl.command.ViaFabricPlusVLCommandHandler; import de.florianmichael.viafabricplus.protocoltranslator.impl.platform.ViaFabricPlusViaLegacyPlatformImpl; @@ -323,6 +323,7 @@ public class ProtocolTranslator { ); Protocol1_20_5To1_20_3.strictErrorHandling = false; ProtocolVersion.register(AUTO_DETECT_PROTOCOL); + VFPProtocol.INSTANCE.initialize(); }); } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/netty/ViaFabricPlusVLLegacyPipeline.java b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/netty/ViaFabricPlusVLLegacyPipeline.java index 416c3c74..52371fbd 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/netty/ViaFabricPlusVLLegacyPipeline.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/netty/ViaFabricPlusVLLegacyPipeline.java @@ -22,6 +22,7 @@ package de.florianmichael.viafabricplus.protocoltranslator.netty; import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import de.florianmichael.viafabricplus.ViaFabricPlus; +import de.florianmichael.viafabricplus.fixes.VFPProtocol; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import net.raphimc.vialoader.netty.CompressionReorderEvent; @@ -37,6 +38,13 @@ public class ViaFabricPlusVLLegacyPipeline extends VLLegacyPipeline { super(user, version); } + @Override + public void handlerAdded(ChannelHandlerContext ctx) { + super.handlerAdded(ctx); + + this.user.getProtocolInfo().getPipeline().add(VFPProtocol.INSTANCE); + } + @Override protected ChannelHandler createViaDecoder() { return new ViaFabricPlusViaDecoder(this.user); diff --git a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/translator/ItemTranslator.java b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/translator/ItemTranslator.java index b7cf23a3..1d15d0dd 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/translator/ItemTranslator.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/translator/ItemTranslator.java @@ -27,8 +27,8 @@ import com.viaversion.viaversion.api.protocol.packet.State; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.version.Types1_20_5; -import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPackets1_20_5; import de.florianmichael.viafabricplus.ViaFabricPlus; +import de.florianmichael.viafabricplus.fixes.VFPProtocol; import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator; import io.netty.buffer.Unpooled; import net.minecraft.client.MinecraftClient; @@ -59,7 +59,7 @@ public class ItemTranslator { buf.writeShort(0); // slot ItemStack.OPTIONAL_PACKET_CODEC.encode(buf, stack); // item - final PacketWrapper wrapper = PacketWrapper.create(ServerboundPackets1_20_5.CREATIVE_INVENTORY_ACTION, buf, user); + final PacketWrapper wrapper = PacketWrapper.create(VFPProtocol.getCreativeInventoryActionPacket(), buf, user); user.getProtocolInfo().getPipeline().transform(Direction.SERVERBOUND, State.PLAY, wrapper); wrapper.read(Type.SHORT); // slot