Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-27 16:40:10 +01:00
Complete 23w31a protocol
Dieser Commit ist enthalten in:
Ursprung
1bc3d407d1
Commit
ac10bb3fd0
@ -25,9 +25,11 @@ package com.viaversion.viaversion.api.protocol.packet.provider;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
final class PacketTypeArrayMap<P> implements PacketTypeMap<P> {
|
final class PacketTypeArrayMap<P extends PacketType> implements PacketTypeMap<P> {
|
||||||
private final Map<String, P> packetsByName;
|
private final Map<String, P> packetsByName;
|
||||||
private final P[] packets;
|
private final P[] packets;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public interface PacketTypeMap<P> {
|
public interface PacketTypeMap<P extends PacketType> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the packet type by the given name.
|
* Returns the packet type by the given name.
|
||||||
@ -67,11 +67,11 @@ public interface PacketTypeMap<P> {
|
|||||||
return of(byName, types);
|
return of(byName, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
|
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
|
||||||
return new PacketTypeMapMap<>(packetsByName, packetsById);
|
return new PacketTypeMapMap<>(packetsByName, packetsById);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> PacketTypeMap<T> of(final Map<String, T> packetsByName, final T[] packets) {
|
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final T[] packets) {
|
||||||
return new PacketTypeArrayMap<>(packetsByName, packets);
|
return new PacketTypeArrayMap<>(packetsByName, packets);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,12 +22,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.api.protocol.packet.provider;
|
package com.viaversion.viaversion.api.protocol.packet.provider;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
final class PacketTypeMapMap<P> implements PacketTypeMap<P> {
|
final class PacketTypeMapMap<P extends PacketType> implements PacketTypeMap<P> {
|
||||||
private final Map<String, P> packetsByName;
|
private final Map<String, P> packetsByName;
|
||||||
private final Int2ObjectMap<P> packetsById;
|
private final Int2ObjectMap<P> packetsById;
|
||||||
|
|
||||||
|
@ -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<BlockEntity> {
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
@ -22,8 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.api.type.types.version;
|
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.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.minecraft.metadata.types.MetaTypes1_20_2;
|
||||||
import com.viaversion.viaversion.api.type.Type;
|
import com.viaversion.viaversion.api.type.Type;
|
||||||
import com.viaversion.viaversion.api.type.types.minecraft.MetaListType;
|
import com.viaversion.viaversion.api.type.types.minecraft.MetaListType;
|
||||||
@ -33,6 +33,8 @@ import java.util.List;
|
|||||||
|
|
||||||
public final class Types1_20_2 {
|
public final class Types1_20_2 {
|
||||||
|
|
||||||
|
|
||||||
|
public static final Type<BlockEntity> BLOCK_ENTITY = new BlockEntityType1_20_2();
|
||||||
public static final ParticleType PARTICLE = Types1_20.PARTICLE; // Only safe to use after protocol loading
|
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 MetaTypes1_20_2 META_TYPES = new MetaTypes1_20_2(PARTICLE);
|
||||||
public static final Type<Metadata> METADATA = new MetadataType(META_TYPES);
|
public static final Type<Metadata> METADATA = new MetadataType(META_TYPES);
|
||||||
|
@ -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.Direction;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
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.EntityRewriter;
|
||||||
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
|
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
|
||||||
import com.viaversion.viaversion.api.type.Type;
|
import com.viaversion.viaversion.api.type.Type;
|
||||||
@ -52,16 +53,12 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
private final BlockItemPacketRewriter1_20_2 itemPacketRewriter = new BlockItemPacketRewriter1_20_2(this);
|
private final BlockItemPacketRewriter1_20_2 itemPacketRewriter = new BlockItemPacketRewriter1_20_2(this);
|
||||||
|
|
||||||
public Protocol1_20_2To1_20() {
|
public Protocol1_20_2To1_20() {
|
||||||
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
|
|
||||||
super(ClientboundPackets1_19_4.class, ClientboundPackets1_20_2.class, ServerboundPackets1_19_4.class, ServerboundPackets1_20_2.class);
|
super(ClientboundPackets1_19_4.class, ClientboundPackets1_20_2.class, ServerboundPackets1_19_4.class, ServerboundPackets1_20_2.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerPackets() {
|
protected void registerPackets() {
|
||||||
// Close your eyes and turn around while you still can
|
// Close your eyes and turn around while you still can
|
||||||
// TODO Handle Enabled features and tags before configuration phase end?
|
|
||||||
// TODO Player info, replace profile with missing name with null?
|
|
||||||
// TODO Scoreboard objective probably okay, but there are refactors to the id
|
|
||||||
super.registerPackets();
|
super.registerPackets();
|
||||||
|
|
||||||
final TagRewriter<ClientboundPackets1_19_4> tagRewriter = new TagRewriter<>(this);
|
final TagRewriter<ClientboundPackets1_19_4> tagRewriter = new TagRewriter<>(this);
|
||||||
@ -96,62 +93,54 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
});
|
});
|
||||||
|
|
||||||
registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> {
|
registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> {
|
||||||
System.out.println("Login acknowleged!");
|
|
||||||
wrapper.cancel();
|
wrapper.cancel();
|
||||||
|
|
||||||
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
||||||
configurationState.setBridgePhase(ConfigurationState.BridgePhase.CONFIGURATION);
|
configurationState.setBridgePhase(ConfigurationState.BridgePhase.CONFIGURATION);
|
||||||
wrapper.user().getProtocolInfo().setState(State.PLAY);
|
wrapper.user().getProtocolInfo().setState(State.PLAY);
|
||||||
|
configurationState.sendQueuedPackets(wrapper.user());
|
||||||
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();
|
|
||||||
});
|
});
|
||||||
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 -> {
|
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> {
|
||||||
wrapper.user().get(ConfigurationState.class).reset();
|
|
||||||
wrapper.cancel();
|
wrapper.cancel();
|
||||||
System.out.println("CLIENT NOW ALSO ENTERING PLAY STATE");
|
|
||||||
});
|
|
||||||
|
|
||||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, wrapper -> {
|
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
||||||
wrapper.setPacketType(ServerboundPackets1_20_2.PLUGIN_MESSAGE);
|
configurationState.setBridgePhase(ConfigurationState.BridgePhase.NONE);
|
||||||
wrapper.user().get(ConfigurationState.class).addPacketToQueue(wrapper, false);
|
configurationState.sendQueuedPackets(wrapper.user());
|
||||||
});
|
configurationState.clear();
|
||||||
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 -> {
|
|
||||||
});
|
});
|
||||||
|
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);
|
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);
|
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
|
@Override
|
||||||
public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception {
|
public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception {
|
||||||
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
|
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
|
||||||
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.NONE) {
|
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.NONE) {
|
||||||
super.transform(direction, state, packetWrapper);
|
super.transform(direction, state, packetWrapper);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction == Direction.SERVERBOUND) {
|
if (direction == Direction.SERVERBOUND) {
|
||||||
// Client and server might be on two different protocol states - always let the client packets go through
|
// 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
|
super.transform(direction, configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.CONFIGURATION
|
||||||
? State.CONFIGURATION : state, packetWrapper);
|
? State.CONFIGURATION : state, packetWrapper);
|
||||||
return;
|
return;
|
||||||
@ -159,38 +148,46 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
|||||||
|
|
||||||
// Queue packets sent by the serverwhile we wait for the client to transition to the configuration state
|
// Queue packets sent by the serverwhile we wait for the client to transition to the configuration state
|
||||||
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.PROFILE_SENT) {
|
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.PROFILE_SENT) {
|
||||||
System.out.println("added to queue " + packetWrapper.getId() + " " + direction + " " + state);
|
configurationBridge.addPacketToQueue(packetWrapper, true);
|
||||||
configurationBridge.addPacketToQueue(packetWrapper, direction == Direction.CLIENTBOUND);
|
|
||||||
throw CancelException.generate();
|
throw CancelException.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map some of them to their configuration state counterparts
|
// Map some of them to their configuration state counterparts, but make sure to late join game through
|
||||||
System.out.println("Transforming " + packetWrapper.getId() + " " + direction + " " + state);
|
|
||||||
System.out.println(configurationBridge.bridgePhase());
|
|
||||||
if (packetWrapper.getPacketType() == null || packetWrapper.getPacketType().state() != State.CONFIGURATION) {
|
if (packetWrapper.getPacketType() == null || packetWrapper.getPacketType().state() != State.CONFIGURATION) {
|
||||||
final int unmappedId = packetWrapper.getId();
|
final int unmappedId = packetWrapper.getId();
|
||||||
if (state == State.PLAY) {
|
if (unmappedId == ClientboundPackets1_19_4.JOIN_GAME.getId()) {
|
||||||
if (unmappedId == ClientboundPackets1_19_4.PLUGIN_MESSAGE.getId()) {
|
// Make sure we handle the start of the play phase correctly
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD);
|
super.transform(direction, state, packetWrapper);
|
||||||
} else if (unmappedId == ClientboundPackets1_19_4.DISCONNECT.getId()) {
|
return;
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.DISCONNECT);
|
|
||||||
} else if (unmappedId == ClientboundPackets1_19_4.KEEP_ALIVE.getId()) {
|
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE);
|
|
||||||
} else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) {
|
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING);
|
|
||||||
} else if (unmappedId == ClientboundPackets1_19_4.RESOURCE_PACK.getId()) {
|
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK);
|
|
||||||
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
|
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
|
|
||||||
} else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) {
|
|
||||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
|
|
||||||
} else {
|
|
||||||
configurationBridge.addPacketToQueue(packetWrapper, direction == Direction.CLIENTBOUND);
|
|
||||||
throw CancelException.generate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (configurationBridge.queuedOrSentJoinGame()) {
|
||||||
|
// Don't try to send configuration packets after the join game packet has been queued or sent
|
||||||
|
configurationBridge.addPacketToQueue(packetWrapper, true);
|
||||||
|
throw CancelException.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unmappedId == ClientboundPackets1_19_4.PLUGIN_MESSAGE.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD);
|
||||||
|
} else if (unmappedId == ClientboundPackets1_19_4.DISCONNECT.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.DISCONNECT);
|
||||||
|
} else if (unmappedId == ClientboundPackets1_19_4.KEEP_ALIVE.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE);
|
||||||
|
} else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING);
|
||||||
|
} else if (unmappedId == ClientboundPackets1_19_4.RESOURCE_PACK.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK);
|
||||||
|
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
|
||||||
|
} else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) {
|
||||||
|
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
|
||||||
|
} else {
|
||||||
|
// Not a packet that can be mapped to the configuration protocol
|
||||||
|
configurationBridge.addPacketToQueue(packetWrapper, true);
|
||||||
|
throw CancelException.generate();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect packets during the fake configuration phase
|
// Redirect packets during the fake configuration phase
|
||||||
// This might mess up people using Via API/other protocols down the line, but such is life. We can't have different states for server and client
|
// This might mess up people using Via API/other protocols down the line, but such is life. We can't have different states for server and client
|
||||||
|
@ -73,14 +73,14 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
|||||||
wrapper.write(newChunkType, chunk);
|
wrapper.write(newChunkType, chunk);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Weeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
// Replace the NBT type everywhere
|
||||||
protocol.registerClientbound(ClientboundPackets1_19_4.WINDOW_ITEMS, new PacketHandlers() {
|
protocol.registerClientbound(ClientboundPackets1_19_4.WINDOW_ITEMS, new PacketHandlers() {
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
map(Type.UNSIGNED_BYTE); // Window id
|
map(Type.UNSIGNED_BYTE); // Window id
|
||||||
map(Type.VAR_INT); // State id
|
map(Type.VAR_INT); // State id
|
||||||
handler(wrapper -> {
|
handler(wrapper -> {
|
||||||
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
|
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Carried item
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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_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.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.packet.ClientboundConfigurationPackets1_20_2;
|
||||||
|
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState;
|
||||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||||
|
|
||||||
public final class EntityPacketRewriter1_20_2 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_20_2To1_20> {
|
public final class EntityPacketRewriter1_20_2 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_20_2To1_20> {
|
||||||
@ -86,17 +87,18 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
|
|||||||
registryDataPacket.send(Protocol1_20_2To1_20.class);
|
registryDataPacket.send(Protocol1_20_2To1_20.class);
|
||||||
|
|
||||||
// Enabling features is only possible during the configuraton phase
|
// Enabling features is only possible during the configuraton phase
|
||||||
// TODO Capture more packets after login to send them later
|
// TODO Sad emoji
|
||||||
final PacketWrapper enableFeaturesPacket = wrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
|
final PacketWrapper enableFeaturesPacket = wrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
|
||||||
enableFeaturesPacket.write(Type.VAR_INT, 1);
|
enableFeaturesPacket.write(Type.VAR_INT, 1);
|
||||||
enableFeaturesPacket.write(Type.STRING, "minecraft:vanilla");
|
enableFeaturesPacket.write(Type.STRING, "minecraft:vanilla");
|
||||||
enableFeaturesPacket.scheduleSend(Protocol1_20_2To1_20.class);
|
enableFeaturesPacket.send(Protocol1_20_2To1_20.class);
|
||||||
|
|
||||||
final PacketWrapper finishConfigurationPacket = wrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION);
|
final PacketWrapper finishConfigurationPacket = wrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION);
|
||||||
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
|
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
|
||||||
|
|
||||||
// Manually send it at the end and hope nothing breaks
|
// Manually send it at the end and hope nothing breaks
|
||||||
wrapper.send(Protocol1_20_2To1_20.class);
|
final ConfigurationState configurationBridge = wrapper.user().get(ConfigurationState.class);
|
||||||
|
configurationBridge.setJoinGamePacket(wrapper);
|
||||||
wrapper.cancel();
|
wrapper.cancel();
|
||||||
});
|
});
|
||||||
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
|
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
|
||||||
@ -142,6 +144,7 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
|
|||||||
@Override
|
@Override
|
||||||
protected void registerRewrites() {
|
protected void registerRewrites() {
|
||||||
filter().handler((event, meta) -> meta.setMetaType(Types1_20_2.META_TYPES.byId(meta.metaType().typeId())));
|
filter().handler((event, meta) -> meta.setMetaType(Types1_20_2.META_TYPES.byId(meta.metaType().typeId())));
|
||||||
|
filter().filterFamily(Entity1_19_4Types.DISPLAY).addIndex(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,8 +18,10 @@
|
|||||||
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage;
|
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage;
|
||||||
|
|
||||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
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.PacketType;
|
||||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
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.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -31,6 +33,8 @@ public class ConfigurationState implements StorableObject {
|
|||||||
|
|
||||||
private final List<QueuedPacket> packetQueue = new ArrayList<>();
|
private final List<QueuedPacket> packetQueue = new ArrayList<>();
|
||||||
private BridgePhase bridgePhase = BridgePhase.NONE;
|
private BridgePhase bridgePhase = BridgePhase.NONE;
|
||||||
|
private QueuedPacket joinGamePacket;
|
||||||
|
private boolean queuedJoinGame;
|
||||||
|
|
||||||
public BridgePhase bridgePhase() {
|
public BridgePhase bridgePhase() {
|
||||||
return bridgePhase;
|
return bridgePhase;
|
||||||
@ -41,19 +45,24 @@ public class ConfigurationState implements StorableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addPacketToQueue(final PacketWrapper wrapper, final boolean clientbound) throws Exception {
|
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
|
// 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 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);
|
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<QueuedPacket> packetQueue() {
|
public void setJoinGamePacket(final PacketWrapper wrapper) throws Exception {
|
||||||
return packetQueue;
|
this.joinGamePacket = toQueuedPacket(wrapper, true, true);
|
||||||
}
|
queuedJoinGame = true;
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
packetQueue.clear();
|
|
||||||
bridgePhase = BridgePhase.NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -61,6 +70,46 @@ public class ConfigurationState implements StorableObject {
|
|||||||
return false; // This might be bad
|
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 {
|
public enum BridgePhase {
|
||||||
NONE, PROFILE_SENT, CONFIGURATION
|
NONE, PROFILE_SENT, CONFIGURATION
|
||||||
}
|
}
|
||||||
@ -70,12 +119,15 @@ public class ConfigurationState implements StorableObject {
|
|||||||
private final boolean clientbound;
|
private final boolean clientbound;
|
||||||
private final PacketType packetType;
|
private final PacketType packetType;
|
||||||
private final int packetId;
|
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.buf = buf;
|
||||||
this.clientbound = clientbound;
|
this.clientbound = clientbound;
|
||||||
this.packetType = packetType;
|
this.packetType = packetType;
|
||||||
this.packetId = packetId;
|
this.packetId = packetId;
|
||||||
|
this.skip1_20_2Pipeline = skip1_20_2Pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuf buf() {
|
public ByteBuf buf() {
|
||||||
@ -93,5 +145,20 @@ public class ConfigurationState implements StorableObject {
|
|||||||
public @Nullable PacketType packetType() {
|
public @Nullable PacketType packetType() {
|
||||||
return 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 +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.types;
|
|||||||
|
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
import com.google.common.base.Preconditions;
|
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.blockentity.BlockEntity;
|
||||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_18;
|
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.Type;
|
||||||
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
|
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.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 io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -64,7 +63,7 @@ public final class Chunk1_20_2Type extends Type<Chunk> {
|
|||||||
final int blockEntitiesLength = Type.VAR_INT.readPrimitive(buffer);
|
final int blockEntitiesLength = Type.VAR_INT.readPrimitive(buffer);
|
||||||
final List<BlockEntity> blockEntities = new ArrayList<>(blockEntitiesLength);
|
final List<BlockEntity> blockEntities = new ArrayList<>(blockEntitiesLength);
|
||||||
for (int i = 0; i < blockEntitiesLength; i++) {
|
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);
|
return new Chunk1_18(chunkX, chunkZ, sections, heightMap, blockEntities);
|
||||||
@ -91,7 +90,7 @@ public final class Chunk1_20_2Type extends Type<Chunk> {
|
|||||||
|
|
||||||
Type.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
|
Type.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
|
||||||
for (final BlockEntity blockEntity : chunk.blockEntities()) {
|
for (final BlockEntity blockEntity : chunk.blockEntities()) {
|
||||||
Types1_18.BLOCK_ENTITY.write(buffer, blockEntity);
|
Types1_20_2.BLOCK_ENTITY.write(buffer, blockEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren