13
0
geforkt von Mirrors/Velocity
Dieser Commit ist enthalten in:
Gero 2023-11-22 10:17:52 +01:00 committet von Shane Freeder
Ursprung a6d90105ec
Commit 814b53f12c
25 geänderte Dateien mit 406 neuen und 321 gelöschten Zeilen

Datei anzeigen

@ -63,7 +63,8 @@ public enum ProtocolVersion {
MINECRAFT_1_19_3(761, "1.19.3"),
MINECRAFT_1_19_4(762, "1.19.4"),
MINECRAFT_1_20(763, "1.20", "1.20.1"),
MINECRAFT_1_20_2(764, "1.20.2");
MINECRAFT_1_20_2(764, "1.20.2"),
MINECRAFT_1_20_3(765, "1.20.3");
private static final int SNAPSHOT_BIT = 30;

Datei anzeigen

@ -19,6 +19,8 @@ import com.velocitypowered.api.proxy.player.TabList;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.ModInfo;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
@ -236,6 +238,7 @@ public interface Player extends
* @return the applied resource pack or null if none.
*/
@Nullable
@Deprecated
ResourcePackInfo getAppliedResourcePack();
/**
@ -246,8 +249,26 @@ public interface Player extends
* @return the pending resource pack or null if none
*/
@Nullable
@Deprecated
ResourcePackInfo getPendingResourcePack();
/**
* Gets the {@link ResourcePackInfo} of the currently applied
* resource-packs.
*
* @return collection of the applied resource packs.
*/
Collection<ResourcePackInfo> getAppliedResourcePacks();
/**
* Gets the {@link ResourcePackInfo} of the resource packs
* the user is currently downloading or is currently
* prompted to install.
*
* @return collection of the pending resource packs
*/
Collection<ResourcePackInfo> getPendingResourcePacks();
/**
* <strong>Note that this method does not send a plugin message to the server the player
* is connected to.</strong> You should only use this method if you are trying to communicate

Datei anzeigen

@ -10,11 +10,20 @@ package com.velocitypowered.api.proxy.player;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
/**
* Represents the information for a resource pack to apply that can be sent to the client.
*/
public interface ResourcePackInfo {
/**
* Gets the id of this resource-pack.
*
* @return the id of the resource-pack
*/
UUID getId();
/**
* Gets the link the resource-pack can be found at.
*
@ -96,6 +105,13 @@ public interface ResourcePackInfo {
*/
interface Builder {
/**
* Sets the id of the resource pack.
*
* @param id the id the resource-pack
*/
Builder setId(UUID id);
/**
* Sets the resource-pack as required to play on the network.
* This feature was introduced in 1.17.

Datei anzeigen

@ -37,6 +37,7 @@ import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import com.velocitypowered.proxy.protocol.packet.PingIdentify;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
import com.velocitypowered.proxy.protocol.packet.RemoveResourcePack;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponse;
import com.velocitypowered.proxy.protocol.packet.Respawn;
@ -248,6 +249,10 @@ public interface MinecraftSessionHandler {
return false;
}
default boolean handle(RemoveResourcePack packet) {
return false;
}
default boolean handle(ResourcePackResponse packet) {
return false;
}

Datei anzeigen

@ -49,11 +49,13 @@ import com.velocitypowered.proxy.protocol.packet.KeepAlive;
import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItem;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
import com.velocitypowered.proxy.protocol.packet.RemoveResourcePack;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponse;
import com.velocitypowered.proxy.protocol.packet.ServerData;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import com.velocitypowered.proxy.protocol.packet.config.StartUpdate;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import io.netty.buffer.ByteBuf;
@ -167,7 +169,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
public boolean handle(ResourcePackRequest packet) {
ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(
Preconditions.checkNotNull(packet.getUrl()))
.setPrompt(packet.getPrompt())
.setId(packet.getId())
.setPrompt(packet.getPrompt() == null ? null : packet.getPrompt().getComponent())
.setShouldForce(packet.isRequired())
.setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
@ -213,6 +216,11 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
return true;
}
@Override
public boolean handle(RemoveResourcePack packet) {
//TODO
}
@Override
public boolean handle(PluginMessage packet) {
if (bungeecordMessageResponder.process(packet)) {
@ -304,7 +312,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
ping -> server.getEventManager()
.fire(new ProxyPingEvent(this.serverConn.getPlayer(), ping)),
playerConnection.eventLoop()).thenAcceptAsync(pingEvent -> this.playerConnection.write(
new ServerData(pingEvent.getPing().getDescriptionComponent(),
new ServerData(new ComponentHolder(this.serverConn.ensureConnected().getProtocolVersion(),
pingEvent.getPing().getDescriptionComponent()),
pingEvent.getPing().getFavicon().orElse(null), packet.isSecureChatEnforced())),
playerConnection.eventLoop());
return true;

Datei anzeigen

@ -68,6 +68,7 @@ import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest;
import com.velocitypowered.proxy.protocol.packet.chat.ChatQueue;
import com.velocitypowered.proxy.protocol.packet.chat.ChatType;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import com.velocitypowered.proxy.protocol.packet.chat.builder.ChatBuilderFactory;
import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChat;
import com.velocitypowered.proxy.protocol.packet.config.StartUpdate;
@ -84,6 +85,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.net.InetSocketAddress;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
@ -1015,22 +1017,36 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
request.setHash("");
}
request.setRequired(queued.getShouldForce());
request.setPrompt(queued.getPrompt());
request.setPrompt(queued.getPrompt() == null ? null : new ComponentHolder(getProtocolVersion(), queued.getPrompt()));
connection.write(request);
}
}
@Override
@Deprecated
public @Nullable ResourcePackInfo getAppliedResourcePack() {
//TODO which resource pack should be returned here?
return appliedResourcePack;
}
@Override
@Deprecated
public @Nullable ResourcePackInfo getPendingResourcePack() {
//TODO which resource pack should be returned here?
return pendingResourcePack;
}
@Override
public Collection<ResourcePackInfo> getAppliedResourcePacks() {
//TODO
}
@Override
public Collection<ResourcePackInfo> getPendingResourcePacks() {
//TODO
}
/**
* Clears the applied resource pack field.
*/
@ -1089,6 +1105,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
* Gives an indication about the previous resource pack responses.
*/
public @Nullable Boolean getPreviousResourceResponse() {
//TODO can probably be removed
return previousResourceResponse;
}

Datei anzeigen

@ -22,11 +22,14 @@ import com.velocitypowered.api.proxy.player.ResourcePackInfo;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
/**
* Implements {@link ResourcePackInfo}.
*/
public final class VelocityResourcePackInfo implements ResourcePackInfo {
private final UUID id;
private final String url;
private final @Nullable byte[] hash;
private final boolean shouldForce;
@ -34,8 +37,9 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
private final Origin origin;
private Origin originalOrigin;
private VelocityResourcePackInfo(String url, @Nullable byte[] hash, boolean shouldForce,
private VelocityResourcePackInfo(UUID id, String url, @Nullable byte[] hash, boolean shouldForce,
@Nullable Component prompt, Origin origin) {
this.id = id;
this.url = url;
this.hash = hash;
this.shouldForce = shouldForce;
@ -44,6 +48,11 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
this.originalOrigin = origin;
}
@Override
public UUID getId() {
return id;
}
@Override
public String getUrl() {
return url;
@ -81,6 +90,7 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
@Override
public Builder asBuilder() {
return new BuilderImpl(url)
.setId(id)
.setShouldForce(shouldForce)
.setHash(hash)
.setPrompt(prompt);
@ -89,6 +99,7 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
@Override
public Builder asBuilder(String newUrl) {
return new BuilderImpl(newUrl)
.setId(id)
.setShouldForce(shouldForce)
.setHash(hash)
.setPrompt(prompt);
@ -99,6 +110,7 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
*/
public static final class BuilderImpl implements ResourcePackInfo.Builder {
private UUID id;
private final String url;
private boolean shouldForce;
private @Nullable byte[] hash;
@ -109,6 +121,12 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
this.url = Preconditions.checkNotNull(url, "url");
}
@Override
public BuilderImpl setId(UUID id) {
this.id = id;
return this;
}
@Override
public BuilderImpl setShouldForce(boolean shouldForce) {
this.shouldForce = shouldForce;
@ -134,7 +152,7 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
@Override
public ResourcePackInfo build() {
return new VelocityResourcePackInfo(url, hash, shouldForce, prompt, origin);
return new VelocityResourcePackInfo(id, url, hash, shouldForce, prompt, origin);
}
public BuilderImpl setOrigin(Origin origin) {

Datei anzeigen

@ -1,128 +0,0 @@
/*
* Copyright (C) 2018-2023 Velocity 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 <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.connection.registry;
import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo;
import com.velocitypowered.proxy.protocol.packet.config.RegistrySync;
import net.kyori.adventure.key.Key;
import org.jetbrains.annotations.Nullable;
/**
* Holds the registry data that is sent
* to the client during the config stage.
*/
public class ClientConfigData {
private final @Nullable VelocityResourcePackInfo resourcePackInfo;
private final DataTag tag;
private final RegistrySync registry;
private final Key[] features;
private final String brand;
private ClientConfigData(@Nullable VelocityResourcePackInfo resourcePackInfo, DataTag tag,
RegistrySync registry, Key[] features, String brand) {
this.resourcePackInfo = resourcePackInfo;
this.tag = tag;
this.registry = registry;
this.features = features;
this.brand = brand;
}
public RegistrySync getRegistry() {
return registry;
}
public DataTag getTag() {
return tag;
}
public Key[] getFeatures() {
return features;
}
public @Nullable VelocityResourcePackInfo getResourcePackInfo() {
return resourcePackInfo;
}
public String getBrand() {
return brand;
}
/**
* Creates a new builder.
*
* @return ClientConfigData.Builder
*/
public static ClientConfigData.Builder builder() {
return new Builder();
}
/**
* Builder for ClientConfigData.
*/
public static class Builder {
private VelocityResourcePackInfo resourcePackInfo;
private DataTag tag;
private RegistrySync registry;
private Key[] features;
private String brand;
private Builder() {
}
/**
* Clears the builder.
*/
public void clear() {
this.resourcePackInfo = null;
this.tag = null;
this.registry = null;
this.features = null;
this.brand = null;
}
public Builder resourcePack(@Nullable VelocityResourcePackInfo resourcePackInfo) {
this.resourcePackInfo = resourcePackInfo;
return this;
}
public Builder dataTag(DataTag tag) {
this.tag = tag;
return this;
}
public Builder registry(RegistrySync registry) {
this.registry = registry;
return this;
}
public Builder features(Key[] features) {
this.features = features;
return this;
}
public Builder brand(String brand) {
this.brand = brand;
return this;
}
public ClientConfigData build() {
return new ClientConfigData(resourcePackInfo, tag, registry, features, brand);
}
}
}

Datei anzeigen

@ -1,95 +0,0 @@
/*
* Copyright (C) 2019-2023 Velocity 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 <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.connection.registry;
import com.google.common.collect.ImmutableList;
import java.util.List;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.Keyed;
import org.jetbrains.annotations.NotNull;
/**
* Represents a data tag.
*/
public class DataTag {
private final ImmutableList<DataTag.Set> entrySets;
public DataTag(ImmutableList<DataTag.Set> entrySets) {
this.entrySets = entrySets;
}
/**
* Returns the entry sets.
*
* @return List of entry sets
*/
public List<Set> getEntrySets() {
return entrySets;
}
/**
* Represents a data tag set.
*/
public static class Set implements Keyed {
private final Key key;
private final ImmutableList<Entry> entries;
public Set(Key key, ImmutableList<Entry> entries) {
this.key = key;
this.entries = entries;
}
/**
* Returns the entries.
*
* @return List of entries
*/
public List<Entry> getEntries() {
return entries;
}
@Override
public @NotNull Key key() {
return key;
}
}
/**
* Represents a data tag entry.
*/
public static class Entry implements Keyed {
private final Key key;
private final int[] elements;
public Entry(Key key, int[] elements) {
this.key = key;
this.elements = elements;
}
public int[] getElements() {
return elements;
}
@Override
public @NotNull Key key() {
return key;
}
}
}

Datei anzeigen

@ -34,15 +34,16 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.CorruptedFrameException;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.EncoderException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.BinaryTagIO;
import net.kyori.adventure.nbt.BinaryTagType;
import net.kyori.adventure.nbt.BinaryTagTypes;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
@ -64,6 +65,11 @@ public enum ProtocolUtils {
.build();
public static final int DEFAULT_MAX_STRING_SIZE = 65536; // 64KiB
private static final BinaryTagType<? extends BinaryTag>[] BINARY_TAG_TYPES = new BinaryTagType[] {
BinaryTagTypes.END, BinaryTagTypes.BYTE, BinaryTagTypes.SHORT, BinaryTagTypes.INT,
BinaryTagTypes.LONG, BinaryTagTypes.FLOAT, BinaryTagTypes.DOUBLE,
BinaryTagTypes.BYTE_ARRAY, BinaryTagTypes.STRING, BinaryTagTypes.LIST,
BinaryTagTypes.COMPOUND, BinaryTagTypes.INT_ARRAY, BinaryTagTypes.LONG_ARRAY};
private static final QuietDecoderException BAD_VARINT_CACHED =
new QuietDecoderException("Bad VarInt decoded");
private static final int[] VARINT_EXACT_BYTE_LENGTHS = new int[33];
@ -367,29 +373,53 @@ public enum ProtocolUtils {
* Reads a {@link net.kyori.adventure.nbt.CompoundBinaryTag} from the {@code buf}.
*
* @param buf the buffer to read from
* @param reader the NBT reader to use
* @param reader the {@link BinaryTagIO.Reader} to use
* @return {@link net.kyori.adventure.nbt.CompoundBinaryTag} the CompoundTag from the buffer
*/
public static CompoundBinaryTag readCompoundTag(ByteBuf buf, BinaryTagIO.Reader reader) {
public static CompoundBinaryTag readCompoundTag(ByteBuf buf, ProtocolVersion version, BinaryTagIO.Reader reader) {
BinaryTag binaryTag = readBinaryTag(buf, version, reader);
if (binaryTag.type() != BinaryTagTypes.COMPOUND) {
throw new DecoderException("Expected root tag to be CompoundTag, but is " + binaryTag.getClass().getSimpleName());
}
return (CompoundBinaryTag) binaryTag;
}
/**
* Reads a {@link net.kyori.adventure.nbt.BinaryTag} from the {@code buf}.
*
* @param buf the buffer to read from
* @param reader the {@link BinaryTagIO.Reader} to use
* @return {@link net.kyori.adventure.nbt.BinaryTag} the BinaryTag from the buffer
*/
public static BinaryTag readBinaryTag(ByteBuf buf, ProtocolVersion version, BinaryTagIO.Reader reader) {
BinaryTagType<?> type = BINARY_TAG_TYPES[buf.readByte()];
if (version.compareTo(ProtocolVersion.MINECRAFT_1_20_2) < 0) {
buf.skipBytes(buf.readUnsignedShort());
}
try {
return reader.read((DataInput) new ByteBufInputStream(buf));
return type.read(new ByteBufInputStream(buf));
} catch (IOException thrown) {
throw new DecoderException(
"Unable to parse NBT CompoundTag, full error: " + thrown.getMessage());
throw new DecoderException("Unable to parse BinaryTag, full error: " + thrown.getMessage());
}
}
/**
* Writes a CompoundTag to the {@code buf}.
* Writes a {@link net.kyori.adventure.nbt.BinaryTag} to the {@code buf}.
*
* @param buf the buffer to write to
* @param compoundTag the CompoundTag to write
* @param buf the buffer to write to
* @param tag the BinaryTag to write
*/
public static void writeCompoundTag(ByteBuf buf, CompoundBinaryTag compoundTag) {
public static <T extends BinaryTag> void writeBinaryTag(ByteBuf buf, ProtocolVersion version, T tag) {
BinaryTagType<T> type = (BinaryTagType<T>) tag.type();
buf.writeByte(type.id());
try {
BinaryTagIO.writer().write(compoundTag, (DataOutput) new ByteBufOutputStream(buf));
if (version.compareTo(ProtocolVersion.MINECRAFT_1_20_2) < 0) {
// Empty name
buf.writeShort(0);
}
type.write(tag, new ByteBufOutputStream(buf));
} catch (IOException e) {
throw new EncoderException("Unable to encode NBT CompoundTag");
throw new EncoderException("Unable to encode BinaryTag");
}
}

Datei anzeigen

@ -34,6 +34,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_1;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_4;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_2;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_3;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_7_2;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9;
@ -62,6 +63,7 @@ import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import com.velocitypowered.proxy.protocol.packet.PingIdentify;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
import com.velocitypowered.proxy.protocol.packet.RemoveResourcePack;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponse;
import com.velocitypowered.proxy.protocol.packet.Respawn;
@ -154,10 +156,16 @@ public enum StateRegistry {
clientbound.register(
RegistrySync.class, RegistrySync::new, map(0x05, MINECRAFT_1_20_2, false));
clientbound.register(
ResourcePackRequest.class, ResourcePackRequest::new, map(0x06, MINECRAFT_1_20_2, false));
clientbound.register(
ActiveFeatures.class, ActiveFeatures::new, map(0x07, MINECRAFT_1_20_2, false));
clientbound.register(TagsUpdate.class, TagsUpdate::new, map(0x08, MINECRAFT_1_20_2, false));
RemoveResourcePack.class, RemoveResourcePack::new, map(0x06, MINECRAFT_1_20_3, false));
clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new,
map(0x06, MINECRAFT_1_20_2, false),
map(0x07, MINECRAFT_1_20_3, false));
clientbound.register(ActiveFeatures.class, ActiveFeatures::new,
map(0x07, MINECRAFT_1_20_2, false),
map(0x08, MINECRAFT_1_20_3, false));
clientbound.register(TagsUpdate.class, TagsUpdate::new,
map(0x08, MINECRAFT_1_20_2, false),
map(0x09, MINECRAFT_1_20_3, false));
}
},
PLAY {
@ -228,7 +236,8 @@ public enum StateRegistry {
map(0x0D, MINECRAFT_1_19_1, false),
map(0x0C, MINECRAFT_1_19_3, false),
map(0x0D, MINECRAFT_1_19_4, false),
map(0x0F, MINECRAFT_1_20_2, false));
map(0x0F, MINECRAFT_1_20_2, false),
map(0x10, MINECRAFT_1_20_3, false));
serverbound.register(
KeepAlive.class,
KeepAlive::new,
@ -244,7 +253,8 @@ public enum StateRegistry {
map(0x12, MINECRAFT_1_19_1, false),
map(0x11, MINECRAFT_1_19_3, false),
map(0x12, MINECRAFT_1_19_4, false),
map(0x14, MINECRAFT_1_20_2, false));
map(0x14, MINECRAFT_1_20_2, false),
map(0x15, MINECRAFT_1_20_3, false));
serverbound.register(
ResourcePackResponse.class,
ResourcePackResponse::new,
@ -257,7 +267,8 @@ public enum StateRegistry {
map(0x21, MINECRAFT_1_16_2, false),
map(0x23, MINECRAFT_1_19, false),
map(0x24, MINECRAFT_1_19_1, false),
map(0x27, MINECRAFT_1_20_2, false));
map(0x27, MINECRAFT_1_20_2, false),
map(0x28, MINECRAFT_1_20_3, false));
serverbound.register(
FinishedUpdate.class, FinishedUpdate::new, map(0x0B, MINECRAFT_1_20_2, false));
@ -385,7 +396,10 @@ public enum StateRegistry {
map(0x3E, MINECRAFT_1_19_1, true),
map(0x3D, MINECRAFT_1_19_3, true),
map(0x41, MINECRAFT_1_19_4, true),
map(0x43, MINECRAFT_1_20_2, true));
map(0x43, MINECRAFT_1_20_2, true),
map(0x45, MINECRAFT_1_20_3, true));
clientbound.register(
RemoveResourcePack.class, RemoveResourcePack::new, map(0x43, MINECRAFT_1_20_3, false));
clientbound.register(
ResourcePackRequest.class,
ResourcePackRequest::new,
@ -403,7 +417,8 @@ public enum StateRegistry {
map(0x3D, MINECRAFT_1_19_1, false),
map(0x3C, MINECRAFT_1_19_3, false),
map(0x40, MINECRAFT_1_19_4, false),
map(0x42, MINECRAFT_1_20_2, false));
map(0x42, MINECRAFT_1_20_2, false),
map(0x44, MINECRAFT_1_20_3, false));
clientbound.register(
HeaderAndFooter.class,
HeaderAndFooter::new,
@ -422,7 +437,8 @@ public enum StateRegistry {
map(0x63, MINECRAFT_1_19_1, true),
map(0x61, MINECRAFT_1_19_3, true),
map(0x65, MINECRAFT_1_19_4, true),
map(0x68, MINECRAFT_1_20_2, true));
map(0x68, MINECRAFT_1_20_2, true),
map(0x6A, MINECRAFT_1_20_3, true));
clientbound.register(
LegacyTitlePacket.class,
LegacyTitlePacket::new,
@ -440,7 +456,8 @@ public enum StateRegistry {
map(0x5B, MINECRAFT_1_19_1, true),
map(0x59, MINECRAFT_1_19_3, true),
map(0x5D, MINECRAFT_1_19_4, true),
map(0x5F, MINECRAFT_1_20_2, true));
map(0x5F, MINECRAFT_1_20_2, true),
map(0x61, MINECRAFT_1_20_3, true));
clientbound.register(
TitleTextPacket.class,
TitleTextPacket::new,
@ -449,7 +466,8 @@ public enum StateRegistry {
map(0x5D, MINECRAFT_1_19_1, true),
map(0x5B, MINECRAFT_1_19_3, true),
map(0x5F, MINECRAFT_1_19_4, true),
map(0x61, MINECRAFT_1_20_2, true));
map(0x61, MINECRAFT_1_20_2, true),
map(0x63, MINECRAFT_1_20_3, true));
clientbound.register(
TitleActionbarPacket.class,
TitleActionbarPacket::new,
@ -458,7 +476,8 @@ public enum StateRegistry {
map(0x43, MINECRAFT_1_19_1, true),
map(0x42, MINECRAFT_1_19_3, true),
map(0x46, MINECRAFT_1_19_4, true),
map(0x48, MINECRAFT_1_20_2, true));
map(0x48, MINECRAFT_1_20_2, true),
map(0x4A, MINECRAFT_1_20_3, true));
clientbound.register(
TitleTimesPacket.class,
TitleTimesPacket::new,
@ -467,7 +486,8 @@ public enum StateRegistry {
map(0x5E, MINECRAFT_1_19_1, true),
map(0x5C, MINECRAFT_1_19_3, true),
map(0x60, MINECRAFT_1_19_4, true),
map(0x62, MINECRAFT_1_20_2, true));
map(0x62, MINECRAFT_1_20_2, true),
map(0x64, MINECRAFT_1_20_3, true));
clientbound.register(
TitleClearPacket.class,
TitleClearPacket::new,
@ -507,7 +527,8 @@ public enum StateRegistry {
map(0x62, MINECRAFT_1_19_1, true),
map(0x60, MINECRAFT_1_19_3, true),
map(0x64, MINECRAFT_1_19_4, true),
map(0x67, MINECRAFT_1_20_2, true));
map(0x67, MINECRAFT_1_20_2, true),
map(0x69, MINECRAFT_1_20_3, true));
clientbound.register(
PlayerChatCompletion.class,
PlayerChatCompletion::new,
@ -522,8 +543,13 @@ public enum StateRegistry {
map(0x42, MINECRAFT_1_19_1, false),
map(0x41, MINECRAFT_1_19_3, false),
map(0x45, MINECRAFT_1_19_4, false),
map(0x47, MINECRAFT_1_20_2, false));
clientbound.register(StartUpdate.class, StartUpdate::new, map(0x65, MINECRAFT_1_20_2, false));
map(0x47, MINECRAFT_1_20_2, false),
map(0x49, MINECRAFT_1_20_3, false));
clientbound.register(
StartUpdate.class,
StartUpdate::new,
map(0x65, MINECRAFT_1_20_2, false),
map(0x67, MINECRAFT_1_20_3, false));
}
},
LOGIN {

Datei anzeigen

@ -21,6 +21,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -35,7 +36,7 @@ public class BossBar implements MinecraftPacket {
public static final int UPDATE_PROPERTIES = 5;
private @Nullable UUID uuid;
private int action;
private @Nullable String name;
private @Nullable ComponentHolder name;
private float percent;
private int color;
private int overlay;
@ -60,11 +61,11 @@ public class BossBar implements MinecraftPacket {
this.action = action;
}
public @Nullable String getName() {
public @Nullable ComponentHolder getName() {
return name;
}
public void setName(String name) {
public void setName(ComponentHolder name) {
this.name = name;
}
@ -119,7 +120,7 @@ public class BossBar implements MinecraftPacket {
this.action = ProtocolUtils.readVarInt(buf);
switch (action) {
case ADD:
this.name = ProtocolUtils.readString(buf);
this.name = ComponentHolder.read(buf, version);
this.percent = buf.readFloat();
this.color = ProtocolUtils.readVarInt(buf);
this.overlay = ProtocolUtils.readVarInt(buf);
@ -131,7 +132,7 @@ public class BossBar implements MinecraftPacket {
this.percent = buf.readFloat();
break;
case UPDATE_NAME:
this.name = ProtocolUtils.readString(buf);
this.name = ComponentHolder.read(buf, version);
break;
case UPDATE_STYLE:
this.color = ProtocolUtils.readVarInt(buf);
@ -157,7 +158,7 @@ public class BossBar implements MinecraftPacket {
if (name == null) {
throw new IllegalStateException("No name specified!");
}
ProtocolUtils.writeString(buf, name);
name.write(buf, version);
buf.writeFloat(percent);
ProtocolUtils.writeVarInt(buf, color);
ProtocolUtils.writeVarInt(buf, overlay);
@ -172,7 +173,7 @@ public class BossBar implements MinecraftPacket {
if (name == null) {
throw new IllegalStateException("No name specified!");
}
ProtocolUtils.writeString(buf, name);
name.write(buf, version);
break;
case UPDATE_STYLE:
ProtocolUtils.writeVarInt(buf, color);

Datei anzeigen

@ -17,39 +17,36 @@
package com.velocitypowered.proxy.protocol.packet;
import static com.velocitypowered.proxy.protocol.ProtocolUtils.writeString;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import io.netty.buffer.ByteBuf;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class HeaderAndFooter implements MinecraftPacket {
private static final String EMPTY_COMPONENT = "{\"translate\":\"\"}";
private static final HeaderAndFooter RESET = new HeaderAndFooter();
private final String header;
private final String footer;
private final ComponentHolder header;
private final ComponentHolder footer;
public HeaderAndFooter() {
this(EMPTY_COMPONENT, EMPTY_COMPONENT);
this(ComponentHolder.EMPTY, ComponentHolder.EMPTY);
}
public HeaderAndFooter(String header, String footer) {
public HeaderAndFooter(ComponentHolder header, ComponentHolder footer) {
this.header = Preconditions.checkNotNull(header, "header");
this.footer = Preconditions.checkNotNull(footer, "footer");
}
public String getHeader() {
public ComponentHolder getHeader() {
return header;
}
public String getFooter() {
public ComponentHolder getFooter() {
return footer;
}
@ -60,8 +57,8 @@ public class HeaderAndFooter implements MinecraftPacket {
@Override
public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
writeString(buf, header);
writeString(buf, footer);
header.write(buf, version);
footer.write(buf, version);
}
@Override
@ -71,8 +68,8 @@ public class HeaderAndFooter implements MinecraftPacket {
public static HeaderAndFooter create(Component header,
Component footer, ProtocolVersion protocolVersion) {
GsonComponentSerializer serializer = ProtocolUtils.getJsonChatSerializer(protocolVersion);
return new HeaderAndFooter(serializer.serialize(header), serializer.serialize(footer));
return new HeaderAndFooter(new ComponentHolder(protocolVersion, header),
new ComponentHolder(protocolVersion, footer));
}
public static HeaderAndFooter reset() {

Datei anzeigen

@ -255,12 +255,12 @@ public class JoinGame implements MinecraftPacket {
this.previousGamemode = buf.readByte();
this.levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf));
this.registry = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
this.registry = ProtocolUtils.readCompoundTag(buf, version, JOINGAME_READER);
String dimensionIdentifier;
String levelName = null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, version, JOINGAME_READER);
dimensionIdentifier = ProtocolUtils.readString(buf);
} else {
dimensionIdentifier = ProtocolUtils.readString(buf);
@ -390,10 +390,10 @@ public class JoinGame implements MinecraftPacket {
buf.writeByte(previousGamemode);
ProtocolUtils.writeStringArray(buf, levelNames.toArray(String[]::new));
ProtocolUtils.writeCompoundTag(buf, this.registry);
ProtocolUtils.writeBinaryTag(buf, version, this.registry);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
ProtocolUtils.writeCompoundTag(buf, currentDimensionData);
ProtocolUtils.writeBinaryTag(buf, version, currentDimensionData);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());

Datei anzeigen

@ -0,0 +1,54 @@
/*
* Copyright (C) 2018-2021 Velocity 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 <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.protocol.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
public class RemoveResourcePack implements MinecraftPacket {
private UUID id;
public RemoveResourcePack() {
}
public RemoveResourcePack(UUID id) {
this.id = id;
}
@Override
public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) {
this.id = ProtocolUtils.readUuid(buf);
}
@Override
public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) {
ProtocolUtils.writeUuid(buf, id);
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this);
}
}

Datei anzeigen

@ -25,24 +25,33 @@ import com.velocitypowered.proxy.connection.player.VelocityResourcePackInfo;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
import java.util.regex.Pattern;
public class ResourcePackRequest implements MinecraftPacket {
private @MonotonicNonNull UUID id; // 1.20.3+
private @MonotonicNonNull String url;
private @MonotonicNonNull String hash;
private boolean isRequired; // 1.17+
private @Nullable Component prompt; // 1.17+
private @Nullable ComponentHolder prompt; // 1.17+
private static final Pattern PLAUSIBLE_SHA1_HASH = Pattern.compile("^[a-z0-9]{40}$"); // 1.20.2+
public @Nullable UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public @Nullable String getUrl() {
return url;
}
@ -67,22 +76,25 @@ public class ResourcePackRequest implements MinecraftPacket {
isRequired = required;
}
public @Nullable Component getPrompt() {
public @Nullable ComponentHolder getPrompt() {
return prompt;
}
public void setPrompt(Component prompt) {
public void setPrompt(ComponentHolder prompt) {
this.prompt = prompt;
}
@Override
public void decode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) {
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_20_3) >= 0) {
this.id = ProtocolUtils.readUuid(buf);
}
this.url = ProtocolUtils.readString(buf);
this.hash = ProtocolUtils.readString(buf);
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) {
this.isRequired = buf.readBoolean();
if (buf.readBoolean()) {
this.prompt = GsonComponentSerializer.gson().deserialize(ProtocolUtils.readString(buf));
this.prompt = ComponentHolder.read(buf, protocolVersion);
} else {
this.prompt = null;
}
@ -91,6 +103,12 @@ public class ResourcePackRequest implements MinecraftPacket {
@Override
public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVersion) {
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_20_3) >= 0) {
if (id == null) {
throw new IllegalStateException("Resource pack id not set yet!");
}
ProtocolUtils.writeUuid(buf, id);
}
if (url == null || hash == null) {
throw new IllegalStateException("Packet not fully filled in yet!");
}
@ -100,7 +118,7 @@ public class ResourcePackRequest implements MinecraftPacket {
buf.writeBoolean(isRequired);
if (prompt != null) {
buf.writeBoolean(true);
ProtocolUtils.writeString(buf, GsonComponentSerializer.gson().serialize(prompt));
prompt.write(buf, protocolVersion);
} else {
buf.writeBoolean(false);
}
@ -109,7 +127,8 @@ public class ResourcePackRequest implements MinecraftPacket {
public VelocityResourcePackInfo toServerPromptedPack() {
ResourcePackInfo.Builder builder =
new VelocityResourcePackInfo.BuilderImpl(Preconditions.checkNotNull(url)).setPrompt(prompt)
new VelocityResourcePackInfo.BuilderImpl(Preconditions.checkNotNull(url))
.setId(id).setPrompt(prompt == null ? null : prompt.getComponent())
.setShouldForce(isRequired).setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
if (hash != null && !hash.isEmpty()) {

Datei anzeigen

@ -165,7 +165,7 @@ public class Respawn implements MinecraftPacket {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, BinaryTagIO.reader());
this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, version, BinaryTagIO.reader());
dimensionIdentifier = ProtocolUtils.readString(buf);
} else {
dimensionIdentifier = ProtocolUtils.readString(buf);
@ -210,7 +210,7 @@ public class Respawn implements MinecraftPacket {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
ProtocolUtils.writeCompoundTag(buf, currentDimensionData);
ProtocolUtils.writeBinaryTag(buf, version, currentDimensionData);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());

Datei anzeigen

@ -22,23 +22,23 @@ import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import io.netty.buffer.ByteBuf;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class ServerData implements MinecraftPacket {
private @Nullable Component description;
private @Nullable ComponentHolder description;
private @Nullable Favicon favicon;
private boolean secureChatEnforced; // Added in 1.19.1
public ServerData() {
}
public ServerData(@Nullable Component description, @Nullable Favicon favicon,
boolean secureChatEnforced) {
public ServerData(@Nullable ComponentHolder description, @Nullable Favicon favicon,
boolean secureChatEnforced) {
this.description = description;
this.favicon = favicon;
this.secureChatEnforced = secureChatEnforced;
@ -48,8 +48,7 @@ public class ServerData implements MinecraftPacket {
public void decode(ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion protocolVersion) {
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_19_4) >= 0 || buf.readBoolean()) {
this.description = ProtocolUtils.getJsonChatSerializer(protocolVersion)
.deserialize(ProtocolUtils.readString(buf));
this.description = ComponentHolder.read(buf, protocolVersion);
}
if (buf.readBoolean()) {
String iconBase64;
@ -77,10 +76,7 @@ public class ServerData implements MinecraftPacket {
buf.writeBoolean(hasDescription);
}
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_19_4) >= 0 || hasDescription) {
ProtocolUtils.writeString(
buf,
ProtocolUtils.getJsonChatSerializer(protocolVersion).serialize(this.description)
);
this.description.write(buf, protocolVersion);
}
boolean hasFavicon = this.favicon != null;
@ -108,7 +104,7 @@ public class ServerData implements MinecraftPacket {
return handler.handle(this);
}
public @Nullable Component getDescription() {
public @Nullable ComponentHolder getDescription() {
return description;
}

Datei anzeigen

@ -22,6 +22,7 @@ import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
@ -31,7 +32,6 @@ import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
public class UpsertPlayerInfo implements MinecraftPacket {
@ -179,16 +179,14 @@ public class UpsertPlayerInfo implements MinecraftPacket {
}),
UPDATE_DISPLAY_NAME((version, buf, info) -> { // read
if (buf.readBoolean()) {
info.displayName = ProtocolUtils.getJsonChatSerializer(version)
.deserialize(ProtocolUtils.readString(buf));
info.displayName = ComponentHolder.read(buf, version);
} else {
info.displayName = null;
}
}, (version, buf, info) -> { // write
buf.writeBoolean(info.displayName != null);
if (info.displayName != null) {
ProtocolUtils.writeString(buf, ProtocolUtils.getJsonChatSerializer(version)
.serialize(info.displayName));
info.displayName.write(buf, version);
}
});
@ -219,7 +217,7 @@ public class UpsertPlayerInfo implements MinecraftPacket {
private int latency;
private int gameMode;
@Nullable
private Component displayName;
private ComponentHolder displayName;
@Nullable
private RemoteChatSession chatSession;
@ -248,7 +246,7 @@ public class UpsertPlayerInfo implements MinecraftPacket {
}
@Nullable
public Component getDisplayName() {
public ComponentHolder getDisplayName() {
return displayName;
}
@ -273,7 +271,7 @@ public class UpsertPlayerInfo implements MinecraftPacket {
this.gameMode = gameMode;
}
public void setDisplayName(@Nullable Component displayName) {
public void setDisplayName(@Nullable ComponentHolder displayName) {
this.displayName = displayName;
}

Datei anzeigen

@ -0,0 +1,82 @@
package com.velocitypowered.proxy.protocol.packet.chat;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.BinaryTagIO;
import net.kyori.adventure.nbt.StringBinaryTag;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public class ComponentHolder {
public static ComponentHolder EMPTY = new ComponentHolder(null, Component.empty());
static {
EMPTY.json = "{\"text\":\"\"}";
EMPTY.binaryTag = StringBinaryTag.stringBinaryTag("");
}
private final ProtocolVersion version;
private @MonotonicNonNull Component component;
private @MonotonicNonNull String json;
private @MonotonicNonNull BinaryTag binaryTag;
public ComponentHolder(ProtocolVersion version, Component component) {
this.version = version;
this.component = component;
}
public ComponentHolder(ProtocolVersion version, String json) {
this.version = version;
this.json = json;
}
public ComponentHolder(ProtocolVersion version, BinaryTag binaryTag) {
this.version = version;
this.binaryTag = binaryTag;
}
public Component getComponent() {
if (component == null) {
if (json != null) {
component = ProtocolUtils.getJsonChatSerializer(version).deserialize(json);
} else if (binaryTag != null) {
//TODO component = deserialize(binaryTag);
throw new UnsupportedOperationException("binary tag -> component not implemented yet");
}
}
return component;
}
public String getJson() {
if (json == null) {
json = ProtocolUtils.getJsonChatSerializer(version).serialize(getComponent());
}
return json;
}
public BinaryTag getBinaryTag() {
if (binaryTag == null) {
//TODO binaryTag = serialize(getComponent());
throw new UnsupportedOperationException("component -> binary tag not implemented yet");
}
return binaryTag;
}
public static ComponentHolder read(ByteBuf buf, ProtocolVersion version) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_20_3) >= 0) {
return new ComponentHolder(version, ProtocolUtils.readBinaryTag(buf, version, BinaryTagIO.reader()));
} else {
return new ComponentHolder(version, ProtocolUtils.readString(buf));
}
}
public void write(ByteBuf buf, ProtocolVersion version) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_20_3) >= 0) {
ProtocolUtils.writeBinaryTag(buf, version, getBinaryTag());
} else {
ProtocolUtils.writeString(buf, getJson());
}
}
}

Datei anzeigen

@ -17,6 +17,7 @@
package com.velocitypowered.proxy.tablist;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.player.TabList;
import com.velocitypowered.proxy.protocol.packet.LegacyPlayerListItem;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
@ -27,6 +28,8 @@ import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo;
*/
public interface InternalTabList extends TabList {
Player getPlayer();
default void processLegacy(LegacyPlayerListItem packet) {
}

Datei anzeigen

@ -59,6 +59,11 @@ public class KeyedVelocityTabList implements InternalTabList {
this.connection = player.getConnection();
}
@Override
public Player getPlayer() {
return player;
}
@Deprecated
@Override
public void setHeaderAndFooter(Component header, Component footer) {

Datei anzeigen

@ -19,6 +19,7 @@ package com.velocitypowered.proxy.tablist;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.player.ChatSession;
import com.velocitypowered.api.proxy.player.TabListEntry;
import com.velocitypowered.api.util.GameProfile;
@ -27,6 +28,7 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.console.VelocityConsole;
import com.velocitypowered.proxy.protocol.packet.RemovePlayerInfo;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import com.velocitypowered.proxy.protocol.packet.chat.RemoteChatSession;
import java.util.ArrayList;
import java.util.Collection;
@ -64,6 +66,11 @@ public class VelocityTabList implements InternalTabList {
this.entries = Maps.newHashMap();
}
@Override
public Player getPlayer() {
return player;
}
@Override
public void setHeaderAndFooter(Component header, Component footer) {
Preconditions.checkNotNull(header, "header");
@ -103,7 +110,8 @@ public class VelocityTabList implements InternalTabList {
if (!Objects.equals(previousEntry.getDisplayNameComponent().orElse(null),
entry.getDisplayNameComponent().orElse(null))) {
actions.add(UpsertPlayerInfo.Action.UPDATE_DISPLAY_NAME);
playerInfoEntry.setDisplayName(entry.getDisplayNameComponent().get());
playerInfoEntry.setDisplayName(new ComponentHolder(player.getProtocolVersion(),
entry.getDisplayNameComponent().get()));
}
if (!Objects.equals(previousEntry.getLatency(), entry.getLatency())) {
actions.add(UpsertPlayerInfo.Action.UPDATE_LATENCY);
@ -132,7 +140,8 @@ public class VelocityTabList implements InternalTabList {
playerInfoEntry.setProfile(entry.getProfile());
if (entry.getDisplayNameComponent().isPresent()) {
actions.add(UpsertPlayerInfo.Action.UPDATE_DISPLAY_NAME);
playerInfoEntry.setDisplayName(entry.getDisplayNameComponent().get());
playerInfoEntry.setDisplayName(new ComponentHolder(player.getProtocolVersion(),
entry.getDisplayNameComponent().get()));
}
if (entry.getChatSession() != null) {
actions.add(UpsertPlayerInfo.Action.INITIALIZE_CHAT);
@ -243,7 +252,7 @@ public class VelocityTabList implements InternalTabList {
currentEntry.setLatencyWithoutUpdate(entry.getLatency());
}
if (actions.contains(UpsertPlayerInfo.Action.UPDATE_DISPLAY_NAME)) {
currentEntry.setDisplayNameWithoutUpdate(entry.getDisplayName());
currentEntry.setDisplayNameWithoutUpdate(entry.getDisplayName().getComponent());
}
if (actions.contains(UpsertPlayerInfo.Action.INITIALIZE_CHAT)) {
currentEntry.setChatSession(entry.getChatSession());

Datei anzeigen

@ -23,6 +23,8 @@ import com.velocitypowered.api.proxy.player.TabListEntry;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfo;
import java.util.Optional;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -78,7 +80,7 @@ public class VelocityTabListEntry implements TabListEntry {
public TabListEntry setDisplayName(@Nullable Component displayName) {
this.displayName = displayName;
UpsertPlayerInfo.Entry upsertEntry = this.tabList.createRawEntry(this);
upsertEntry.setDisplayName(displayName);
upsertEntry.setDisplayName(new ComponentHolder(this.tabList.getPlayer().getProtocolVersion(), displayName));
this.tabList.emitActionRaw(UpsertPlayerInfo.Action.UPDATE_DISPLAY_NAME, upsertEntry);
return this;
}

Datei anzeigen

@ -20,7 +20,7 @@ package com.velocitypowered.proxy.util.bossbar;
import com.google.common.collect.MapMaker;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import com.velocitypowered.proxy.util.collect.Enum2IntMap;
import com.velocitypowered.proxy.util.concurrent.Once;
import java.util.Collections;
@ -212,8 +212,7 @@ public class AdventureBossBarManager implements BossBar.Listener {
.proxy.protocol.packet.BossBar();
packet.setUuid(this.id);
packet.setAction(com.velocitypowered.proxy.protocol.packet.BossBar.ADD);
packet.setName(ProtocolUtils.getJsonChatSerializer(player.getProtocolVersion())
.serialize(player.translateMessage(bar.name())));
packet.setName(new ComponentHolder(player.getProtocolVersion(), player.translateMessage(bar.name())));
packet.setColor(COLORS_TO_PROTOCOL.get(bar.color()));
packet.setOverlay(OVERLAY_TO_PROTOCOL.get(bar.overlay()));
packet.setPercent(bar.progress());
@ -247,7 +246,7 @@ public class AdventureBossBarManager implements BossBar.Listener {
.proxy.protocol.packet.BossBar();
packet.setUuid(this.id);
packet.setAction(com.velocitypowered.proxy.protocol.packet.BossBar.UPDATE_NAME);
packet.setName(ProtocolUtils.getJsonChatSerializer(version).serialize(name));
packet.setName(new ComponentHolder(version, name));
return packet;
}