Skip to content

Commit 92c130b

Browse files
committed
Fully support 1.21.6+ for Spigot
1 parent dfd2496 commit 92c130b

8 files changed

Lines changed: 173 additions & 21 deletions

File tree

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ You can specify a list of visible commands or block specific ones from showing u
4343

4444
### Spigot & Paper
4545

46-
- Supported versions: **1.8 – 1.21.5**
46+
- Supported versions: **1.8 – 1.21.8**+
4747
- Requires: [ProtocolLib](https://github.com/dmulloy2/ProtocolLib)
4848

4949
### Paper 1.20.6+
@@ -64,6 +64,11 @@ Check out the [documentation](https://github.com/BlueTree242/AdvancedPlHide/wiki
6464
- This plugin is actively updated for the latest Minecraft versions until v3 is released.
6565
- No new features will be added to v2 — only bug fixes and compatibility updates.
6666
- The plugin works immediately after installation, but advanced features require configuration.
67+
- Sometimes Mojang does some breaking changes and plugin has to be updated to support those newer versions, this is not very common so you should test if plugin works before opening an issue. This is strictly for **Spigot** only (even Paper is unaffected).
68+
69+
70+
> Occasionally, Mojang introduces breaking changes that may require the plugin to be updated for compatibility with newer versions. While this is relatively rare, you should always test the plugin on the target version before reporting any issues.
71+
> This notice applies **strictly to Spigot**—Paper, Bungee and Velocity are unaffected.
6772
6873
> It is recommended to set the permission `bukkit.command.*` to `false` for all players.
6974

settings.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ include 'spigot:modern:V1_19_3_NMS'
4242
findProject(':spigot:modern:V1_19_3_NMS')?.name = 'V1_19_3_NMS'
4343
include 'spigot:modern:V1_20_5_NMS'
4444
findProject(':spigot:modern:V1_20_5_NMS')?.name = 'V1_20_5_NMS'
45+
include 'spigot:modern:V1_21_6_NMS'
46+
findProject(':spigot:modern:V1_21_6_NMS')?.name = 'V1_21_6_NMS'
4547

4648

4749
include 'spigot:paper'

spigot/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
2020
* END
2121
*/
22+
2223
plugins {
2324
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
2425
id("com.github.johnrengelman.shadow")
2526
}
2627
repositories {
28+
maven("https://repo.papermc.io/repository/maven-public/")
2729
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
2830
maven("https://repo.dmulloy2.net/repository/public/")
2931
maven("https://repo.destroystokyo.com/repository/maven-public/")
@@ -35,6 +37,7 @@ dependencies {
3537
implementation(project(":spigot:modern:V1_19_NMS", "reobf"))
3638
implementation(project(":spigot:modern:V1_19_3_NMS", "reobf"))
3739
implementation(project(":spigot:modern:V1_20_5_NMS", "reobf"))
40+
implementation(project(":spigot:modern:V1_21_6_NMS", "reobf"))
3841
implementation(project(":spigot:paper"))
3942
compileOnly(libs.brigadier)
4043
compileOnly(libs.spigot)

spigot/modern/V1_20_5_NMS/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ java {
2929
}
3030

3131
tasks.compileJava {
32-
options.release.set(17) // So that it compiles, otherwise it thinks Record class doesn't exist
32+
options.release.set(17)
3333
}
3434

3535
dependencies {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* LICENSE
3+
* AdvancedPlHide
4+
* -------------
5+
* Copyright (C) 2021 - 2024 BlueTree242
6+
* -------------
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as
9+
* published by the Free Software Foundation, either version 3 of the
10+
* License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public
18+
* License along with this program. If not, see
19+
* <http://www.gnu.org/licenses/gpl-3.0.html>.
20+
* END
21+
*/
22+
23+
plugins {
24+
id("io.papermc.paperweight.userdev")
25+
}
26+
27+
java {
28+
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
29+
}
30+
31+
tasks.compileJava {
32+
options.release.set(17)
33+
}
34+
35+
dependencies {
36+
paperweight.paperDevBundle("1.21.6-R0.1-SNAPSHOT")
37+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package dev.bluetree242.advancedplhide.spigot.modern;
2+
3+
import com.comphenix.protocol.PacketType;
4+
import com.comphenix.protocol.events.PacketContainer;
5+
import com.comphenix.protocol.events.PacketEvent;
6+
import com.comphenix.protocol.reflect.StructureModifier;
7+
import com.mojang.brigadier.arguments.ArgumentType;
8+
import com.mojang.brigadier.builder.ArgumentBuilder;
9+
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
10+
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
11+
import com.mojang.brigadier.suggestion.Suggestions;
12+
import com.mojang.brigadier.tree.RootCommandNode;
13+
import dev.bluetree242.advancedplhide.CompleterModifier;
14+
import dev.bluetree242.advancedplhide.Group;
15+
import dev.bluetree242.advancedplhide.impl.completer.RootNodeCommandCompleter;
16+
import net.minecraft.commands.Commands;
17+
import net.minecraft.commands.SharedSuggestionProvider;
18+
import net.minecraft.commands.synchronization.SuggestionProviders;
19+
import net.minecraft.data.registries.VanillaRegistries;
20+
import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket;
21+
import net.minecraft.network.protocol.game.ClientboundCommandsPacket;
22+
import net.minecraft.resources.ResourceLocation;
23+
import org.jetbrains.annotations.NotNull;
24+
import org.jetbrains.annotations.Nullable;
25+
26+
import java.lang.reflect.Field;
27+
import java.util.ArrayList;
28+
29+
public class V1_21_6_Handler implements ModernHandler {
30+
public static ClientboundCommandsPacket.NodeInspector<?> getCommandNodeInspector() {
31+
Field field = null;
32+
for (Field f : Commands.class.getDeclaredFields()) {
33+
if (ClientboundCommandsPacket.NodeInspector.class.isAssignableFrom(f.getType())) {
34+
field = f;
35+
field.setAccessible(true);
36+
break;
37+
}
38+
}
39+
if (field == null) throw new RuntimeException("COMMAND_NODE_INSPECTOR field not found");
40+
try {
41+
return (ClientboundCommandsPacket.NodeInspector<?>) field.get(null);
42+
} catch (IllegalAccessException e) {
43+
throw new RuntimeException(e);
44+
}
45+
}
46+
47+
@Override
48+
public void handleCommands(PacketEvent packetEvent, Group group, boolean whitelist) {
49+
ClientboundCommandsPacket packet = (ClientboundCommandsPacket) packetEvent.getPacket().getHandle();
50+
RootCommandNode<SharedSuggestionProvider> nodeOrigin = packet.getRoot(Commands.createValidationContext(VanillaRegistries.createLookup()), new CustomNodeBuilder());
51+
RootNodeCommandCompleter node = new RootNodeCommandCompleter(nodeOrigin);
52+
CompleterModifier.handleCompleter(node, group, whitelist);
53+
//noinspection unchecked
54+
packetEvent.setPacket(new PacketContainer(PacketType.Play.Server.COMMANDS, new ClientboundCommandsPacket(node.export(), getCommandNodeInspector())));
55+
}
56+
57+
@Override
58+
public Suggestions getSuggestions(PacketEvent packetEvent) {
59+
ClientboundCommandSuggestionsPacket packet = (ClientboundCommandSuggestionsPacket) packetEvent.getPacket().getHandle();
60+
Suggestions suggestions = packet.toSuggestions();
61+
return new Suggestions(suggestions.getRange(), new ArrayList<>(suggestions.getList()));
62+
}
63+
64+
@Override
65+
public void writeSuggestions(PacketEvent packetEvent, StructureModifier<Suggestions> modifier, Suggestions suggestions) {
66+
ClientboundCommandSuggestionsPacket packet = (ClientboundCommandSuggestionsPacket) packetEvent.getPacket().getHandle();
67+
packetEvent.setPacket(new PacketContainer(PacketType.Play.Server.TAB_COMPLETE, new ClientboundCommandSuggestionsPacket(packet.id(), suggestions)));
68+
}
69+
70+
private static class CustomNodeBuilder implements ClientboundCommandsPacket.NodeBuilder<SharedSuggestionProvider> {
71+
@Override
72+
public @NotNull ArgumentBuilder<SharedSuggestionProvider, ?> createLiteral(@NotNull String s) {
73+
return LiteralArgumentBuilder.literal(s);
74+
}
75+
76+
@Override
77+
public @NotNull ArgumentBuilder<SharedSuggestionProvider, ?> createArgument(@NotNull String s, @NotNull ArgumentType<?> argumentType, @Nullable ResourceLocation resourceLocation) {
78+
RequiredArgumentBuilder<SharedSuggestionProvider, ?> requiredArgumentBuilder = RequiredArgumentBuilder.argument(s, argumentType);
79+
if (resourceLocation != null) {
80+
requiredArgumentBuilder.suggests(SuggestionProviders.getProvider(resourceLocation));
81+
}
82+
return requiredArgumentBuilder;
83+
}
84+
85+
@Override
86+
public @NotNull ArgumentBuilder<SharedSuggestionProvider, ?> configure(@NotNull ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder, boolean b, boolean b1) {
87+
if (b) {
88+
argumentBuilder.executes(context -> 0);
89+
}
90+
return argumentBuilder;
91+
}
92+
}
93+
}

spigot/paper/src/main/java/dev/bluetree242/advancedplhide/spigot/paper/PaperEventListener.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ public void onSuggestions(AsyncPlayerSendSuggestionsEvent e) {
6767
if (!notCompleted.contains(" ")) {
6868
SuggestionCommandCompleterList suggestions = new SuggestionCommandCompleterList(e.getSuggestions());
6969
CompleterModifier.handleCompleter(suggestions, getGroup.apply(e.getPlayer()), e.getPlayer().hasPermission(Constants.WHITELIST_MODE_PERMISSION));
70-
suggestions.export();
7170
} else {
7271
SuggestionSubCommandCompleterList suggestions = new SuggestionSubCommandCompleterList(e.getSuggestions(), notCompleted);
7372
CompleterModifier.handleSubCompleter(suggestions, getGroup.apply(e.getPlayer()), e.getPlayer().hasPermission(Constants.WHITELIST_MODE_PERMISSION));

spigot/src/main/java/dev/bluetree242/advancedplhide/spigot/AdvancedPlHideSpigot.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@
2828
import dev.bluetree242.advancedplhide.impl.version.UpdateCheckResult;
2929
import dev.bluetree242.advancedplhide.spigot.listener.event.SpigotEventListener;
3030
import dev.bluetree242.advancedplhide.spigot.listener.packet.SpigotPacketListener;
31-
import dev.bluetree242.advancedplhide.spigot.modern.ModernHandler;
32-
import dev.bluetree242.advancedplhide.spigot.modern.V1_19_3_Handler;
33-
import dev.bluetree242.advancedplhide.spigot.modern.V1_19_Handler;
34-
import dev.bluetree242.advancedplhide.spigot.modern.V1_20_5_Handler;
31+
import dev.bluetree242.advancedplhide.spigot.modern.*;
3532
import dev.bluetree242.advancedplhide.spigot.paper.PaperEventListener;
3633
import dev.bluetree242.advancedplhide.utils.Constants;
3734
import org.bukkit.Bukkit;
@@ -99,25 +96,41 @@ public void onEnable() {
9996

10097
public void useProtocolLib() {
10198
String mv = Bukkit.getServer().getBukkitVersion();
102-
legacy = (mv.startsWith("1.8") || mv.startsWith("1.9") || mv.startsWith("1.10") || mv.startsWith("1.11") || mv.startsWith("1.12"));
99+
legacy = isLegacyVersion(mv);
103100
if (!legacy) {
104-
boolean modernNeeded = !(mv.startsWith("1.13") || mv.startsWith("1.14") || mv.startsWith("1.15") || mv.startsWith("1.16") || mv.startsWith("1.17") || mv.startsWith("1.18"));
105-
if (!modernNeeded) {
106-
modernHandler = (packetEvent, group, whitelist) -> {
107-
throw new UnsupportedOperationException();
108-
};
109-
} else if (mv.startsWith("1.19.1")) {
110-
modernHandler = new V1_19_Handler();
111-
} else if (mv.startsWith("1.19.3") || mv.startsWith("1.19.4") || (mv.startsWith("1.20") && Integer.parseInt(mv.substring(5, 6)) <= 4)) { // Expect 1.19.3+
112-
modernHandler = new V1_19_3_Handler();
113-
} else {
114-
modernHandler = new V1_20_5_Handler();
115-
}
101+
modernHandler = resolveModernHandler(mv);
116102
}
117103
protocolLibHookHandler = new ProtocolLibHookHandler();
118104
protocolLibHookHandler.hook();
119105
}
120106

107+
private boolean isLegacyVersion(String mv) {
108+
return mv.startsWith("1.8") || mv.startsWith("1.9") || mv.startsWith("1.10") ||
109+
mv.startsWith("1.11") || mv.startsWith("1.12");
110+
}
111+
112+
private ModernHandler resolveModernHandler(String mv) {
113+
if (!isModernNeeded(mv)) {
114+
return (packetEvent, group, whitelist) -> {
115+
throw new UnsupportedOperationException();
116+
};
117+
} else if (mv.startsWith("1.19.1")) {
118+
return new V1_19_Handler();
119+
} else if (mv.startsWith("1.19.3") || mv.startsWith("1.19.4") ||
120+
(mv.startsWith("1.20") && Integer.parseInt(mv.substring(5, 6)) <= 4)) {
121+
return new V1_19_3_Handler();
122+
} else if (mv.startsWith("1.21") && Integer.parseInt(mv.substring(5, 6)) <= 5) {
123+
return new V1_20_5_Handler();
124+
} else {
125+
return new V1_21_6_Handler();
126+
}
127+
}
128+
129+
private boolean isModernNeeded(String mv) {
130+
return !(mv.startsWith("1.13") || mv.startsWith("1.14") || mv.startsWith("1.15") ||
131+
mv.startsWith("1.16") || mv.startsWith("1.17") || mv.startsWith("1.18"));
132+
}
133+
121134
public void onDisable() {
122135
if (protocolLibHookHandler != null) protocolLibHookHandler.unhook();
123136
}
@@ -244,4 +257,4 @@ public Type getType() {
244257
return Type.SPIGOT;
245258
}
246259
}
247-
}
260+
}

0 commit comments

Comments
 (0)