diff --git a/build.gradle b/build.gradle index 9c9760f..3cebd13 100644 --- a/build.gradle +++ b/build.gradle @@ -22,18 +22,17 @@ repositories { maven { url = 'https://repo.papermc.io/repository/maven-public/' } maven { url = 'https://jitpack.io/' } maven { url = 'https://repo.minebench.de/' } - maven { url = 'https://mvn.exceptionflug.de/repository/exceptionflug-public/' } + maven { url = "https://maven.elytrium.net/repo/" } } dependencies { - compileOnly 'com.velocitypowered:velocity-api:3.1.1' + compileOnly 'com.velocitypowered:velocity-api:3.2.0-SNAPSHOT' + compileOnly 'com.velocitypowered:velocity-proxy:3.2.0-SNAPSHOT' compileOnly 'net.luckperms:api:5.4' - compileOnly 'dev.simplix:protocolize-api:2.2.6' compileOnly 'io.netty:netty-codec-http:4.1.91.Final' compileOnly 'io.github.miniplaceholders:miniplaceholders-api:2.0.0' compileOnly 'net.william278:PAPIProxyBridge:1.2' compileOnly 'org.projectlombok:lombok:1.18.26' - compileOnly 'net.kyori:adventure-text-minimessage:4.13.1' implementation 'org.apache.commons:commons-text:1.10.0' implementation 'net.william278:Annotaml:2.0.1' diff --git a/src/main/java/net/william278/velocitab/Velocitab.java b/src/main/java/net/william278/velocitab/Velocitab.java index 93b837b..f459f2c 100644 --- a/src/main/java/net/william278/velocitab/Velocitab.java +++ b/src/main/java/net/william278/velocitab/Velocitab.java @@ -132,10 +132,6 @@ public class Velocitab { private void prepareScoreboardManager() { if (settings.isSortPlayers()) { - if (!Hook.isPluginAvailable(this, "protocolize")) { - log("Protocolize is required to sort players by weight, but was not found. Disabling sorting."); - return; - } this.scoreboardManager = new ScoreboardManager(this); scoreboardManager.registerPacket(); } diff --git a/src/main/java/net/william278/velocitab/config/Settings.java b/src/main/java/net/william278/velocitab/config/Settings.java index 7372122..67fc320 100644 --- a/src/main/java/net/william278/velocitab/config/Settings.java +++ b/src/main/java/net/william278/velocitab/config/Settings.java @@ -92,7 +92,7 @@ public class Settings { @Getter @YamlKey("sort_players") - @YamlComment("Whether to sort players in the TAB list. Requires Protocolize to be installed.") + @YamlComment("Whether to sort players in the TAB list.") private boolean sortPlayers = true; @YamlKey("sort_players_by") diff --git a/src/main/java/net/william278/velocitab/hook/Hook.java b/src/main/java/net/william278/velocitab/hook/Hook.java index 7704f04..d493ec6 100644 --- a/src/main/java/net/william278/velocitab/hook/Hook.java +++ b/src/main/java/net/william278/velocitab/hook/Hook.java @@ -70,7 +70,7 @@ public abstract class Hook { this.plugin = plugin; } - public static boolean isPluginAvailable(@NotNull Velocitab plugin, @NotNull String id) { + private static boolean isPluginAvailable(@NotNull Velocitab plugin, @NotNull String id) { return plugin.getServer().getPluginManager().getPlugin(id).isPresent(); } diff --git a/src/main/java/net/william278/velocitab/packet/PacketRegistration.java b/src/main/java/net/william278/velocitab/packet/PacketRegistration.java new file mode 100644 index 0000000..5d6003f --- /dev/null +++ b/src/main/java/net/william278/velocitab/packet/PacketRegistration.java @@ -0,0 +1,120 @@ +/* + * This file is part of Velocitab, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.velocitab.packet; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.protocol.StateRegistry; +import org.jetbrains.annotations.NotNull; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +// Based on VPacketEvents PacketRegistration API +public final class PacketRegistration

{ + + private final Class

packetClass; + private Supplier

packetSupplier; + private ProtocolUtils.Direction direction; + private StateRegistry stateRegistry; + private final List mappings = new ArrayList<>(); + + public PacketRegistration

packetSupplier(final @NotNull Supplier

packetSupplier) { + this.packetSupplier = packetSupplier; + return this; + } + + public PacketRegistration

direction(final ProtocolUtils.Direction direction) { + this.direction = direction; + return this; + } + + public PacketRegistration

stateRegistry(final @NotNull StateRegistry stateRegistry) { + this.stateRegistry = stateRegistry; + return this; + } + + public PacketRegistration

mapping( + final int id, + final ProtocolVersion version, + final boolean encodeOnly + ) { + try { + final StateRegistry.PacketMapping mapping = (StateRegistry.PacketMapping) PACKET_MAPPING$map.invoke( + id, version, encodeOnly); + this.mappings.add(mapping); + } catch (Throwable t) { + throw new RuntimeException(t); + } + return this; + } + + public void register() { + try { + final StateRegistry.PacketRegistry packetRegistry = direction == ProtocolUtils.Direction.CLIENTBOUND + ? (StateRegistry.PacketRegistry) STATE_REGISTRY$clientBound.invoke(stateRegistry) + : (StateRegistry.PacketRegistry) STATE_REGISTRY$serverBound.invoke(stateRegistry); + PACKET_REGISTRY$register.invoke( + packetRegistry, + packetClass, + packetSupplier, + mappings.toArray(StateRegistry.PacketMapping[]::new) + ); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + public static

PacketRegistration

of(Class

packetClass) { + return new PacketRegistration<>(packetClass); + } + + private PacketRegistration(final @NotNull Class

packetClass) { + this.packetClass = packetClass; + } + + private static final MethodHandle STATE_REGISTRY$clientBound; + private static final MethodHandle STATE_REGISTRY$serverBound; + private static final MethodHandle PACKET_REGISTRY$register; + private static final MethodHandle PACKET_MAPPING$map; + + static { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + final MethodHandles.Lookup stateRegistryLookup = MethodHandles.privateLookupIn(StateRegistry.class, lookup); + STATE_REGISTRY$clientBound = stateRegistryLookup.findGetter(StateRegistry.class, "clientbound", StateRegistry.PacketRegistry.class); + STATE_REGISTRY$serverBound = stateRegistryLookup.findGetter(StateRegistry.class, "serverbound", StateRegistry.PacketRegistry.class); + + final MethodType mapType = MethodType.methodType(StateRegistry.PacketMapping.class, Integer.TYPE, ProtocolVersion.class, Boolean.TYPE); + PACKET_MAPPING$map = stateRegistryLookup.findStatic(StateRegistry.class, "map", mapType); + + final MethodHandles.Lookup packetRegistryLookup = MethodHandles.privateLookupIn(StateRegistry.PacketRegistry.class, lookup); + final MethodType registerType = MethodType.methodType(void.class, Class.class, Supplier.class, StateRegistry.PacketMapping[].class); + PACKET_REGISTRY$register = packetRegistryLookup.findVirtual(StateRegistry.PacketRegistry.class, "register", registerType); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/william278/velocitab/packet/ScoreboardManager.java b/src/main/java/net/william278/velocitab/packet/ScoreboardManager.java index ada75e2..07f70d4 100644 --- a/src/main/java/net/william278/velocitab/packet/ScoreboardManager.java +++ b/src/main/java/net/william278/velocitab/packet/ScoreboardManager.java @@ -20,16 +20,16 @@ package net.william278.velocitab.packet; import com.velocitypowered.api.proxy.Player; -import dev.simplix.protocolize.api.PacketDirection; -import dev.simplix.protocolize.api.Protocol; -import dev.simplix.protocolize.api.Protocolize; -import dev.simplix.protocolize.api.player.ProtocolizePlayer; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.protocol.StateRegistry; import net.william278.velocitab.Velocitab; import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.stream.Collectors; +import static com.velocitypowered.api.network.ProtocolVersion.*; public class ScoreboardManager { private final Velocitab plugin; @@ -85,13 +85,10 @@ public class ScoreboardManager { plugin.getTabList().removeOfflinePlayer(player); return; } + try { - ProtocolizePlayer protocolizePlayer = Protocolize.playerProvider().player(player.getUniqueId()); - if (protocolizePlayer != null) { - protocolizePlayer.sendPacket(packet); - } else { - plugin.log("Failed to get ProtocolizePlayer for player " + player.getUsername() + " (UUID: " + player.getUniqueId() + ")"); - } + final ConnectedPlayer connectedPlayer = (ConnectedPlayer) player; + connectedPlayer.getConnection().write(packet); } catch (Exception e) { plugin.log("Failed to dispatch packet (is the client or server modded or using an illegal version?)", e); } @@ -99,13 +96,19 @@ public class ScoreboardManager { public void registerPacket() { try { - Protocolize.protocolRegistration().registerPacket( - UpdateTeamsPacket.MAPPINGS, - Protocol.PLAY, - PacketDirection.CLIENTBOUND, - UpdateTeamsPacket.class - ); - } catch (Exception e) { + PacketRegistration.of(UpdateTeamsPacket.class) + .direction(ProtocolUtils.Direction.CLIENTBOUND) + .packetSupplier(UpdateTeamsPacket::new) + .stateRegistry(StateRegistry.PLAY) + .mapping(0x47, MINECRAFT_1_13, false) + .mapping(0x4B, MINECRAFT_1_14, false) + .mapping(0x4C, MINECRAFT_1_15, false) + .mapping(0x55, MINECRAFT_1_17, false) + .mapping(0x58, MINECRAFT_1_19_1, false) + .mapping(0x56, MINECRAFT_1_19_3, false) + .mapping(0x5A, MINECRAFT_1_19_4, false) + .register(); + } catch (Throwable e) { plugin.log("Failed to register UpdateTeamsPacket", e); } } diff --git a/src/main/java/net/william278/velocitab/packet/UpdateTeamsPacket.java b/src/main/java/net/william278/velocitab/packet/UpdateTeamsPacket.java index 4b36b66..1d54e94 100644 --- a/src/main/java/net/william278/velocitab/packet/UpdateTeamsPacket.java +++ b/src/main/java/net/william278/velocitab/packet/UpdateTeamsPacket.java @@ -19,11 +19,10 @@ package net.william278.velocitab.packet; -import dev.simplix.protocolize.api.PacketDirection; -import dev.simplix.protocolize.api.mapping.AbstractProtocolMapping; -import dev.simplix.protocolize.api.mapping.ProtocolIdMapping; -import dev.simplix.protocolize.api.packet.AbstractPacket; -import dev.simplix.protocolize.api.util.ProtocolUtil; +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 io.netty.buffer.ByteBuf; import lombok.*; import lombok.experimental.Accessors; @@ -36,8 +35,6 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import static dev.simplix.protocolize.api.util.ProtocolVersions.*; - @Getter @Setter @ToString @@ -45,17 +42,7 @@ import static dev.simplix.protocolize.api.util.ProtocolVersions.*; @NoArgsConstructor @EqualsAndHashCode(callSuper = false) @Accessors(fluent = true) -public class UpdateTeamsPacket extends AbstractPacket { - - protected static final List MAPPINGS = List.of( - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_13, MINECRAFT_1_13_2, 0x47), - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_14, MINECRAFT_1_14_4, 0x4B), - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_15, MINECRAFT_1_16_5, 0x4C), - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_17, MINECRAFT_1_19, 0x55), - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_19_1, MINECRAFT_1_19_2, 0x58), - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_19_3, MINECRAFT_1_19_3, 0x56), - AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_19_4, MINECRAFT_LATEST, 0x5A) - ); +public class UpdateTeamsPacket implements MinecraftPacket { private String teamName; private UpdateMode mode; @@ -99,58 +86,63 @@ public class UpdateTeamsPacket extends AbstractPacket { .entities(Arrays.asList(teamMembers)); } + @NotNull + private static String getChatString(@NotNull String string) { + return "{\"text\":\"" + StringEscapeUtils.escapeJson(string) + "\"}"; + } + @Override - public void read(ByteBuf byteBuf, PacketDirection packetDirection, int i) { - teamName = ProtocolUtil.readString(byteBuf); + public void decode(ByteBuf byteBuf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + teamName = ProtocolUtils.readString(byteBuf); mode = UpdateMode.byId(byteBuf.readByte()); if (mode == UpdateMode.REMOVE_TEAM) { return; } if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.UPDATE_INFO) { - displayName = ProtocolUtil.readString(byteBuf); + displayName = ProtocolUtils.readString(byteBuf); friendlyFlags = FriendlyFlag.fromBitMask(byteBuf.readByte()); - nameTagVisibility = NameTagVisibility.byId(ProtocolUtil.readString(byteBuf)); - collisionRule = CollisionRule.byId(ProtocolUtil.readString(byteBuf)); + nameTagVisibility = NameTagVisibility.byId(ProtocolUtils.readString(byteBuf)); + collisionRule = CollisionRule.byId(ProtocolUtils.readString(byteBuf)); color = byteBuf.readByte(); - prefix = ProtocolUtil.readString(byteBuf); - suffix = ProtocolUtil.readString(byteBuf); + prefix = ProtocolUtils.readString(byteBuf); + suffix = ProtocolUtils.readString(byteBuf); } if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.ADD_PLAYERS || mode == UpdateMode.REMOVE_PLAYERS) { - int entityCount = ProtocolUtil.readVarInt(byteBuf); + int entityCount = ProtocolUtils.readVarInt(byteBuf); entities = new ArrayList<>(entityCount); for (int j = 0; j < entityCount; j++) { - entities.add(ProtocolUtil.readString(byteBuf)); + entities.add(ProtocolUtils.readString(byteBuf)); } } } @Override - public void write(ByteBuf byteBuf, PacketDirection packetDirection, int i) { - ProtocolUtil.writeString(byteBuf, teamName); + public void encode(ByteBuf byteBuf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + ProtocolUtils.writeString(byteBuf, teamName); byteBuf.writeByte(mode.id()); if (mode == UpdateMode.REMOVE_TEAM) { return; } if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.UPDATE_INFO) { - ProtocolUtil.writeString(byteBuf, displayName); + ProtocolUtils.writeString(byteBuf, displayName); byteBuf.writeByte(FriendlyFlag.toBitMask(friendlyFlags)); - ProtocolUtil.writeString(byteBuf, nameTagVisibility.id()); - ProtocolUtil.writeString(byteBuf, collisionRule.id()); + ProtocolUtils.writeString(byteBuf, nameTagVisibility.id()); + ProtocolUtils.writeString(byteBuf, collisionRule.id()); byteBuf.writeByte(color); - ProtocolUtil.writeString(byteBuf, prefix); - ProtocolUtil.writeString(byteBuf, suffix); + ProtocolUtils.writeString(byteBuf, prefix); + ProtocolUtils.writeString(byteBuf, suffix); } if (mode == UpdateMode.CREATE_TEAM || mode == UpdateMode.ADD_PLAYERS || mode == UpdateMode.REMOVE_PLAYERS) { - ProtocolUtil.writeVarInt(byteBuf, entities != null ? entities.size() : 0); + ProtocolUtils.writeVarInt(byteBuf, entities != null ? entities.size() : 0); for (String entity : entities != null ? entities : new ArrayList()) { - ProtocolUtil.writeString(byteBuf, entity); + ProtocolUtils.writeString(byteBuf, entity); } } } - @NotNull - private static String getChatString(@NotNull String string) { - return "{\"text\":\"" + StringEscapeUtils.escapeJson(string) + "\"}"; + @Override + public boolean handle(MinecraftSessionHandler minecraftSessionHandler) { + return false; } public enum UpdateMode { diff --git a/src/main/resources/velocity-plugin.json b/src/main/resources/velocity-plugin.json index 18f3139..d487004 100644 --- a/src/main/resources/velocity-plugin.json +++ b/src/main/resources/velocity-plugin.json @@ -8,10 +8,6 @@ "William278" ], "dependencies": [ - { - "id": "protocolize", - "optional": true - }, { "id": "luckperms", "optional": true