Skip to content

Commit 8f3e547

Browse files
committed
b
1 parent e614920 commit 8f3e547

5 files changed

Lines changed: 182 additions & 29 deletions

File tree

src/main/java/cn/nekopixel/pluginspoofer/Main.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void onEnable() {
3232

3333
configManager = new ConfigManager(this);
3434
PacketEvents.getAPI().init();
35-
getServer().getPluginManager().registerEvents(new CommandListener(configManager, adventure), this);
35+
getServer().getPluginManager().registerEvents(new CommandListener(this, configManager, adventure), this);
3636
PacketEvents.getAPI().getEventManager().registerListener(new DebugPacketListener(this, configManager));
3737

3838
CommandHandler commandHandler = new CommandHandler(this);

src/main/java/cn/nekopixel/pluginspoofer/config/ConfigManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public boolean isHoverTooltipsEnabled() {
5353
return config.getBoolean("plugins.hover-tooltips", true);
5454
}
5555

56+
public boolean shouldForceLegacyFormat() {
57+
return config.getBoolean("plugins.force-legacy-format", false);
58+
}
59+
5660
public List<String> getPaperEnabledPlugins() {
5761
if (!config.contains("plugins.paper") || !config.contains("plugins.paper.enabled")) {
5862
return new ArrayList<>();

src/main/java/cn/nekopixel/pluginspoofer/listener/CommandListener.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
import cn.nekopixel.pluginspoofer.config.ConfigManager;
44
import cn.nekopixel.pluginspoofer.utils.PluginListSender;
55
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
6+
import org.bukkit.Bukkit;
67
import org.bukkit.event.EventHandler;
78
import org.bukkit.event.EventPriority;
89
import org.bukkit.event.Listener;
910
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
1011
import org.bukkit.event.player.PlayerCommandSendEvent;
1112
import org.bukkit.event.server.TabCompleteEvent;
13+
import org.bukkit.plugin.Plugin;
1214

1315
import java.util.ArrayList;
1416

1517
public class CommandListener implements Listener {
1618
private final ConfigManager config;
1719
private final PluginListSender pluginListSender;
20+
private final Plugin plugin;
1821

19-
public CommandListener(ConfigManager config, BukkitAudiences adventure) {
22+
public CommandListener(Plugin plugin, ConfigManager config, BukkitAudiences adventure) {
23+
this.plugin = plugin;
2024
this.config = config;
2125
this.pluginListSender = new PluginListSender(config, adventure);
2226
}
@@ -35,9 +39,15 @@ public void onCommand(PlayerCommandPreprocessEvent event) {
3539
if ((cmdName.equals("pl") || cmdName.equals("plugins") ||
3640
cmdName.equals("bukkit:pl") || cmdName.equals("bukkit:plugins"))
3741
&& config.isCustomPluginListEnabled()) {
38-
pluginListSender.sendCustomPluginList(event.getPlayer());
42+
43+
Bukkit.getScheduler().runTaskLater(plugin, () -> {
44+
pluginListSender.sendCustomPluginList(event.getPlayer());
45+
}, 1L);
46+
3947
} else {
40-
event.getPlayer().sendMessage(config.getUnknownCommandMessage());
48+
Bukkit.getScheduler().runTaskLater(plugin, () -> {
49+
event.getPlayer().sendMessage(config.getUnknownCommandMessage());
50+
}, 1L);
4151
}
4252
return;
4353
}

src/main/java/cn/nekopixel/pluginspoofer/utils/PluginListSender.java

Lines changed: 163 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414
import org.bukkit.Bukkit;
1515

1616
public class PluginListSender {
17+
private static final TextColor INFO_COLOR = TextColor.color(0x00BFFF);
18+
private static final TextColor PAPER_COLOR = TextColor.color(0x00AAAA);
19+
1720
private final ConfigManager config;
1821
private final BukkitAudiences adventure;
19-
private static final Logger logger = Bukkit.getLogger();
20-
21-
private static final TextColor BUKKIT_COLOR = TextColor.fromHexString("#ea7f06");
22-
private static final TextColor INFO_COLOR = TextColor.fromHexString("#339dd7");
23-
private static final TextColor LEGACY_COLOR = BUKKIT_COLOR;
22+
private final Logger logger;
2423

2524
public PluginListSender(ConfigManager config, BukkitAudiences adventure) {
2625
this.config = config;
2726
this.adventure = adventure;
27+
this.logger = Logger.getLogger("PluginSpoofer");
2828
}
2929

3030
public void sendCustomPluginList(Player player) {
@@ -33,6 +33,13 @@ public void sendCustomPluginList(Player player) {
3333
boolean serverSupportsHover = ServerCompatibility.shouldUseHoverTooltips();
3434

3535
boolean useHover = hoverEnabled && serverSupportsHover;
36+
37+
boolean useLegacyFormat = shouldUseLegacyFormat(player);
38+
39+
if (useLegacyFormat) {
40+
sendLegacyPluginList(player);
41+
return;
42+
}
3643

3744
Component title;
3845
if (useHover) {
@@ -57,12 +64,12 @@ public void sendCustomPluginList(Player player) {
5764
}
5865

5966
if (config.isDebugEnabled() && hoverEnabled && !serverSupportsHover) {
60-
logger.warning("Your server doesn't support hover tooltips natively.");
61-
logger.warning("Consider using Paper 1.16.5+ for full hover support.");
67+
logger.warning("[PluginSpoofer] Your server doesn't support hover tooltips natively.");
68+
logger.warning("[PluginSpoofer] Consider using Paper 1.16.5+ for full hover support.");
6269
}
6370
} catch (Exception e) {
6471
if (config.isDebugEnabled()) {
65-
logger.severe("Failed to send message with Adventure API: " + e.getMessage());
72+
logger.severe("[PluginSpoofer] Failed to send message with Adventure API: " + e.getMessage());
6673
e.printStackTrace();
6774
}
6875
}
@@ -80,7 +87,7 @@ private void sendBukkitPlugins(Player player) {
8087
return;
8188
}
8289

83-
Component bukkitTitle = Component.text("Bukkit Plugins:", BUKKIT_COLOR);
90+
Component bukkitTitle = Component.text("Bukkit Plugins:", TextColor.color(0xFFD700));
8491
sendMessage(player, bukkitTitle);
8592

8693
Component pluginLine = buildPluginLine(enabled, legacy, disabled);
@@ -96,7 +103,7 @@ private void sendPaperPlugins(Player player) {
96103
return;
97104
}
98105

99-
Component paperTitle = Component.text("Paper Plugins:", NamedTextColor.DARK_AQUA);
106+
Component paperTitle = Component.text("Paper Plugins:", PAPER_COLOR);
100107
sendMessage(player, paperTitle);
101108

102109
Component pluginLine = buildPluginLine(enabled, legacy, disabled);
@@ -134,8 +141,8 @@ private Component buildPluginLine(List<String> enabled, List<String> legacy, Lis
134141
break;
135142
case LEGACY:
136143
Component legacyMarker = useHover
137-
? HoverTextBuilder.createLegacyMarker(LEGACY_COLOR)
138-
: Component.text("*", LEGACY_COLOR);
144+
? HoverTextBuilder.createLegacyMarker(NamedTextColor.GOLD)
145+
: Component.text("*", NamedTextColor.GOLD);
139146
lineComponent = lineComponent.append(legacyMarker)
140147
.append(Component.text(entry.name, NamedTextColor.GREEN));
141148
break;
@@ -149,6 +156,128 @@ private Component buildPluginLine(List<String> enabled, List<String> legacy, Lis
149156

150157
return lineComponent;
151158
}
159+
160+
private boolean shouldUseLegacyFormat(Player player) {
161+
if (config.shouldForceLegacyFormat()) {
162+
if (config.isDebugEnabled()) {
163+
logger.info("[PluginSpoofer] Force legacy format enabled for " + player.getName());
164+
}
165+
return true;
166+
}
167+
168+
try {
169+
if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
170+
Class<?> viaAPI = Class.forName("com.viaversion.viaversion.api.Via");
171+
Object api = viaAPI.getMethod("getAPI").invoke(null);
172+
Method getPlayerVersion = api.getClass().getMethod("getPlayerVersion", Object.class);
173+
int protocolVersion = (int) getPlayerVersion.invoke(api, player);
174+
175+
if (config.isDebugEnabled()) {
176+
logger.info("[PluginSpoofer] Player " + player.getName() + " protocol version: " + protocolVersion);
177+
}
178+
179+
return protocolVersion < 393;
180+
}
181+
182+
if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) {
183+
try {
184+
Class<?> protocolManager = Class.forName("com.comphenix.protocol.ProtocolLibrary");
185+
Object manager = protocolManager.getMethod("getProtocolManager").invoke(null);
186+
Method getProtocolVersion = manager.getClass().getMethod("getProtocolVersion", Player.class);
187+
Object version = getProtocolVersion.invoke(manager, player);
188+
int protocolVersion = (int) version.getClass().getMethod("getVersion").invoke(version);
189+
190+
if (config.isDebugEnabled()) {
191+
logger.info("[PluginSpoofer] Player " + player.getName() + " protocol version (ProtocolLib): " + protocolVersion);
192+
}
193+
194+
return protocolVersion < 393;
195+
} catch (Exception e) {
196+
}
197+
}
198+
} catch (Exception e) {
199+
if (config.isDebugEnabled()) {
200+
logger.warning("[PluginSpoofer] Failed to detect client version: " + e.getMessage());
201+
}
202+
}
203+
204+
String serverVersion = Bukkit.getVersion();
205+
if (serverVersion.contains("1.20") || serverVersion.contains("1.21")) {
206+
if (config.isDebugEnabled()) {
207+
logger.info("[PluginSpoofer] High version server detected, using legacy format for safety");
208+
}
209+
return true;
210+
}
211+
212+
return false;
213+
}
214+
215+
private void sendLegacyPluginList(Player player) {
216+
int totalPlugins = getTotalPluginCount();
217+
218+
player.sendMessage("§3ℹ§f Server Plugins (" + totalPlugins + "):");
219+
220+
List<String> bukkitEnabled = config.getBukkitEnabledPlugins();
221+
List<String> bukkitLegacy = config.getBukkitLegacyPlugins();
222+
List<String> bukkitDisabled = config.getBukkitDisabledPlugins();
223+
224+
if (!bukkitEnabled.isEmpty() || !bukkitLegacy.isEmpty() || !bukkitDisabled.isEmpty()) {
225+
player.sendMessage("§6Bukkit Plugins:");
226+
String pluginLine = buildLegacyPluginLine(bukkitEnabled, bukkitLegacy, bukkitDisabled);
227+
player.sendMessage(pluginLine);
228+
}
229+
230+
List<String> paperEnabled = config.getPaperEnabledPlugins();
231+
List<String> paperLegacy = config.getPaperLegacyPlugins();
232+
List<String> paperDisabled = config.getPaperDisabledPlugins();
233+
234+
if (!paperEnabled.isEmpty() || !paperLegacy.isEmpty() || !paperDisabled.isEmpty()) {
235+
player.sendMessage("§3Paper Plugins:");
236+
String pluginLine = buildLegacyPluginLine(paperEnabled, paperLegacy, paperDisabled);
237+
player.sendMessage(pluginLine);
238+
}
239+
}
240+
241+
private String buildLegacyPluginLine(List<String> enabled, List<String> legacy, List<String> disabled) {
242+
List<PluginEntry> allPlugins = new ArrayList<>();
243+
244+
for (String plugin : enabled) {
245+
allPlugins.add(new PluginEntry(plugin, PluginType.ENABLED));
246+
}
247+
for (String plugin : legacy) {
248+
allPlugins.add(new PluginEntry(plugin, PluginType.LEGACY));
249+
}
250+
for (String plugin : disabled) {
251+
allPlugins.add(new PluginEntry(plugin, PluginType.DISABLED));
252+
}
253+
254+
allPlugins.sort((a, b) -> a.name.compareToIgnoreCase(b.name));
255+
256+
StringBuilder line = new StringBuilder("§7 - ");
257+
boolean first = true;
258+
259+
for (PluginEntry entry : allPlugins) {
260+
if (!first) {
261+
line.append("§f, ");
262+
}
263+
264+
switch (entry.type) {
265+
case ENABLED:
266+
line.append("§a").append(entry.name);
267+
break;
268+
case LEGACY:
269+
line.append("§6*§a").append(entry.name);
270+
break;
271+
case DISABLED:
272+
line.append("§c").append(entry.name);
273+
break;
274+
}
275+
276+
first = false;
277+
}
278+
279+
return line.toString();
280+
}
152281

153282
private static class PluginEntry {
154283
final String name;
@@ -174,21 +303,30 @@ private int getTotalPluginCount() {
174303
}
175304

176305
private void sendMessage(Player player, Component message) {
177-
if (ServerCompatibility.isPaper() && adventure == null) {
178-
try {
179-
Method sendMessageMethod = player.getClass().getMethod("sendMessage", Component.class);
180-
sendMessageMethod.invoke(player, message);
181-
} catch (Exception e) {
182-
if (adventure != null) {
183-
adventure.player(player).sendMessage(message);
184-
} else {
185-
player.sendMessage(LegacyComponentSerializer.legacySection().serialize(message));
306+
try {
307+
if (ServerCompatibility.isPaper() && adventure == null) {
308+
try {
309+
Method sendMessageMethod = player.getClass().getMethod("sendMessage", Component.class);
310+
sendMessageMethod.invoke(player, message);
311+
} catch (Exception e) {
312+
sendLegacyMessage(player, message);
186313
}
314+
} else if (adventure != null) {
315+
adventure.player(player).sendMessage(message);
316+
} else {
317+
sendLegacyMessage(player, message);
187318
}
188-
} else if (adventure != null) {
189-
adventure.player(player).sendMessage(message);
190-
} else {
191-
player.sendMessage(LegacyComponentSerializer.legacySection().serialize(message));
319+
} catch (Exception e) {
320+
sendLegacyMessage(player, message);
321+
}
322+
}
323+
324+
private void sendLegacyMessage(Player player, Component message) {
325+
try {
326+
String legacyText = LegacyComponentSerializer.legacySection().serialize(message);
327+
player.sendMessage(legacyText);
328+
} catch (Exception e) {
329+
player.sendMessage(message.toString());
192330
}
193331
}
194332
}

src/main/resources/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ blocked-commands:
1515
plugins:
1616
enabled: true
1717
hover-tooltips: true
18+
force-legacy-format: false
1819
paper:
1920
enabled:
2021
- "Geyser-Spigot"

0 commit comments

Comments
 (0)