Solved Custom events not registering

Discussion in 'Spigot Plugin Development' started by Nuubles, Dec 1, 2020.

  1. The title is pretty self explanatory. All events worked with RightClickNPCEvent before until I changed the event type to a custom event. The rightClickNPC event in TalkEvent gets called, I've verified it with a simple broadcastMessage(). With the code below I can also produce the following error message with no idea what's causing it. Maybe Something to do with the event class itself?

    Code (Text):
    [16:52:05] [Server thread/ERROR]: Error occurred while enabling MissionNPCs v0.0.1 (Is it up to date?)
    org.bukkit.plugin.IllegalPluginAccessException: java.lang.NullPointerException
            at org.bukkit.plugin.SimplePluginManager.getEventListeners(SimplePluginManager.java:663) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginManager.java:616) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at net.karanteeni.missionnpcs.MissionNPCs.registerEvents(MissionNPCs.java:137) ~[?:?]
            at net.karanteeni.missionnpcs.MissionNPCs.onEnable(MissionNPCs.java:131) ~[?:?]
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:263) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:351) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:480) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at org.bukkit.craftbukkit.v1_16_R3.CraftServer.enablePlugin(CraftServer.java:494) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at org.bukkit.craftbukkit.v1_16_R3.CraftServer.enablePlugins(CraftServer.java:408) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at net.minecraft.server.v1_16_R3.MinecraftServer.loadWorld(MinecraftServer.java:435) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at net.minecraft.server.v1_16_R3.DedicatedServer.init(DedicatedServer.java:218) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:808) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$0(MinecraftServer.java:164) ~[spigot-1.16.4-R0.1-SNAPSHOT.jar:git-Spigot-37d799b-3eb7236]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_191]

    Code (Java):
    public class TalkToNPCEvent extends Event implements Cancellable {
        private static final HandlerList handlers = new HandlerList();
        private static final TalkEvent listener = new TalkEvent();
        @Getter private Player player;
        @Getter private NPC npc;
        @Getter @Setter private boolean missionFired = false;
        private boolean cancelled = false;
       
        public TalkToNPCEvent(Player player, NPC npc) {
            this.player = player;
            this.npc = npc;
        }
       
       
        @Override
        public boolean isCancelled() {
            return this.cancelled;
        }

       
        @Override
        public void setCancelled(boolean cancel) {
            this.cancelled = cancel;
        }

       
        @Override
        public HandlerList getHandlers() {
            return handlers;
        }
       
       
        public HandlerList getHandlerList() {
            return handlers;
        }

       
        public static void register(JavaPlugin plugin) {
            Bukkit.getPluginManager().registerEvents(listener, plugin);
        }
       
       
        private static class TalkEvent implements Listener {
            @EventHandler (priority = EventPriority.LOWEST)
            private void rightClickNPC(NPCRightClickEvent event) {
                TalkToNPCEvent e = new TalkToNPCEvent(
                        event.getClicker(),
                        event.getNPC());
                Bukkit.getPluginManager().callEvent(e);

                if(e.isMissionFired() || !e.isCancelled())
                    event.setCancelled(true);
            }
        }
    }

    Code (Java):
        @Override
        public void onEnable() {
            this.missionManager = new MissionManager(this);
            this.npcManager = new NPCManager(this);
            registerEvents();
            registerCommands();
        }
       
       
        private void registerEvents() {
            TalkToNPCEvent.register(this);
            this.getServer().getPluginManager().registerEvents(new PlayerClickNPC(this), this);
        }


    Code (Java):
    public class PlayerClickNPC implements Listener {
        private MissionNPCs plugin;
       
        public PlayerClickNPC(@NonNull MissionNPCs plugin) {
            this.plugin = plugin;
        }
       
       
        @EventHandler(priority = EventPriority.HIGHEST)
        public void onNPCClick(TalkToNPCEvent event) {
            NPC npc = event.getNpc();
            Player player = event.getPlayer();
            Bukkit.broadcastMessage("speak!");
            // if a mission fire did not consume this, activate the npc
            if(!event.isMissionFired())
                plugin.getNpcManager().npcActivated(npc.getId(), player);
        }
       
       
        @EventHandler
        public void onNPCDelete(NPCRemoveEvent event) {
            plugin.getNpcManager().removeNPCData(event.getNPC().getId());
        }
    }
     
     
  2. If you would use a proper debugger, you could perfectly tell where the error exactly occurs, with a stop before each line telling you what each variable contains exactly.
    Normally an IDE contains some sort of debugging solution, otherwise there are plenty of other solutions on Google, especially how to hook a debugger into a running server.

    Other than that, without looking too much into it, I'm already seeing a lot of static abuse and violation of encapsulation rules, which potentially might even lead to the problem you are encountering. I would advise against writing multiple classes into one class (with a few exceptions) - except for "saving" another class file, it's more harmful than useful.

    I'm also not sure if you defined the custom event properly. Opposite to the other static abuse, I believe the getHandlerList() method actually needs to be static for it to work properly. Just an assumption, as I'm using Kotlin only nowadays and I think to remember encountering something regarding that matter while transcribing it into a Kotlin version of custom events.
     
    • Like Like x 1
  3. Thanks, the getHandlerList needed to be static in order to work, now the code works correctly. I'll probably move the inner class into its own file later as it's causing some members to be static, but otherwise the code examples aren't using static methods except for Bukkit
     
  4. Just because I was already looking for it to verify my statement, for anyone who might look into this thread and needs it - here is my Kotlin template (from JetBrains IntelliJ IDEA) I'm using for custom events:

    Code (Text):
    #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}

    #end
    #parse("Header.kt")
    import org.bukkit.event.HandlerList

    class ${NAME} () {

        companion object {
            @JvmStatic
            private val HANDLERS = HandlerList()

            @JvmStatic
            fun getHandlerList(): HandlerList = HANDLERS
        }

        override fun getHandlers(): HandlerList {
            return HANDLERS
        }
    }