call a method from a different class

Discussion in 'Plugin Development' started by thechrisanator, Nov 26, 2018.

Thread Status:
Not open for further replies.
  1. Offline

    thechrisanator

    so currently I am trying to implement multiple class files to make my code much more readable.
    main class, on a command, tries to call Menu.mainMenu() which returns an Inventory.

    I dont know how to do this.

    here's what I currently have

    main:
    Code:
    @Override
        public boolean onCommand(CommandSender sender, Command cmd, String commandlabel, String[] args) {
            if (!(sender instanceof Player)) {
                sender.sendMessage(prefix + ChatColor.RED + "The console cannot open the item request inventory!");
                return true;
            }
           
            Player player = (Player) sender;
           
            if (player.hasPermission("requests.command")) {
                if (cmd.getName().equalsIgnoreCase("requests")) {
                    Inventory requestinv = Menu.mainMenu();
                    player.openInventory(requestinv);
                }
            }
            return true;
        }
    Menu:
    Code:
    public class Menu implements Listener {
    
        public Inventory mainMenu() {
           
            Inventory requestinv = Bukkit.getServer().createInventory(null, 54, ChatColor.GREEN + "The Grand Minechange");
           
            ItemStack invstack = new ItemStack(Material.ARROW, 1);
            ItemMeta invmeta = invstack.getItemMeta();
            invmeta.setUnbreakable(true);
            invmeta.setDisplayName(ChatColor.GREEN + "Next Page");
            invstack.setItemMeta(invmeta);
            requestinv.setItem(51, invstack);
            invstack = new ItemStack(Material.ARROW, 1);
            invmeta = invstack.getItemMeta();
            invmeta.setUnbreakable(true);
            invmeta.setDisplayName(ChatColor.RED + "Previous Page");
            invstack.setItemMeta(invmeta);
            requestinv.setItem(47, invstack);
            invstack = new ItemStack(Material.SUNFLOWER, 1);
            invmeta = invstack.getItemMeta();
            invmeta.setUnbreakable(true);
            invmeta.setDisplayName(ChatColor.YELLOW.toString() + ChatColor.BOLD.toString() + "Create Request");
            invstack.setItemMeta(invmeta);
            invstack.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
            requestinv.setItem(49, invstack);
           
            return requestinv;
           
        }
       
    }
    
     
  2. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator Have an instance of the Menu class in your main class. Then you can do main.mainMenu()
     
  3. Offline

    thechrisanator

    @timtower
    so I included
    public Menu menu;
    in my main class,
    but this error happens when I run the command

    Code:
    [03:35:09 ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'minechange' in plugin TheGrandMinechange v1.0.0
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[patched_1.13.2.jar:git-Paper-448]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[patched_1.13.2.jar:git-Paper-448]
            at org.bukkit.craftbukkit.v1_13_R2.CraftServer.dispatchCommand(CraftServer.java:732) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PlayerConnection.handleCommand(PlayerConnection.java:1766) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PlayerConnection.a(PlayerConnection.java:1570) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PacketPlayInChat.a(PacketPlayInChat.java:45) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PacketPlayInChat.a(PacketPlayInChat.java:5) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PlayerConnectionUtils.lambda$ensureMainThread$0(PlayerConnectionUtils.java:12) ~[patched_1.13.2.jar:git-Paper-448]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_191]
            at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_191]
            at net.minecraft.server.v1_13_R2.SystemUtils.a(SystemUtils.java:109) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.MinecraftServer.b(MinecraftServer.java:1016) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.DedicatedServer.b(DedicatedServer.java:439) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:943) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.MinecraftServer.run(MinecraftServer.java:841) ~[patched_1.13.2.jar:git-Paper-448]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_191]
    Caused by: java.lang.NullPointerException
            at me.Darkolythe.GrandMinechange.GrandMinechange.onCommand(GrandMinechange.java:45) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[patched_1.13.2.jar:git-Paper-448]
            ... 15 more
     
  4. Offline

    timtower Administrator Administrator Moderator

  5. Offline

    thechrisanator

    @timtower
    thats not what I did when I did
    public Menu menu;
    ?

    how do I init it?
     
  6. Offline

    timtower Administrator Administrator Moderator

    menu = new Menu();
    What you did there is declaring the variable.
     
  7. Offline

    thechrisanator

    and this needs to be in a method?

    also, I'll try to explain this so I better understand it.

    public Menu menu gives the main class access to the Menu class.

    menu = new Menu() creates a new instance of the Menu class which can be accessed within the method.

    is that right?
     
  8. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator "menu = new Menu()" will give the "public Menu menu" a value to use.
    For this one you can use "public Menu menu = new Menu()"
     
  9. Offline

    thechrisanator

    oh okay. thank you!

    so now that I have that figured out, how would I go about doing an InventoryClickEvent within the Menu class?
    currently its just sitting there and no errors are happening, the code just isnt running.
    @timtower
     
  10. Offline

    timtower Administrator Administrator Moderator

  11. Offline

    thechrisanator

    I would assume not.
    and this doesnt look right

    registerEvents(this, new menu.onInventoryClick());

    here's that method (which is inside Menu):

    Code:
    @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            System.out.println("x");
            Player player = (Player) event.getWhoClicked();
            if (event.getClickedInventory() != null) {
                if (event.getClickedInventory().getTitle().equals(ChatColor.GREEN + "The Grand Minechange")) {
                    if (player.getItemOnCursor().getType() == Material.AIR) {
                        ItemStack clickstack = event.getCurrentItem();
                        if (clickstack.getItemMeta().hasDisplayName()) {
                            if (clickstack.getItemMeta().getDisplayName() == ChatColor.YELLOW.toString() + ChatColor.BOLD.toString() + "Create Request") {
                                System.out.println("ietm");
                            }
                        }
                    }
                }
            }
        }
     
  12. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator That "new menu.onInventoryClick()" should only be menu
    And strings are compared with equals, not with ==
     
  13. Offline

    thechrisanator

    in main:
    Code:
    @Override
        public void onEnable() {
            registerEvents(this, menu);
            System.out.println(prefix + ChatColor.GREEN + "The Grand Minechange Enabled!");
        }
    it says "the method registerEvents is undefined for the type GrandMinechange

    and thanks!

    @timtower
     
  14. Offline

    timtower Administrator Administrator Moderator

  15. Offline

    thechrisanator

    so I need to add a method inside the Menu class too?
    I'm just as unsure about what I'm doing than I was before...
    @timtower

    a multitple class tutorial on the forums said to do this, but this doesnt work either

    Code:
    //Much eaisier then registering events in 10 diffirent methods
        public static void registerEvents(org.bukkit.plugin.Plugin plugin, Listener... listeners) {
            for (Listener listener : listeners) {
                Bukkit.getServer().getPluginManager().registerEvents(listener, plugin);
            }
        }
    I tried this now too, but its not working either

    getServer().getPluginManager().registerEvents(this, menu);

    ok, I've been trying this for 30 minutes now, I really don't know what to do

    I tried the things in the API and none of it worked.
     
    Last edited: Nov 26, 2018
  16. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator That is because the plugin is the second argument, not the first.
     
  17. Offline

    thechrisanator

    Even if I do
    RegisterEvents(menu, this);

    My IDE says its wrong
     
  18. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator Because that method does not exist. getServer().getPluginManager().registerEvents(menu, this);
     
  19. Offline

    thechrisanator

    ohhhhh. thanks!

    also, since I have a lot of questions about this stuff. do I create a new thread for each one? or..
     
  20. Offline

    timtower Administrator Administrator Moderator

    Depends how close they are to each other.
    You can always ask here, can split it if needed.
     
  21. Offline

    thechrisanator

    how do I get access to a main class method from a different class file?

    I have a method:

    Code:
        public long getCooldown(UUID uuid) {
           
            long timeleft = System.currentTimeMillis() - cooldown.get(uuid);
           
            return timeleft;
           
        }
    that I want to access from Menu
     
  22. Offline

    KarimAKL

    @thechrisanator You can do something like this:
    Code:Java
    1. //Inside some class with methods
    2. public long getCooldown(UUID uuid) {
    3. long timeleft = System.currentTimeMillis() - cooldown.get(uuid);
    4. return timeleft;
    5. }

    Code:Java
    1. //Inside main class
    2. private ClassWithMethodsNameHere whatever;
    3.  
    4. private static MainClassNameHere instance;
    5.  
    6. public void onEnable() {
    7. instance = this;
    8. whatever = new ClassWithMethodsNameHere();
    9. }
    10.  
    11. public static MainClassNameHere getInstance() {
    12. return instance;
    13. }
    14.  
    15. public ClassWithMethodsNameHere getClassWithMethods() {
    16. return whatever;
    17. }

    Code:Java
    1. //Inside Menu class
    2. private MainClassNameHere main = MainClassNameHere.getInstance();
    3.  
    4. //Then to use methods do this
    5. main.getClassWithMethods().getCooldown(uuid);

    Hope this helped somehow, if you didn't understand what is going on i could try explaining it, just ask the question.
     
  23. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator Pass the main instance along to the Menu class using the constructor.
    You do need to move the initialization of Menu to the onEnable though.

    @KarimAKL Do you have a reason to use static above constructors?
     
  24. Offline

    KarimAKL

    No, that was just one way to do it and it uses less code in the long run.
    EDIT: I use constructors myself.
     
  25. Offline

    thechrisanator

    what do you mean pass the initialization of Main to the onEnable() ?
    and what do you mean using the constructor?

    @timtower
     
  26. Offline

    timtower Administrator Administrator Moderator

  27. Offline

    thechrisanator

    so I moved
    "public Menu menu = new Menu();"
    to onEnable(),
    but my IDE says "illegal modifier for parameter menu; only final is permitted"

    I also tried removing the "public", but now my other methods dont have access to menu
     
  28. Offline

    timtower Administrator Administrator Moderator

    @thechrisanator The public Menu menu; had to stay.
    menu = new Menu(this) should be in the onEnable
     
  29. Offline

    thechrisanator

    alright! I figured it out thanks to the help of you and KarimAKL!
    thanks!
    chances are, Ill be coming back here soon haha. using multiples files is tricky at first, but hopefully Ill catch on to it quickly

    @timtower

    update:

    my InventoryClickEvent doesnt want to work:

    error:
    Code:
    [16:20:09 ERROR]: Could not pass event InventoryClickEvent to TheGrandMinechange v1.0.0
    org.bukkit.event.EventException: null
            at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:72) ~[patched_1.13.2.jar:git-Paper-448]
            at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:78) ~[patched_1.13.2.jar:git-Paper-448]
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[patched_1.13.2.jar:git-Paper-448]
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:513) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PlayerConnection.a(PlayerConnection.java:2280) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PacketPlayInWindowClick.a(SourceFile:33) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PacketPlayInWindowClick.a(SourceFile:10) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.PlayerConnectionUtils.lambda$ensureMainThread$0(PlayerConnectionUtils.java:12) ~[patched_1.13.2.jar:git-Paper-448]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_191]
            at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_191]
            at net.minecraft.server.v1_13_R2.SystemUtils.a(SystemUtils.java:109) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.MinecraftServer.b(MinecraftServer.java:1016) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.DedicatedServer.b(DedicatedServer.java:439) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:943) ~[patched_1.13.2.jar:git-Paper-448]
            at net.minecraft.server.v1_13_R2.MinecraftServer.run(MinecraftServer.java:841) ~[patched_1.13.2.jar:git-Paper-448]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_191]
    Caused by: java.lang.NullPointerException
            at me.Darkolythe.GrandMinechange.Menu.onInventoryClick(Menu.java:60) ~[?:?]
            at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor144.execute(Unknown Source) ~[?:?]
            at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:70) ~[patched_1.13.2.jar:git-Paper-448]
            ... 15 more
    menu:
    Code:
    public void onInventoryClick(InventoryClickEvent event) {
           
            int cooldowntimer = 30; //(30 minutes)
           
            Player player = (Player) event.getWhoClicked();
            if (event.getClickedInventory() != null) {
                if (event.getClickedInventory().getTitle().equals(ChatColor.GREEN.toString() + ChatColor.BOLD.toString() + "The Grand Minechange")) {
                    if (player.getItemOnCursor().getType() == Material.AIR) {
                        ItemStack clickstack = event.getCurrentItem();
                        if (clickstack.getItemMeta().hasDisplayName()) {
                            if (clickstack.getItemMeta().getDisplayName().equals(ChatColor.YELLOW.toString() + ChatColor.BOLD.toString() + "Create Request")) {
                                System.out.println("xxx");
                                long timeleft = System.currentTimeMillis() - main.getCooldown(player.getUniqueId());
                                if (timeleft > cooldowntimer * 60000) {
                                    Inventory crinv = createrequest.createInventory();
                                    player.openInventory(crinv);
                                } else {
                                    player.sendMessage(main.prefix + ChatColor.RED + "You must wait before making another request!\nTime left:" + Integer.toString((int)timeleft / 1000) + 's');
                                }
                            }
                        }
                    }
                    event.setCancelled(true);
                }
            }
        }

    main:
    Code:
    public long getCooldown(UUID uuid) {
            System.out.println("x");
            if (cooldown.containsKey(uuid)) {
                return System.currentTimeMillis() - cooldown.get(uuid);
            } else {
                cooldown.put(uuid, System.currentTimeMillis() + (30 * 60000));
                return System.currentTimeMillis() - cooldown.get(uuid);
            }
        }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Nov 26, 2018
  30. Offline

    timtower Administrator Administrator Moderator

Thread Status:
Not open for further replies.

Share This Page