1313import org .bukkit .craftbukkit .v1_12_R1 .CraftServer ;
1414import org .bukkit .craftbukkit .v1_12_R1 .entity .CraftPlayer ;
1515import org .bukkit .entity .Player ;
16+ import org .bukkit .event .HandlerList ;
17+ import org .bukkit .plugin .Plugin ;
18+ import org .bukkit .plugin .RegisteredListener ;
19+ import org .spigotmc .SneakyThrow ;
20+
21+ import java .io .File ;
22+ import java .io .IOException ;
23+ import java .io .PrintWriter ;
24+ import java .lang .invoke .MethodHandle ;
25+ import java .lang .invoke .MethodHandles ;
26+ import java .lang .reflect .Field ;
27+ import java .time .LocalDateTime ;
28+ import java .time .format .DateTimeFormatter ;
29+ import java .util .Collections ;
30+ import java .util .Locale ;
31+ import java .util .Set ;
1632
1733public class CommandCatserver extends Command {
1834 public CommandCatserver (String name ) {
1935 super (name );
2036 this .description = "CatServer related commands" ;
21- this .usageMessage = "/catserver worlds|reload|reloadall|dumpitem" ; // CatRoom - Dump item command
37+ this .usageMessage = "/catserver worlds|reload|reloadall|dumpitem|dumplisteners" ;
2238 setPermission ("catserver.command.catserver" );
2339 }
2440
41+ private static final MethodHandle EVENT_TYPES_HANDLE ;
42+
43+ static {
44+ try {
45+ final Field eventTypesField = HandlerList .class .getDeclaredField ("EVENT_TYPES" );
46+ eventTypesField .setAccessible (true );
47+ EVENT_TYPES_HANDLE = MethodHandles .lookup ().unreflectGetter (eventTypesField );
48+ } catch (final ReflectiveOperationException e ) {
49+ throw new RuntimeException (e );
50+ }
51+ }
52+
2553 @ Override
2654 public boolean execute (CommandSender sender , String commandLabel , String [] args ) {
2755 if (!testPermission (sender )) return true ;
@@ -30,37 +58,52 @@ public boolean execute(CommandSender sender, String commandLabel, String[] args)
3058 return false ;
3159 }
3260
33- if (args [0 ].equals ("worlds" )) {
34- sender .sendMessage (formatStringLength ("Dim" , 8 ) + " " + formatStringLength ("Name" , 8 ) + " " + formatStringLength ("Type" , 8 ));
35- for (Integer dimension : DimensionManager .getStaticDimensionIDs ()) {
36- World world = DimensionManager .getWorld (dimension , false );
37- String name = (world != null ? world .getWorld ().getName () : "(Unload)" );
38- String type = DimensionManager .getProviderType (dimension ).toString ();
39- sender .sendMessage (formatStringLength (String .valueOf (dimension ), 8 ) + " " + formatStringLength (name , 8 ) + " " + formatStringLength (type , 8 ));
61+ switch (args [0 ].toLowerCase (Locale .ROOT )) {
62+ case "worlds" -> {
63+ sender .sendMessage (formatStringLength ("Dim" , 8 ) + " " + formatStringLength ("Name" , 8 ) + " " + formatStringLength ("Type" , 8 ));
64+ for (Integer dimension : DimensionManager .getStaticDimensionIDs ()) {
65+ World world = DimensionManager .getWorld (dimension , false );
66+ String name = (world != null ? world .getWorld ().getName () : "(Unload)" );
67+ String type = DimensionManager .getProviderType (dimension ).toString ();
68+ sender .sendMessage (formatStringLength (String .valueOf (dimension ), 8 ) + " " + formatStringLength (name , 8 ) + " " + formatStringLength (type , 8 ));
69+ }
4070 }
41- } else if (args [0 ].equals ("reload" )) {
42- CatServer .getConfig ().loadConfig ();
43- sender .sendMessage (ChatColor .GREEN + "Configuration reload complete." );
44- } else if (args [0 ].equals ("reloadall" )) {
45- CatServer .getConfig ().loadConfig ();
46- ((CraftServer ) Bukkit .getServer ()).reloadConfig ();
47- sender .sendMessage (ChatColor .GREEN + "Configuration reload complete." );
48- } else if (args [0 ].equals ("dumpitem" )) { // CatRoom start - Dump item command
49- if (!(sender instanceof Player player )) {
50- sender .sendMessage (ChatColor .RED + "Only players can use this command." );
51- return true ;
71+ case "reload" -> {
72+ CatServer .getConfig ().loadConfig ();
73+ sender .sendMessage (ChatColor .GREEN + "Configuration reload complete." );
5274 }
53- var itemInHand = ((CraftPlayer ) player ).getHandle ().getHeldItemMainhand ();
54- if (itemInHand .isEmpty ()) {
55- sender .sendMessage (ChatColor .RED + "You are not holding any item." );
56- return true ;
75+ case "reloadall" -> {
76+ CatServer .getConfig ().loadConfig ();
77+ ((CraftServer ) Bukkit .getServer ()).reloadConfig ();
78+ sender .sendMessage (ChatColor .GREEN + "Configuration reload complete." );
79+ }
80+ case "dumpitem" -> {
81+ if (!(sender instanceof Player player )) {
82+ sender .sendMessage (ChatColor .RED + "Only players can use this command." );
83+ return true ;
84+ }
85+ var itemInHand = ((CraftPlayer ) player ).getHandle ().getHeldItemMainhand ();
86+ if (itemInHand .isEmpty ()) {
87+ sender .sendMessage (ChatColor .RED + "You are not holding any item." );
88+ return true ;
89+ }
90+ sender .sendMessage (ItemStackUtils .formatItemStackToPrettyString (itemInHand ));
91+ TextComponent message = new TextComponent ("[Click to insert give command]" );
92+ message .setColor (net .md_5 .bungee .api .ChatColor .GREEN );
93+ message .setClickEvent (new ClickEvent (ClickEvent .Action .SUGGEST_COMMAND , ItemStackUtils .itemStackToGiveCommand (itemInHand )));
94+ sender .spigot ().sendMessage (message );
95+ }
96+ case "dumplisteners" -> {
97+ if (args .length < 2 ) {
98+ sender .sendMessage (ChatColor .RED + "Usage: /catserver dumplisteners tofile" );
99+ return true ;
100+ }
101+ if (args [1 ].equals ("tofile" )) {
102+ this .dumpToFile (sender );
103+ } else {
104+ sender .sendMessage (ChatColor .RED + "Usage: /catserver dumplisteners tofile" );
105+ }
57106 }
58- sender .sendMessage (ItemStackUtils .formatItemStackToPrettyString (itemInHand ));
59- TextComponent message = new TextComponent ("[Click to insert give command]" );
60- message .setColor (net .md_5 .bungee .api .ChatColor .GREEN );
61- message .setClickEvent (new ClickEvent (ClickEvent .Action .SUGGEST_COMMAND , ItemStackUtils .itemStackToGiveCommand (itemInHand )));
62- sender .spigot ().sendMessage (message );
63- // CatRoom end - Dump item command
64107 }
65108
66109 return true ;
@@ -73,4 +116,57 @@ private static String formatStringLength(String str, int size) {
73116 }
74117 return str ;
75118 }
119+
120+ private void dumpToFile (final CommandSender sender ) {
121+ final File file = new File ("debug/listeners-"
122+ + DateTimeFormatter .ofPattern ("yyyy-MM-dd_HH.mm.ss" ).format (LocalDateTime .now ()) + ".txt" );
123+ file .getParentFile ().mkdirs ();
124+ try (final PrintWriter writer = new PrintWriter (file )) {
125+ for (final String eventClass : eventClassNames ()) {
126+ final HandlerList handlers ;
127+ try {
128+ handlers = (HandlerList ) findClass (eventClass ).getMethod ("getHandlerList" ).invoke (null );
129+ } catch (final ReflectiveOperationException e ) {
130+ continue ;
131+ }
132+ if (handlers .getRegisteredListeners ().length != 0 ) {
133+ writer .println (eventClass );
134+ }
135+ for (final RegisteredListener registeredListener : handlers .getRegisteredListeners ()) {
136+ writer .println (" - " + registeredListener );
137+ }
138+ }
139+ } catch (final IOException ex ) {
140+ throw new RuntimeException (ex );
141+ }
142+ sender .sendMessage (ChatColor .GREEN + "Dumped listeners to " + file );
143+ }
144+
145+ @ SuppressWarnings ("unchecked" )
146+ private static Set <String > eventClassNames () {
147+ try {
148+ return (Set <String >) EVENT_TYPES_HANDLE .invokeExact ();
149+ } catch (final Throwable e ) {
150+ SneakyThrow .sneaky (e );
151+ return Collections .emptySet (); // Unreachable
152+ }
153+ }
154+
155+ private static Class <?> findClass (final String className ) throws ClassNotFoundException {
156+ try {
157+ return Class .forName (className );
158+ } catch (final ClassNotFoundException ignore ) {
159+ for (final Plugin plugin : Bukkit .getServer ().getPluginManager ().getPlugins ()) {
160+ if (!plugin .isEnabled ()) {
161+ continue ;
162+ }
163+
164+ try {
165+ return Class .forName (className , false , plugin .getClass ().getClassLoader ());
166+ } catch (final ClassNotFoundException ignore0 ) {
167+ }
168+ }
169+ }
170+ throw new ClassNotFoundException (className );
171+ }
76172}
0 commit comments