Cooldowns

Discussion in 'Spigot Plugin Development' started by sandor_1234, Apr 23, 2017.

  1. I am trying to get this to work:
    Code (Text):
    package nl.sandor.cooldown;

    import java.util.ArrayList;

    import org.bukkit.ChatColor;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerInteractEvent;

    public class listerner
    implements Listener
    {
    @EventHandler(priority=EventPriority.HIGH)
    public void onPlayerInteract(PlayerInteractEvent event)
    {
        if ((event.getAction().toString().equals("LEFT_CLICK_BLOCK"))  || (event.getAction().toString().equals("LEFT_CLICK_AIR"))){
        if ((event.getItem().getItemMeta().getLore().contains(ChatColor.MAGIC + "$"))){
        if ((event.getItem().getItemMeta().getDisplayName().equals(ChatColor.RED + "Empire Wand"))){
            ArrayList<String> ItemLore = new ArrayList<String>();
            ArrayList<String> ItemLore2 = new ArrayList<String>();
            ItemLore.add(ChatColor.MAGIC + "c");
            ItemLore2.add(ChatColor.MAGIC + "$");
            event.getItem().getItemMeta().setLore(ItemLore);;
            /**
             * Wait 3 seconds
             */
            event.getItem().getItemMeta().setLore(ItemLore2);;
          }
    }
    }
    }
    }
     
    '
    So it set the lore to &kc and after 3 second it sets it back to &k$. How can i do this? I am very new to java.
     
  2. This should help you: Bukkit.getScheduler().runTaskLater
    Edit: Bukkit.getScheduler ().runTaskLater (main, () -> event.getItem().getItemMeta().setLore(ItemLore2), 60);
     
  3. Seeing you're very new to java, those 'mistakes' in your code are understandable for me.
    Here are two things I'd at least do differently:
    1. You can compare actions with ==, so to detect LEFT_CLICK_BLOCK, you could do:
    Code (Java):
    if (event.getAction() == Action.LEFT_CLICK_BLOCK || .. )
    This is because 'Action' is an enum, and you can compare enum constants with the == statement. This is a small optimization, of course; it will work that way too. I just don't recommend doing it like that, because comparing Strings is a lot slower.

    2. the 'event.getItem().getItemMeta().getDisplayName()' can return null. This will be the case if an item doesn't have a set custom name, so for example; if you chop down a tree and collect the logs, their name will be 'Oak Wood' (Depending on the chosen language). Yes, one would think it has a name, but that's the name defined by the resourcepack, not a custom displayname.

    Also, formatting makes your code more readable :) If you're on Eclipse, hit Ctrl + Shift + F to auto-format, but if you're on IntellJ Idea or Netbeans or similar, then I have no idea .-.
     
    • Agree Agree x 1
  4. So it would be this:
    Code (Text):
    package nl.sandor.cooldown;
    import java.util.ArrayList;
    import java.util.concurrent.Delayed;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;

    public class listerner implements Listener {
        @EventHandler(priority = EventPriority.HIGH)
        public void onPlayerInteract(PlayerInteractEvent event) {
            if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR)
                if ((event.getItem().getItemMeta().getLore().contains(ChatColor.MAGIC + "$"))) {
                    if ((event.getItem().getItemMeta().getDisplayName().equals(ChatColor.RED + "Empire Wand"))) {
                        ArrayList<String> ItemLore = new ArrayList<String>();
                        ArrayList<String> ItemLore2 = new ArrayList<String>();
                        ItemLore.add(ChatColor.MAGIC + "c");
                        ItemLore2.add(ChatColor.MAGIC + "$");
                        event.getItem().getItemMeta().setLore(ItemLore);
                        Bukkit.getScheduler().runTaskLater(Main, () -> event.getItem().getItemMeta().setLore(ItemLore2),
                                60);
                    }
                }
        }
    }
     
    My eclipse gives an error at line 25:
    Code (Text):
    Bukkit.getScheduler().runTaskLater(Main, () -> event.getItem().getItemMeta().setLore(ItemLore2),
     
  5. You need an instance of your Main class there.
    One way to do this:
    Code (Text):
    listerner (Main main) { //This is a constructor. You also kinda misspelled "Listener".
        this.main = main;
    }

    private Main main;
    In the Main class: "getServer ().getPluginManager ().registerEvents (new listerner (this), this);"
    And then you change "Bukkit.getScheduler().runTaskLater(Main, ..." to "Bukkit.getScheduler().runTaskLater(main, ...".
     
  6. Ehm, the lore i am trying to change in this lines:
    Code (Text):
                        ArrayList<String> ItemLore = new ArrayList<String>();
                        ItemLore.add(ChatColor.GREEN + "c");
                        event.getItem().getItemMeta().setLore(ItemLore);
    isn't working? I am not getting any errors, i also typed this code after the lore code:
    Code (Text):
    Bukkit.broadcastMessage("Lore changed");
    And that got executed
     
  7. Save the ItemMeta into a variable, edit it and then set the itemstack's itemmeta using the setItemMeta method.
     
    • Useful Useful x 1
  8. Now, yeah, that's not how ItemMeta works unfortunately.

    Save the ItemMeta of the ItemStack to a field, like this:
    Code (Java):
    ItemMeta meta = yourItem.getItemMeta();
    Then, do all the required changes to the meta you want.
    When that's done, set the ItemStack's ItemMeta to the edited one as follows:
    Code (Text):
    yourItem.setItemMeta(meta);
    and you'll be good to go.

    EDIT: Trigary ninja'd me
     
    • Useful Useful x 1
  9. I'd be wary of doing this at all - not sure quite what your goal is here, but if the player moves the item the ItemStack object will no longer be valid for that item, and therefore setting the lore won't do anything. If it's to do with adding a cooldown to the item, use the chat, or if you can spend the time to figure it out properly - the action bar.
     
  10. I am trying to add a cooldown to another plugin (This plugin: http://www.mediafire.com/file/jmyfon3o7xlnnpd/KingdomWands-6.0.jar you can't download it anymore) that plugin has a magic wand in it and that magic wand only works when it has the lore &k$ so what i am trying to do is changing the lore for like 3 seconds to something else so the magic wands stops working (Cooldown) and after 3 seconds change it back to its old state. But now every thing is working the magic wand plugin is generating errors:
    Code (Text):
    [13:45:04 ERROR]: Could not pass event PlayerInteractEvent to KingdomWands v6.0
    org.bukkit.event.EventException
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:228) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:195) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:191) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:717) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace.a(PacketPlayInBlockPlace.java:52) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace.a(PacketPlayInBlockPlace.java:1) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_131]
            at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_131]
            at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:715) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
    Caused by: java.lang.NullPointerException
            at kingdom.wands.database.UserDatabase.hasBoundSpells(UserDatabase.java:131) ~[?:?]
            at kingdom.wands.listeners.InteractListener.onInteract(InteractListener.java:53) ~[?:?]
            at sun.reflect.GeneratedMethodAccessor55.invoke(Unknown Source) ~[?:?]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
            at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_131]
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot-1.8.8.jar:git-Spigot-21fe707-e1ebe52]
            ... 18 more
    This is probably because i touched the ItemMeta right? Is there another way how i can get a sort off cooldown for that plugin?
    My code now:
    Code (Text):
    package nl.sandor.cooldown;

    import java.util.ArrayList;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.meta.ItemMeta;

    public class listerner implements Listener {
        @EventHandler(priority = EventPriority.HIGH)
        public void onPlayerInteract(PlayerInteractEvent event) {
            if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR)
                if ((event.getItem().getItemMeta().getDisplayName().equals(ChatColor.RED + "Empire Wand"))) {
                    if ((event.getItem().getItemMeta().getLore().contains(ChatColor.MAGIC + "$"))) {
                        ArrayList<String> ItemLore = new ArrayList<String>();
                        ItemMeta meta = event.getItem().getItemMeta();
                        ItemMeta meta2 = event.getItem().getItemMeta();
                        ItemLore.add(ChatColor.MAGIC + "c");
                        meta.setLore(ItemLore);
                        event.getItem().setItemMeta(meta);
                        Bukkit.getScheduler().runTaskLater(main, () -> event.getItem().setItemMeta(meta2), 60);
                    } else {
                        event.getPlayer()
                                .sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GOLD + "Wands" + ChatColor.DARK_GRAY
                                        + "]" + ChatColor.RED
                                        + "Je moet nog een paar seconden wachten voordat je je wand weer kan gebruiken!");
                    }
                }
        }

        listerner(Main main) {
            this.main = main;
        }

        private Main main;
    }
     
     
  11. From the stacktrace, seems some data is wrong perhaps

    Code (Text):

            at kingdom.wands.database.UserDatabase.hasBoundSpells(UserDatabase.java:131) ~[?:?]
     
    I'd personally decompile and check what's there unless you are sure of the cause of the problem


    Also, make your class names be capitalised properly. listener -> Listener

    Also, describe your classes purpose better. Listener -> WandCooldownListener
     
  12. The error is because i changed the lore and 3 seconds later set it back. So how would i fix that.
     
  13. Mas

    Mas

    There a lots of aspects you can improve here:
    • Classes should be named in UpperCamelCase (lilstener should be Listener, but aince that will conflict with the Bukkit listener you should call it something like InteractListener.
    • Compare enums directly with ==, no need to check if Enum#toString() equals whatever (event.getAction == Action.LEFT_CLICK_AIR and such).
    • Check if the item is null, has item meta and has a displayname before trying to retrieve the display name.
    • Fields should be named in lowerCamelCase (ItemLore -> itemLore and so on).
    • You are placing a JavaDoc comment over something which isn't a package/class/global field/method. Instead use multi-line comments with '/*' (not '/**'). In this case a single line comment '//' would do.
    Show us the error. If you're referring to the error above, find what is on line 131 of the UserDatabase class, as that is what is causing the error.
     
    • Agree Agree x 1
  14. Okay,
    Code (Text):
    package kingdom.wands.database;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import kingdom.wands.Spell;
    import kingdom.wands.Wand;
    import org.bukkit.entity.Player;

    public class UserDatabase
    {
      public Map<String, List<String>> usedWands = new HashMap();
      public Map<String, String> currentSpell = new HashMap();
      Player p;
     
      public UserDatabase(Player p)
      {
        this.p = p;
      }
     
      public Spell getCurrentSpell(Wand w)
      {
        return stringToSpell((String)this.currentSpell.get(w.getName()), w);
      }
     
      private Spell stringToSpell(String string, Wand w)
      {
        for (Spell spell : w.registeredSpells) {
          if (spell.getClass().getSimpleName().equals(string)) {
            return spell;
          }
        }
        return null;
      }
     
      public Spell getNextSpell(Wand w)
      {
        if (((List)this.usedWands.get(w.getName())).size() == 1) {
          return stringToSpell((String)((List)this.usedWands.get(w.getName())).get(0), w);
        }
        if (isLastForward(w, stringToSpell((String)this.currentSpell.get(w.getName()), w)))
        {
          Spell spell = stringToSpell((String)((List)this.usedWands.get(w.getName())).get(0), w);
          this.currentSpell.put(w.getName(), spell.getClass().getSimpleName());
          return spell;
        }
        int nextSpellNumber = ((List)this.usedWands.get(w.getName())).indexOf(this.currentSpell.get(w.getName())) + 1;
        Spell nextSpell = stringToSpell((String)((List)this.usedWands.get(w.getName())).get(nextSpellNumber), w);
        this.currentSpell.put(w.getName(), nextSpell.getClass().getSimpleName());
        return nextSpell;
      }
     
      public boolean isLastForward(Wand w, Spell spell)
      {
        int currentNumber = ((List)this.usedWands.get(w.getName())).indexOf(spell.getClass().getSimpleName());
        int nextNumber = currentNumber + 1;
        try
        {
          ((List)this.usedWands.get(w.getName())).get(nextNumber);
          return false;
        }
        catch (IndexOutOfBoundsException localIndexOutOfBoundsException) {}
        return true;
      }
     
      public Spell getPreviousSpell(Wand w)
      {
        if (((List)this.usedWands.get(w.getName())).size() == 1) {
          return stringToSpell((String)((List)this.usedWands.get(w.getName())).get(0), w);
        }
        if (isLastBackward(w, stringToSpell((String)this.currentSpell.get(w.getName()), w)))
        {
          Spell spell = stringToSpell((String)((List)this.usedWands.get(w.getName())).get(((List)this.usedWands.get(w.getName())).size() - 1), w);
          this.currentSpell.put(w.getName(), spell.getClass().getSimpleName());
          return spell;
        }
        int nextSpellNumber = ((List)this.usedWands.get(w.getName())).indexOf(this.currentSpell.get(w.getName())) - 1;
        Spell nextSpell = stringToSpell((String)((List)this.usedWands.get(w.getName())).get(nextSpellNumber), w);
        this.currentSpell.put(w.getName(), nextSpell.getClass().getSimpleName());
        return nextSpell;
      }
     
      public boolean isLastBackward(Wand w, Spell spell)
      {
        int currentNumber = ((List)this.usedWands.get(w.getName())).indexOf(spell.getClass().getSimpleName());
        int nextNumber = currentNumber - 1;
        try
        {
          ((List)this.usedWands.get(w.getName())).get(nextNumber);
          return false;
        }
        catch (IndexOutOfBoundsException localIndexOutOfBoundsException) {}
        return true;
      }
     
      public void unbindSpell(Wand w, Spell spell)
      {
        if (((List)this.usedWands.get(w.getName())).contains(spell.getClass().getSimpleName()))
        {
          List<String> spells = (List)this.usedWands.get(w.getName());
          spells.remove(spell.getClass().getSimpleName());
          this.usedWands.put(w.getName(), spells);
          if (((List)this.usedWands.get(w.getName())).isEmpty()) {
            this.usedWands.remove(w.getName());
          }
        }
        if (this.currentSpell.containsKey(w.getName())) {
          this.currentSpell.remove(w.getName());
        }
      }
     
      public void bindSpell(Wand w, Spell spell)
      {
        if (this.usedWands.containsKey(w.getName()))
        {
          List<String> spellList = (List)this.usedWands.get(w.getName());
          spellList.add(spell.getClass().getSimpleName());
          this.usedWands.put(w.getName(), spellList);
        }
        else
        {
          List<String> spellList = new ArrayList();
          spellList.add(spell.getClass().getSimpleName());
          this.usedWands.put(w.getName(), spellList);
        }
      }
     
      public boolean hasBoundSpells(Wand w)
      {
        if (this.currentSpell.containsKey(w.getName())) {
          return true;
        }
        if (this.usedWands.containsKey(w.getName()))
        {
          this.currentSpell.put(w.getName(), (String)((List)this.usedWands.get(w.getName())).get(0));
          return true;
        }
        return false;
      }
     
      public boolean hasBound(Wand w, Spell spell)
      {
        if (getBoundSpells(w).contains(spell.getClass().getSimpleName())) {
          return true;
        }
        return false;
      }
     
      public List<Spell> getBoundSpells(Wand w)
      {
        List<Spell> boundSpells = new ArrayList();
        for (String searchSpell : (List)this.usedWands.get(w.getName()))
        {
          Spell spel = stringToSpell(searchSpell, w);
          boundSpells.add(spel);
        }
        return boundSpells;
      }
     
      public Player getPlayer()
      {
        return this.p;
      }
     
      public String getPlayerName()
      {
        return this.p.getName();
      }
    }
     
    This line caused the error:
    Code (Text):
        if (this.currentSpell.containsKey(w.getName())) {
     
  15. Mas

    Mas

    'w' is null.