From b135148dfc007e9e116ff9822c65d491ace2157c Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 27 Oct 2024 13:54:08 -0400 Subject: [PATCH 1/6] fix a typo --- .../proxy/protocol/netty/MinecraftVarintFrameDecoder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java index 7bf7563ea2..84f35381ee 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java @@ -46,6 +46,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) // skip any runs of 0x00 we might find int packetStart = in.forEachByte(FIND_NON_NUL); if (packetStart == -1) { + in.clear(); return; } in.readerIndex(packetStart); From f2d6e143ae872f7da83d69a97acca0412923c7f6 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 27 Oct 2024 14:10:33 -0400 Subject: [PATCH 2/6] Update several dependencies --- gradle/libs.versions.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 510c4d62a8..58e8e11bf3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,8 +2,8 @@ configurate3 = "3.7.3" configurate4 = "4.1.2" flare = "2.0.1" -log4j = "2.22.1" -netty = "4.1.106.Final" +log4j = "2.24.1" +netty = "4.1.114.Final" [plugins] indra-publishing = "net.kyori.indra.publishing:2.0.6" @@ -18,7 +18,7 @@ auto-service = "com.google.auto.service:auto-service:1.0.1" auto-service-annotations = "com.google.auto.service:auto-service-annotations:1.0.1" brigadier = "com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT" bstats = "org.bstats:bstats-base:3.0.2" -caffeine = "com.github.ben-manes.caffeine:caffeine:3.1.5" +caffeine = "com.github.ben-manes.caffeine:caffeine:3.1.8" checker-qual = "org.checkerframework:checker-qual:3.42.0" checkstyle = "com.puppycrawl.tools:checkstyle:10.9.3" completablefutures = "com.spotify:completable-futures:0.3.6" @@ -28,15 +28,15 @@ configurate3-gson = { module = "org.spongepowered:configurate-gson", version.ref configurate4-hocon = { module = "org.spongepowered:configurate-hocon", version.ref = "configurate4" } configurate4-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate4" } configurate4-gson = { module = "org.spongepowered:configurate-gson", version.ref = "configurate4" } -disruptor = "com.lmax:disruptor:3.4.4" -fastutil = "it.unimi.dsi:fastutil:8.5.12" +disruptor = "com.lmax:disruptor:4.0.0" +fastutil = "it.unimi.dsi:fastutil:8.5.15" flare-core = { module = "space.vectrix.flare:flare", version.ref = "flare" } flare-fastutil = { module = "space.vectrix.flare:flare-fastutil", version.ref = "flare" } -jline = "org.jline:jline-terminal-jansi:3.23.0" +jline = "org.jline:jline-terminal-jansi:3.27.1" jopt = "net.sf.jopt-simple:jopt-simple:5.0.4" junit = "org.junit.jupiter:junit-jupiter:5.10.2" jspecify = "org.jspecify:jspecify:0.3.0" -kyori-ansi = "net.kyori:ansi:1.0.3" +kyori-ansi = "net.kyori:ansi:1.1.0" guava = "com.google.guava:guava:25.1-jre" gson = "com.google.code.gson:gson:2.10.1" guice = "com.google.inject:guice:6.0.0" From dc40e160d7dbbf63c448ca0fd6b2788d206f22eb Mon Sep 17 00:00:00 2001 From: Aaron <71191102+RealBauHD@users.noreply.github.com> Date: Sun, 27 Oct 2024 19:27:09 +0100 Subject: [PATCH 3/6] replace old velocitypowered.com links (#1399) * replace old links * content to 'PaperMC', cause its probably the best --- .github/ISSUE_TEMPLATE/bug-report.yml | 2 +- .../proxy/command/builtin/VelocityCommand.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 82cada2b6c..ec81079b61 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -44,7 +44,7 @@ body: ``` [17:44:10 INFO]: Velocity 3.3.0-SNAPSHOT (git-9d25d309-b400) [17:44:10 INFO]: Copyright 2018-2023 Velocity Contributors. Velocity is licensed under the terms of the GNU General Public License v3. - [17:44:10 INFO]: velocitypowered.com - GitHub + [17:44:10 INFO]: PaperMC - GitHub ``` validations: diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java b/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java index 79ac41e74e..85bf2061bd 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java @@ -174,10 +174,10 @@ public int run(final CommandContext context) { if (version.getName().equals("Velocity")) { final TextComponent embellishment = Component.text() .append(Component.text() - .content("velocitypowered.com") + .content("PaperMC") .color(NamedTextColor.GREEN) .clickEvent( - ClickEvent.openUrl("https://velocitypowered.com")) + ClickEvent.openUrl("https://papermc.io/software/velocity")) .build()) .append(Component.text(" - ")) .append(Component.text() From 08a42b3723633ea5eb6b96c0bb42180f3c2b07eb Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 27 Oct 2024 15:13:16 -0400 Subject: [PATCH 4/6] Replace home-made legacy hover event serializer with Adventure's implementation This technically can break backwards compatibility, but this seems to be very unlikely to be the practice in reality. (The Velocity implementation probably wasn't correct, anyway.) --- gradle/libs.versions.toml | 3 +- proxy/build.gradle.kts | 2 +- .../proxy/protocol/ProtocolUtils.java | 9 +- .../VelocityLegacyHoverEventSerializer.java | 123 ------------------ 4 files changed, 7 insertions(+), 130 deletions(-) delete mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/util/VelocityLegacyHoverEventSerializer.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 58e8e11bf3..7557ed42c2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,8 @@ spotless = "com.diffplug.spotless:6.25.0" [libraries] adventure-bom = "net.kyori:adventure-bom:4.17.0" -adventure-facet = "net.kyori:adventure-platform-facet:4.3.2" +adventure-text-serializer-json-legacy-impl = "net.kyori:adventure-text-serializer-json-legacy-impl:4.17.0" +adventure-facet = "net.kyori:adventure-platform-facet:4.3.4" asm = "org.ow2.asm:asm:9.6" auto-service = "com.google.auto.service:auto-service:1.0.1" auto-service-annotations = "com.google.auto.service:auto-service-annotations:1.0.1" diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts index 035ff24def..9b74dae57b 100644 --- a/proxy/build.gradle.kts +++ b/proxy/build.gradle.kts @@ -127,7 +127,7 @@ dependencies { runtimeOnly(libs.disruptor) implementation(libs.fastutil) implementation(platform(libs.adventure.bom)) - implementation("net.kyori:adventure-nbt") + implementation(libs.adventure.text.serializer.json.legacy.impl) implementation(libs.adventure.facet) implementation(libs.completablefutures) implementation(libs.nightconfig) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index 797a582236..ca63c1e56e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -25,7 +25,6 @@ import com.velocitypowered.api.util.GameProfile; import com.velocitypowered.proxy.crypto.IdentifiedKeyImpl; import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder; -import com.velocitypowered.proxy.protocol.util.VelocityLegacyHoverEventSerializer; import com.velocitypowered.proxy.util.except.QuietDecoderException; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; @@ -47,6 +46,7 @@ import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.json.JSONOptions; +import net.kyori.adventure.text.serializer.json.legacyimpl.NBTLegacyHoverEventSerializer; import net.kyori.option.OptionState; /** @@ -58,8 +58,7 @@ public enum ProtocolUtils { private static final GsonComponentSerializer PRE_1_16_SERIALIZER = GsonComponentSerializer.builder() .downsampleColors() - .emitLegacyHoverEvent() - .legacyHoverEventSerializer(VelocityLegacyHoverEventSerializer.INSTANCE) + .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get()) .options( OptionState.optionState() // before 1.16 @@ -74,7 +73,7 @@ public enum ProtocolUtils { .build(); private static final GsonComponentSerializer PRE_1_20_3_SERIALIZER = GsonComponentSerializer.builder() - .legacyHoverEventSerializer(VelocityLegacyHoverEventSerializer.INSTANCE) + .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get()) .options( OptionState.optionState() // after 1.16 @@ -89,7 +88,7 @@ public enum ProtocolUtils { .build(); private static final GsonComponentSerializer MODERN_SERIALIZER = GsonComponentSerializer.builder() - .legacyHoverEventSerializer(VelocityLegacyHoverEventSerializer.INSTANCE) + .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get()) .options( OptionState.optionState() // after 1.16 diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/VelocityLegacyHoverEventSerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/VelocityLegacyHoverEventSerializer.java deleted file mode 100644 index e667a9b16e..0000000000 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/VelocityLegacyHoverEventSerializer.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2020-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 . - */ - -package com.velocitypowered.proxy.protocol.util; - -import java.io.IOException; -import java.util.UUID; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.nbt.TagStringIO; -import net.kyori.adventure.nbt.api.BinaryTagHolder; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.HoverEvent; -import net.kyori.adventure.text.event.HoverEvent.ShowEntity; -import net.kyori.adventure.text.event.HoverEvent.ShowItem; -import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import net.kyori.adventure.util.Codec.Decoder; -import net.kyori.adventure.util.Codec.Encoder; -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * An implementation of {@link LegacyHoverEventSerializer} that implements the interface in the most - * literal, albeit "incompatible" way possible. - */ -public class VelocityLegacyHoverEventSerializer implements LegacyHoverEventSerializer { - - public static final LegacyHoverEventSerializer INSTANCE = - new VelocityLegacyHoverEventSerializer(); - - private VelocityLegacyHoverEventSerializer() { - - } - - private static Key legacyIdToFakeKey(byte id) { - return Key.key("velocity", "legacy_hover/id_" + id); - } - - @Override - public HoverEvent.@NonNull ShowItem deserializeShowItem(@NonNull Component input) - throws IOException { - String snbt = PlainTextComponentSerializer.plainText().serialize(input); - CompoundBinaryTag item = TagStringIO.get().asCompound(snbt); - - Key key; - String idIfString = item.getString("id", ""); - if (idIfString.isEmpty()) { - key = legacyIdToFakeKey(item.getByte("id")); - } else { - key = Key.key(idIfString); - } - - byte count = item.getByte("Count", (byte) 1); - return ShowItem.of(key, count, BinaryTagHolder.binaryTagHolder(snbt)); - } - - @Override - public HoverEvent.@NonNull ShowEntity deserializeShowEntity(@NonNull Component input, - Decoder componentDecoder) throws IOException { - String snbt = PlainTextComponentSerializer.plainText().serialize(input); - CompoundBinaryTag item = TagStringIO.get().asCompound(snbt); - - Component name; - try { - name = componentDecoder.decode(item.getString("name")); - } catch (Exception e) { - name = Component.text(item.getString("name")); - } - - return ShowEntity.of(Key.key(item.getString("type")), - UUID.fromString(item.getString("id")), - name); - } - - @Override - public @NonNull Component serializeShowItem(HoverEvent.@NonNull ShowItem input) - throws IOException { - final CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder() - .putByte("Count", (byte) input.count()); - - String keyAsString = input.item().asString(); - if (keyAsString.startsWith("velocity:legacy_hover/id_")) { - builder.putByte("id", Byte.parseByte(keyAsString - .substring("velocity:legacy_hover/id_".length()))); - } else { - builder.putString("id", keyAsString); - } - - BinaryTagHolder nbt = input.nbt(); - if (nbt != null) { - builder.put("tag", TagStringIO.get().asCompound(nbt.string())); - } - - return Component.text(TagStringIO.get().asString(builder.build())); - } - - @Override - public @NonNull Component serializeShowEntity(HoverEvent.@NonNull ShowEntity input, - Encoder componentEncoder) throws IOException { - CompoundBinaryTag.Builder tag = CompoundBinaryTag.builder() - .putString("id", input.id().toString()) - .putString("type", input.type().asString()); - Component name = input.name(); - if (name != null) { - tag.putString("name", componentEncoder.encode(name)); - } - return Component.text(TagStringIO.get().asString(tag.build())); - } -} From cefa3b272ef06715976fbea28ac5937305f2d27d Mon Sep 17 00:00:00 2001 From: Timon Date: Sun, 10 Nov 2024 00:03:34 +0100 Subject: [PATCH 5/6] feat: expose list order in TabListEntry (#1451) * feat: expose list order in TabListEntry * fix: address comment (from github) * fix: address another comment (from github) --- .../api/proxy/player/TabList.java | 21 +++++++++- .../api/proxy/player/TabListEntry.java | 39 ++++++++++++++++++- .../proxy/tablist/KeyedVelocityTabList.java | 9 ++++- .../proxy/tablist/VelocityTabList.java | 23 +++++++++-- .../proxy/tablist/VelocityTabListEntry.java | 25 +++++++++++- 5 files changed, 107 insertions(+), 10 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/TabList.java b/api/src/main/java/com/velocitypowered/api/proxy/player/TabList.java index 4d03d3a87f..feffd76e2e 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/TabList.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/TabList.java @@ -168,6 +168,25 @@ default TabListEntry buildEntry(GameProfile profile, @Nullable Component display * @deprecated Internal usage. Use {@link TabListEntry.Builder} instead. */ @Deprecated + default TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, + int gameMode, @Nullable ChatSession chatSession, boolean listed) { + return buildEntry(profile, displayName, latency, gameMode, chatSession, listed, 0); + } + + /** + * Represents an entry in a {@link Player}'s tab list. + * + * @param profile the profile + * @param displayName the display name + * @param latency the latency + * @param gameMode the game mode + * @param chatSession the chat session + * @param listed the visible status of entry + * @param listOrder the order/priority of entry in the tab list + * @return the entry + * @deprecated Internal usage. Use {@link TabListEntry.Builder} instead. + */ + @Deprecated TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, - int gameMode, @Nullable ChatSession chatSession, boolean listed); + int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java b/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java index 401d6a8da4..b5140776e0 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java @@ -139,6 +139,27 @@ default TabListEntry setListed(boolean listed) { return this; } + /** + * Returns the order/priority of this entry in the tab list. + * + * @return order of this entry + * @sinceMinecraft 1.21.2 + */ + default int getListOrder() { + return 0; + } + + /** + * Sets the order/priority of this entry in the tab list. + * + * @param order order of this entry + * @return {@code this}, for chaining + * @sinceMinecraft 1.21.2 + */ + default TabListEntry setListOrder(int order) { + return this; + } + /** * Returns a {@link Builder} to create a {@link TabListEntry}. * @@ -161,6 +182,7 @@ class Builder { private int latency = 0; private int gameMode = 0; private boolean listed = true; + private int listOrder = 0; private @Nullable ChatSession chatSession; @@ -243,7 +265,7 @@ public Builder gameMode(int gameMode) { } /** - * Sets wether this entry should be visible. + * Sets whether this entry should be visible. * * @param listed to set * @return ${code this}, for chaining @@ -254,6 +276,19 @@ public Builder listed(boolean listed) { return this; } + /** + * Sets the order/priority of this entry in the tab list. + * + * @param order to set + * @return ${code this}, for chaining + * @sinceMinecraft 1.21.2 + * @see TabListEntry#getListOrder() + */ + public Builder listOrder(int order) { + this.listOrder = order; + return this; + } + /** * Constructs the {@link TabListEntry} specified by {@code this} {@link Builder}. * @@ -266,7 +301,7 @@ public TabListEntry build() { if (profile == null) { throw new IllegalStateException("The GameProfile must be set when building a TabListEntry"); } - return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed); + return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder); } } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/KeyedVelocityTabList.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/KeyedVelocityTabList.java index 61967fbc2a..daaa9b0a62 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/KeyedVelocityTabList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/KeyedVelocityTabList.java @@ -159,12 +159,17 @@ public TabListEntry buildEntry(GameProfile profile, @Override public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, - int gameMode, - @Nullable ChatSession chatSession, boolean listed) { + int gameMode, @Nullable ChatSession chatSession, boolean listed) { return new KeyedVelocityTabListEntry(this, profile, displayName, latency, gameMode, chatSession == null ? null : chatSession.getIdentifiedKey()); } + @Override + public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, + int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder) { + return buildEntry(profile, displayName, latency, gameMode, chatSession, listed); + } + @Override public void processLegacy(LegacyPlayerListItemPacket packet) { // Packets are already forwarded on, so no need to do that here diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java index d6b4143ce4..0990119c68 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java @@ -19,6 +19,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Maps; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.player.ChatSession; import com.velocitypowered.api.proxy.player.TabListEntry; @@ -89,7 +90,7 @@ public void addEntry(TabListEntry entry1) { } else { entry = new VelocityTabListEntry(this, entry1.getProfile(), entry1.getDisplayNameComponent().orElse(null), - entry1.getLatency(), entry1.getGameMode(), entry1.getChatSession(), entry1.isListed()); + entry1.getLatency(), entry1.getGameMode(), entry1.getChatSession(), entry1.isListed(), entry1.getListOrder()); } EnumSet actions = EnumSet @@ -128,6 +129,11 @@ public void addEntry(TabListEntry entry1) { actions.add(UpsertPlayerInfoPacket.Action.UPDATE_LISTED); playerInfoEntry.setListed(entry.isListed()); } + if (!Objects.equals(previousEntry.getListOrder(), entry.getListOrder()) + && player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + actions.add(UpsertPlayerInfoPacket.Action.UPDATE_LIST_ORDER); + playerInfoEntry.setListOrder(entry.getListOrder()); + } if (!Objects.equals(previousEntry.getChatSession(), entry.getChatSession())) { ChatSession from = entry.getChatSession(); if (from != null) { @@ -162,6 +168,11 @@ public void addEntry(TabListEntry entry1) { } playerInfoEntry.setLatency(entry.getLatency()); playerInfoEntry.setListed(entry.isListed()); + if (entry.getListOrder() != 0 + && player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + actions.add(UpsertPlayerInfoPacket.Action.UPDATE_LIST_ORDER); + playerInfoEntry.setListOrder(entry.getListOrder()); + } } return entry; }); @@ -207,9 +218,9 @@ public void clearAllSilent() { @Override public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, int gameMode, - @Nullable ChatSession chatSession, boolean listed) { + @Nullable ChatSession chatSession, boolean listed, int listOrder) { return new VelocityTabListEntry(this, profile, displayName, latency, gameMode, chatSession, - listed); + listed, listOrder); } @Override @@ -246,7 +257,8 @@ private void processUpsert(EnumSet actions, 0, -1, null, - false + false, + 0 ) ); } else { @@ -274,6 +286,9 @@ private void processUpsert(EnumSet actions, if (actions.contains(UpsertPlayerInfoPacket.Action.UPDATE_LISTED)) { currentEntry.setListedWithoutUpdate(entry.isListed()); } + if (actions.contains(UpsertPlayerInfoPacket.Action.UPDATE_LIST_ORDER)) { + currentEntry.setListOrderWithoutUpdate(entry.getListOrder()); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java index 4e036504a0..352d627168 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntry.java @@ -17,6 +17,7 @@ package com.velocitypowered.proxy.tablist; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.player.ChatSession; import com.velocitypowered.api.proxy.player.TabList; import com.velocitypowered.api.proxy.player.TabListEntry; @@ -38,6 +39,7 @@ public class VelocityTabListEntry implements TabListEntry { private int latency; private int gameMode; private boolean listed; + private int listOrder; private @Nullable ChatSession session; /** @@ -45,7 +47,7 @@ public class VelocityTabListEntry implements TabListEntry { */ public VelocityTabListEntry(VelocityTabList tabList, GameProfile profile, Component displayName, int latency, - int gameMode, @Nullable ChatSession session, boolean listed) { + int gameMode, @Nullable ChatSession session, boolean listed, int listOrder) { this.tabList = tabList; this.profile = profile; this.displayName = displayName; @@ -53,6 +55,7 @@ public VelocityTabListEntry(VelocityTabList tabList, GameProfile profile, Compon this.gameMode = gameMode; this.session = session; this.listed = listed; + this.listOrder = listOrder; } @Override @@ -150,4 +153,24 @@ public VelocityTabListEntry setListed(boolean listed) { void setListedWithoutUpdate(boolean listed) { this.listed = listed; } + + @Override + public int getListOrder() { + return listOrder; + } + + @Override + public VelocityTabListEntry setListOrder(int listOrder) { + this.listOrder = listOrder; + if (tabList.getPlayer().getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21_2)) { + UpsertPlayerInfoPacket.Entry upsertEntry = this.tabList.createRawEntry(this); + upsertEntry.setListOrder(listOrder); + tabList.emitActionRaw(UpsertPlayerInfoPacket.Action.UPDATE_LIST_ORDER, upsertEntry); + } + return this; + } + + void setListOrderWithoutUpdate(int listOrder) { + this.listOrder = listOrder; + } } \ No newline at end of file From 9cfcfcf2ed5712e792114a3ab824670e25e23526 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 19 Nov 2024 20:49:17 +0300 Subject: [PATCH 6/6] Fix SystemChatPacket: Support reading packet properly in newer MC versions (#1461) --- .../proxy/protocol/packet/chat/SystemChatPacket.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java index 4224dc482d..b36014d5b4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java @@ -47,8 +47,11 @@ public ComponentHolder getComponent() { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { component = ComponentHolder.read(buf, version); - // System chat is never decoded so this doesn't matter for now - type = ChatType.values()[ProtocolUtils.readVarInt(buf)]; + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)){ + type = buf.readBoolean() ? ChatType.GAME_INFO : ChatType.SYSTEM; + } else { + type = ChatType.values()[ProtocolUtils.readVarInt(buf)]; + } } @Override