Costum inventory help

Discussion in 'Plugin Development' started by __ImTheMoney__, Sep 13, 2013.

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

    __ImTheMoney__

    hey i made this code

    Code:java
    1. package me.__ImtheMoney__.Menuinv;
    2.  
    3. import java.util.Arrays;
    4.  
    5. import org.bukkit.Bukkit;
    6. import org.bukkit.ChatColor;
    7. import org.bukkit.DyeColor;
    8. import org.bukkit.GameMode;
    9. import org.bukkit.entity.Player;
    10. import org.bukkit.event.EventHandler;
    11. import org.bukkit.event.Listener;
    12. import org.bukkit.event.block.Action;
    13. import org.bukkit.event.inventory.InventoryClickEvent;
    14. import org.bukkit.event.player.PlayerInteractEvent;
    15. import org.bukkit.inventory.Inventory;
    16. import org.bukkit.inventory.ItemStack;
    17. import org.bukkit.inventory.meta.ItemMeta;
    18. import org.bukkit.material.Wool;
    19. import org.bukkit.plugin.Plugin;
    20. import org.bukkit.plugin.java.JavaPlugin;
    21.  
    22. public class Menu extends JavaPlugin implements Listener{
    23.  
    24. private Inventory inv;
    25. private ItemStack c, s, a;
    26. private Menu menu;
    27.  
    28. public Menu(Plugin p) {
    29. menu = new Menu(this);
    30. inv = Bukkit.getServer().createInventory(null, 9, "Gamemode Chooser");//null is owner so nobody is the owner 9 is number of slots always add 9 last thing is name of the inv so the string
    31.  
    32. c = createItem(DyeColor.GREEN, ChatColor.GREEN + "Creative");
    33. s = createItem(DyeColor.YELLOW, ChatColor.YELLOW +"Survival");
    34. a = createItem(DyeColor.RED, ChatColor.RED + "Adventure");
    35.  
    36. inv.setItem(2, c);
    37. inv.setItem(4, s);
    38. inv.setItem(6, a);
    39.  
    40. Bukkit.getServer().getPluginManager().registerEvents(this, p);
    41. }
    42.  
    43. private ItemStack createItem(DyeColor dc, String name) {
    44. ItemStack i = new Wool(dc).toItemStack(1);
    45. ItemMeta im = i.getItemMeta();
    46. im.setDisplayName(name);
    47. im.setLore(Arrays.asList("Set Your GameMode", "to " + name.toLowerCase() + " mode"));
    48. i.setItemMeta(im);
    49. return i;
    50.  
    51. }
    52.  
    53. public void show(Player p){
    54. p.openInventory(inv);
    55.  
    56. }
    57.  
    58. @EventHandler
    59. public void oninventoryClick(InventoryClickEvent ice){
    60. if (!ice.getInventory().getName().equalsIgnoreCase(inv.getName())) return;
    61. if(ice.getCurrentItem().getItemMeta().getDisplayName().equalsIgnoreCase("Survival")) {
    62. ice.setCancelled(true);
    63. ice.getWhoClicked().setGameMode(GameMode.SURVIVAL);
    64. }
    65. if(ice.getCurrentItem().getItemMeta().getDisplayName().equalsIgnoreCase("Creative")) {
    66. ice.setCancelled(true);
    67. ice.getWhoClicked().setGameMode(GameMode.CREATIVE);
    68. }
    69. if(ice.getCurrentItem().getItemMeta().getDisplayName().equalsIgnoreCase("Adventure")) {
    70. ice.setCancelled(true);
    71. ice.getWhoClicked().setGameMode(GameMode.ADVENTURE);
    72. }
    73. }
    74. @EventHandler
    75. public void onPlayerInteract(PlayerInteractEvent pie) {
    76. if(!(pie.getAction() == Action.RIGHT_CLICK_BLOCK));
    77. menu.show(pie.getPlayer());
    78.  
    79.  
    80. }
    81.  
    82. }



    and then i get this error in my server

    Code:
    java.lang.nosuchmethodexeption: me.__ImtheMoney__.Menuinv.Menu.<init><>
     
    

    this is y plugin yml if it helps



    Code:
    name: test
    main: me.__ImtheMoney__.Menuinv.Menu
    version: 0.1
    description: >
                  This Is IT 


    i want to thank PogoStick for his awesome tuts becouse that where i got the code from


    (Im learning costum invs atm)
     
  2. Offline

    Loogeh

    __ImTheMoney__ Probably because you don't have an onEnable() and onDisable(). Try adding those in. I think it that's what it means by <init> in the stacktrace.
     
  3. Offline

    kiwhen

    You should probably start with the basics of plugins first. Like Loogeh said, the onEnable() method is missing, which is the very first thing your plugin needs.

    There are several more issues in the code that will cause some problems as well. First, you have the private field "menu" in there, which is an instance of the class itself. Why would the class need an instance of itself, inside itself? Makes no sense.

    It's pretty obvious that the code was intended to run in a separate class, and you have just modified it to become your plugin's main class. Just change the constructor into an onEnable() method by replacing this line:
    Code:
    public Menu(Plugin p) {
    
    ... into this:

    Code:
    @Override
    public void onEnable() {
    After that, you will get some errors. Simply delete all references to the menu field. You will now be stuck with two errors; where you register the event listeners, simply replace "p" with "this", and where you do "menu.show(...)", just access the method directly, by typing "show(...)".

    In addition, you do not need to reference Bukkit in your main class. Remove it, and just use "getServer()" directly.

    Now the plugin should load correctly. However, you will get buckets of NullPointerException-errors from your InventoryClickEvent-listener.

    You must take into account that inventory clicks can occur without there being an item involved. For example, if a player clicks outside the inventory container on the screen, the item will be null. Any methods run from ice.getCurrentItem() will then trigger an NPE-error. To check for nulls, do:
    Code:
    if(ice.getCurrentItem() == null)
    Once that's done, you still have the issue of itemstacks without meta data. If a player clicks an empty slot in the inventory container, the item will be air. Air does not have meta data, which will trigger NPE-errors when you try to access it. To check for items without meta data, do:
    Code:
    if(ice.getCurrentItem().hasItemMeta())
    Now all the errors will be gone - but it still won't work. The final problem is the color code in the item's display name. Color codes in Minecraft are invisible characters, which means that a red string isn't the same as a white string. Luckily, the ChatColor enumerator provides a method called stripColor(). Use it like this:
    Code:
    String name = ChatColor.stripColor(ice.getCurrentItem().hasItemMeta().getItemMeta().getDisplayName());
    Now you can compare "name" to anything using equalsIgnoreCase(), and you will get positive hits for "survival", "creative" and "adventure".

    A few tips for moving on:
    • Don't repeat yourself. If you start typing long statements over and over, like "ice.getCurrentItem().getItemMeta().getDisplayName().equalsIgnoreCase(...)", you should re-write it to something shorter. In Java 7, the switch()-block is ideal for this kind of thing, as it takes a single condition with multiple possibilities. Like this:
      Code:
      String name = ChatColor.stripColor(ice.getCurrentItem().getItemMeta().getDisplayName());
      switch(name.toLowerCase()) {
      case "survival":
          // Do stuff
          break;
      case "creative":
          // Do stuff
          break;
      default:
          // This is like an "else"-field. Do stuff.
      }
      Note that switch() is case-sensetive, which is why I use toLowerCase(). A switch statement will enter at the matching "case", and run the code. It will continue to run each "case" down the line until it hits a "break" statement. On "break", it exits. If a matching "case" is not found, it will run the "default" block, and all blocks that follow down the line, until it hits a "break". Same thing, really.
    • Your plugin should not have more than one class extending JavaPlugin. If you find yourself in a situation where this seems to be a good solution, use a constructor to pass an instance of your main class instead.
    • Enumerators are usually named, and you can grab the enum using that name. In your code, you are looking for one of three GameModes. A quick way of doing this could be:
      Code:
      @EventHandler
      public void oninventoryClick(InventoryClickEvent ice){
          if (!ice.getInventory().getName().equalsIgnoreCase(inv.getName())) return;
          if (ice.getCurrentItem() == null) return;
          if (!ice.getCurrentItem().hasItemMeta()) return;
          String name = ChatColor.stripColor(ice.getCurrentItem().getItemMeta().getDisplayName());
          ice.getWhoClicked().setGameMode(GameMode.valueOf(name.toUpperCase()));
          ice.setCancelled(true);
      }
      ... but make sure you have spelled the item's display name correctly, otherwise this will not work.
     
    Blue_Blaze72 and Loogeh like this.
  4. Offline

    Loogeh

    kiwhen although it's not my problem, liked for such a detailed post.
     
Thread Status:
Not open for further replies.

Share This Page