diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeArrayMap.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeArrayMap.java index 42996c019..879bb839e 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeArrayMap.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeArrayMap.java @@ -25,9 +25,11 @@ package com.viaversion.viaversion.api.protocol.packet.provider; import java.util.Arrays; import java.util.Collection; import java.util.Map; + +import com.viaversion.viaversion.api.protocol.packet.PacketType; import org.checkerframework.checker.nullness.qual.Nullable; -final class PacketTypeArrayMap

implements PacketTypeMap

{ +final class PacketTypeArrayMap

implements PacketTypeMap

{ private final Map packetsByName; private final P[] packets; diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMap.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMap.java index e481f30f8..8b766056e 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMap.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMap.java @@ -29,7 +29,7 @@ import java.util.HashMap; import java.util.Map; import org.checkerframework.checker.nullness.qual.Nullable; -public interface PacketTypeMap

{ +public interface PacketTypeMap

{ /** * Returns the packet type by the given name. @@ -67,11 +67,11 @@ public interface PacketTypeMap

{ return of(byName, types); } - static PacketTypeMap of(final Map packetsByName, final Int2ObjectMap packetsById) { + static PacketTypeMap of(final Map packetsByName, final Int2ObjectMap packetsById) { return new PacketTypeMapMap<>(packetsByName, packetsById); } - static PacketTypeMap of(final Map packetsByName, final T[] packets) { + static PacketTypeMap of(final Map packetsByName, final T[] packets) { return new PacketTypeArrayMap<>(packetsByName, packets); } } \ No newline at end of file diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMapMap.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMapMap.java index b3ba7a762..80a22d9f2 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMapMap.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/packet/provider/PacketTypeMapMap.java @@ -22,12 +22,13 @@ */ package com.viaversion.viaversion.api.protocol.packet.provider; +import com.viaversion.viaversion.api.protocol.packet.PacketType; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import java.util.Collection; import java.util.Map; import org.checkerframework.checker.nullness.qual.Nullable; -final class PacketTypeMapMap

implements PacketTypeMap

{ +final class PacketTypeMapMap

implements PacketTypeMap

{ private final Map packetsByName; private final Int2ObjectMap

packetsById; diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/BlockEntityType1_20_2.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/BlockEntityType1_20_2.java new file mode 100644 index 000000000..2513183de --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/BlockEntityType1_20_2.java @@ -0,0 +1,53 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2023 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.type.types.version; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity; +import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntityImpl; +import com.viaversion.viaversion.api.type.Type; +import io.netty.buffer.ByteBuf; + +public class BlockEntityType1_20_2 extends Type { + + public BlockEntityType1_20_2() { + super(BlockEntity.class); + } + + @Override + public BlockEntity read(final ByteBuf buffer) throws Exception { + final byte xz = buffer.readByte(); + final short y = buffer.readShort(); + final int typeId = Type.VAR_INT.readPrimitive(buffer); + final CompoundTag tag = Type.NAMELESS_NBT.read(buffer); + return new BlockEntityImpl(xz, y, typeId, tag); + } + + @Override + public void write(final ByteBuf buffer, final BlockEntity entity) throws Exception { + buffer.writeByte(entity.packedXZ()); + buffer.writeShort(entity.y()); + Type.VAR_INT.writePrimitive(buffer, entity.typeId()); + Type.NAMELESS_NBT.write(buffer, entity.tag()); + } +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_2.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_2.java index 066cf85ee..582bf03a6 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_2.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/Types1_20_2.java @@ -22,8 +22,8 @@ */ package com.viaversion.viaversion.api.type.types.version; +import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity; import com.viaversion.viaversion.api.minecraft.metadata.Metadata; -import com.viaversion.viaversion.api.minecraft.metadata.types.MetaTypes1_19_4; import com.viaversion.viaversion.api.minecraft.metadata.types.MetaTypes1_20_2; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.minecraft.MetaListType; @@ -33,6 +33,8 @@ import java.util.List; public final class Types1_20_2 { + + public static final Type BLOCK_ENTITY = new BlockEntityType1_20_2(); public static final ParticleType PARTICLE = Types1_20.PARTICLE; // Only safe to use after protocol loading public static final MetaTypes1_20_2 META_TYPES = new MetaTypes1_20_2(PARTICLE); public static final Type METADATA = new MetadataType(META_TYPES); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/Protocol1_20_2To1_20.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/Protocol1_20_2To1_20.java index 0cab27e6f..6fd6fb716 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/Protocol1_20_2To1_20.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/Protocol1_20_2To1_20.java @@ -23,6 +23,7 @@ import com.viaversion.viaversion.api.protocol.AbstractProtocol; import com.viaversion.viaversion.api.protocol.packet.Direction; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.State; +import com.viaversion.viaversion.api.protocol.remapper.PacketHandler; import com.viaversion.viaversion.api.rewriter.EntityRewriter; import com.viaversion.viaversion.api.rewriter.ItemRewriter; import com.viaversion.viaversion.api.type.Type; @@ -52,16 +53,12 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol tagRewriter = new TagRewriter<>(this); @@ -96,62 +93,54 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol { - System.out.println("Login acknowleged!"); wrapper.cancel(); + final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class); configurationState.setBridgePhase(ConfigurationState.BridgePhase.CONFIGURATION); wrapper.user().getProtocolInfo().setState(State.PLAY); - - for (final ConfigurationState.QueuedPacket packet : configurationState.packetQueue()) { - final PacketWrapper queuedWrapper; - if (packet.packetType() != null) { - queuedWrapper = PacketWrapper.create(packet.packetType(), packet.buf(), wrapper.user()); - } else { - //noinspection deprecation - queuedWrapper = PacketWrapper.create(packet.packetId(), packet.buf(), wrapper.user()); - } - - queuedWrapper.send(Protocol1_20_2To1_20.class, false); - } - - configurationState.packetQueue().clear(); + configurationState.sendQueuedPackets(wrapper.user()); }); - cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId()); // TODO ? + cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId()); - // TODO Make sure this is called in other protocols as well/the base protocol + // TODO Needs baseprotocol logic or something to set to PLAY from the next version onwards registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> { - wrapper.user().get(ConfigurationState.class).reset(); wrapper.cancel(); - System.out.println("CLIENT NOW ALSO ENTERING PLAY STATE"); - }); - registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, wrapper -> { - wrapper.setPacketType(ServerboundPackets1_20_2.PLUGIN_MESSAGE); - wrapper.user().get(ConfigurationState.class).addPacketToQueue(wrapper, false); - }); - registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), ServerboundPackets1_19_4.KEEP_ALIVE.getId(), wrapper -> { - }); - registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.PONG.getId(), ServerboundPackets1_19_4.PONG.getId(), wrapper -> { - }); - registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), ServerboundPackets1_19_4.RESOURCE_PACK_STATUS.getId(), wrapper -> { + final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class); + configurationState.setBridgePhase(ConfigurationState.BridgePhase.NONE); + configurationState.sendQueuedPackets(wrapper.user()); + configurationState.clear(); }); + registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PLUGIN_MESSAGE)); + registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.KEEP_ALIVE)); + registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.PONG.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PONG)); + registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.RESOURCE_PACK_STATUS)); - cancelClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES); // Sad emoji + cancelClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES); // TODO Sad emoji cancelServerbound(ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED); - // TODO Check if we can just not send batches (probably fine like this) cancelServerbound(ServerboundPackets1_20_2.CHUNK_BATCH_RECEIVED); } + private PacketHandler queueServerboundPacket(final ServerboundPackets1_20_2 packetType) { + return wrapper -> { + wrapper.setPacketType(packetType); + wrapper.user().get(ConfigurationState.class).addPacketToQueue(wrapper, false); + wrapper.cancel(); + }; + } + @Override public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception { final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class); if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.NONE) { super.transform(direction, state, packetWrapper); + return; } if (direction == Direction.SERVERBOUND) { // Client and server might be on two different protocol states - always let the client packets go through + // Simply change the processed state if necessary super.transform(direction, configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.CONFIGURATION ? State.CONFIGURATION : state, packetWrapper); return; @@ -159,38 +148,46 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol { - wrapper.write(Type.ITEM1_20_2_VAR_INT_ARRAY, wrapper.read(Type.FLAT_ITEM_ARRAY_VAR_INT)); // Items + wrapper.write(Type.ITEM1_20_2_VAR_INT_ARRAY, wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT)); // Items wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Carried item }); } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/rewriter/EntityPacketRewriter1_20_2.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/rewriter/EntityPacketRewriter1_20_2.java index 971bbe952..bfb9cb1b2 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/rewriter/EntityPacketRewriter1_20_2.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/rewriter/EntityPacketRewriter1_20_2.java @@ -29,6 +29,7 @@ import com.viaversion.viaversion.api.type.types.version.Types1_20_2; import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundConfigurationPackets1_20_2; +import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState; import com.viaversion.viaversion.rewriter.EntityRewriter; public final class EntityPacketRewriter1_20_2 extends EntityRewriter { @@ -86,17 +87,18 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter meta.setMetaType(Types1_20_2.META_TYPES.byId(meta.metaType().typeId()))); + filter().filterFamily(Entity1_19_4Types.DISPLAY).addIndex(10); } @Override diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/storage/ConfigurationState.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/storage/ConfigurationState.java index cb579bb5a..0be45a1cd 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/storage/ConfigurationState.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/storage/ConfigurationState.java @@ -18,8 +18,10 @@ package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage; import com.viaversion.viaversion.api.connection.StorableObject; +import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.protocol.packet.PacketType; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; +import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.checkerframework.checker.nullness.qual.Nullable; @@ -31,6 +33,8 @@ public class ConfigurationState implements StorableObject { private final List packetQueue = new ArrayList<>(); private BridgePhase bridgePhase = BridgePhase.NONE; + private QueuedPacket joinGamePacket; + private boolean queuedJoinGame; public BridgePhase bridgePhase() { return bridgePhase; @@ -41,19 +45,24 @@ public class ConfigurationState implements StorableObject { } public void addPacketToQueue(final PacketWrapper wrapper, final boolean clientbound) throws Exception { + packetQueue.add(toQueuedPacket(wrapper, clientbound, false)); + } + + private QueuedPacket toQueuedPacket(final PacketWrapper wrapper, final boolean clientbound, final boolean skip1_20_2Pipeline) throws Exception { // Caching packet buffers is cursed, copy to heap buffers to make sure we don't start leaking in dumb cases final ByteBuf copy = Unpooled.buffer(); + final PacketType packetType = wrapper.getPacketType(); + final int packetId = wrapper.getId(); + // Don't write the packet id to the buffer + //noinspection deprecation + wrapper.setId(-1); wrapper.writeToBuffer(copy); - packetQueue.add(new QueuedPacket(copy, clientbound, wrapper.getPacketType(), wrapper.getId())); + return new QueuedPacket(copy, clientbound, packetType, packetId, skip1_20_2Pipeline); } - public List packetQueue() { - return packetQueue; - } - - public void reset() { - packetQueue.clear(); - bridgePhase = BridgePhase.NONE; + public void setJoinGamePacket(final PacketWrapper wrapper) throws Exception { + this.joinGamePacket = toQueuedPacket(wrapper, true, true); + queuedJoinGame = true; } @Override @@ -61,6 +70,46 @@ public class ConfigurationState implements StorableObject { return false; // This might be bad } + public void sendQueuedPackets(final UserConnection connection) throws Exception { + if (joinGamePacket != null) { + packetQueue.add(0, joinGamePacket); + joinGamePacket = null; + } + + final ConfigurationState.QueuedPacket[] queuedPackets = packetQueue.toArray(new ConfigurationState.QueuedPacket[0]); + packetQueue.clear(); + + for (final ConfigurationState.QueuedPacket packet : queuedPackets) { + final PacketWrapper queuedWrapper; + try { + if (packet.packetType() != null) { + queuedWrapper = PacketWrapper.create(packet.packetType(), packet.buf(), connection); + } else { + //noinspection deprecation + queuedWrapper = PacketWrapper.create(packet.packetId(), packet.buf(), connection); + } + + if (packet.clientbound()) { + queuedWrapper.send(Protocol1_20_2To1_20.class, packet.skip1_20_2Pipeline()); + } else { + queuedWrapper.sendToServer(Protocol1_20_2To1_20.class, packet.skip1_20_2Pipeline()); + } + } finally { + packet.buf().release(); + } + } + } + + public void clear() { + packetQueue.clear(); + bridgePhase = BridgePhase.NONE; + queuedJoinGame = false; + } + + public boolean queuedOrSentJoinGame() { + return queuedJoinGame; + } + public enum BridgePhase { NONE, PROFILE_SENT, CONFIGURATION } @@ -70,12 +119,15 @@ public class ConfigurationState implements StorableObject { private final boolean clientbound; private final PacketType packetType; private final int packetId; + private final boolean skip1_20_2Pipeline; - private QueuedPacket(final ByteBuf buf, final boolean clientbound, final PacketType packetType, final int packetId) { + private QueuedPacket(final ByteBuf buf, final boolean clientbound, final PacketType packetType, + final int packetId, final boolean skip1_20_2Pipeline) { this.buf = buf; this.clientbound = clientbound; this.packetType = packetType; this.packetId = packetId; + this.skip1_20_2Pipeline = skip1_20_2Pipeline; } public ByteBuf buf() { @@ -93,5 +145,20 @@ public class ConfigurationState implements StorableObject { public @Nullable PacketType packetType() { return packetType; } + + public boolean skip1_20_2Pipeline() { + return skip1_20_2Pipeline; + } + + @Override + public String toString() { + return "QueuedPacket{" + + "buf=" + buf + + ", clientbound=" + clientbound + + ", packetType=" + packetType + + ", packetId=" + packetId + + ", skip1_20_2Pipeline=" + skip1_20_2Pipeline + + '}'; + } } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/types/Chunk1_20_2Type.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/types/Chunk1_20_2Type.java index 78a6fbcc9..fc64cd540 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/types/Chunk1_20_2Type.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_2to1_20/types/Chunk1_20_2Type.java @@ -19,7 +19,6 @@ package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.types; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.google.common.base.Preconditions; -import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity; import com.viaversion.viaversion.api.minecraft.chunks.Chunk; import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_18; @@ -27,7 +26,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType; import com.viaversion.viaversion.api.type.types.version.ChunkSectionType1_18; -import com.viaversion.viaversion.api.type.types.version.Types1_18; +import com.viaversion.viaversion.api.type.types.version.Types1_20_2; import io.netty.buffer.ByteBuf; import java.util.ArrayList; @@ -64,7 +63,7 @@ public final class Chunk1_20_2Type extends Type { final int blockEntitiesLength = Type.VAR_INT.readPrimitive(buffer); final List blockEntities = new ArrayList<>(blockEntitiesLength); for (int i = 0; i < blockEntitiesLength; i++) { - blockEntities.add(Types1_18.BLOCK_ENTITY.read(buffer)); + blockEntities.add(Types1_20_2.BLOCK_ENTITY.read(buffer)); } return new Chunk1_18(chunkX, chunkZ, sections, heightMap, blockEntities); @@ -91,7 +90,7 @@ public final class Chunk1_20_2Type extends Type { Type.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size()); for (final BlockEntity blockEntity : chunk.blockEntities()) { - Types1_18.BLOCK_ENTITY.write(buffer, blockEntity); + Types1_20_2.BLOCK_ENTITY.write(buffer, blockEntity); } }