[SOLVED] PlayerInteractEvent and enderpearls

Discussion in 'Spigot Plugin Development' started by AdrianPMC, Jul 12, 2015.

  1. Code (Text):
    package me.leetzilantonis.hcfadditions;

    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    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 java.util.*;

    import static org.bukkit.Material.*;

    public class EnderPearlListener implements Listener {

        Main plugin;
        ChatMethods chat;
     
        public EnderPearlListener(Main instance) {
         
            plugin = instance;
         
        }
     
        /** playername -> last throw timestamp */
        private final Map<UUID, Long> lastThrow = new HashMap<UUID, Long>();

        // materials that allow interactions are ignored, since the enderpearl will not fire
        private final static Set<Material> interactables =
                new HashSet<>(Arrays.asList(
                    ANVIL, COMMAND, BED, BEACON, BED_BLOCK, BREWING_STAND, BURNING_FURNACE, CAKE_BLOCK, CHEST,
                    DIODE, DIODE_BLOCK_OFF, DIODE_BLOCK_ON, DISPENSER, DROPPER, ENCHANTMENT_TABLE, ENDER_CHEST, FENCE_GATE,
                    FENCE_GATE, FURNACE, HOPPER, IRON_DOOR, IRON_DOOR_BLOCK, ITEM_FRAME, LEVER,  REDSTONE_COMPARATOR,
                    REDSTONE_COMPARATOR_OFF, REDSTONE_COMPARATOR_ON, STONE_BUTTON, TRAP_DOOR, TRAPPED_CHEST,
                    WOODEN_DOOR, WOOD_BUTTON, WOOD_DOOR, WORKBENCH
                ));
     
        @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled=true)
        public void onPlayerUseEP(PlayerInteractEvent event) {
         
           
    Player p = event.getPlayer();

            Material itemInHand = p.getInventory().getItemInHand().getType();

            ItemStack item = p.getInventory().getItemInHand();

            if (event.getAction() == Action.LEFT_CLICK_AIR

                    || event.getAction() == Action.LEFT_CLICK_BLOCK

                    || itemInHand == null

                    || itemInHand != ENDER_PEARL

                    || item == null) {

                p.sendMessage("did an action!");

                return;

            }
            // ignore certain materials...
            if (event.getClickedBlock() != null && !event.getPlayer().isSneaking()) {
                Material clickedMat = event.getClickedBlock().getType();
                if (interactables.contains(clickedMat)) {
                 
                    p.sendMessage("You clicked a block...");
                    return;
                }
            }
         
            // apply cooldown to player
            long now = System.currentTimeMillis();
            if (validthrow(p, now)) {
                // allow throw, set cooldown
                    lastThrow.put(p.getUniqueId(), now);
                    p.sendMessage("allowed throw!");
            } else {
                event.setCancelled(true);
            }
        }

        /** Return remaining cooldown in seconds. */
        private double remainingCooldown(Player p, long throwTime) {
            Long lastPlayerPearl = lastThrow.get(p.getUniqueId());
            return (plugin.cooldown - (throwTime - lastPlayerPearl)) / 1000.0;
        }

        /** Check if player is allowed to throw a pearl at this moment. */
        private boolean validthrow(Player p, long throwTime) {
            p.sendMessage("start of method");
            long lastPlayerPearl = lastThrow.get(p.getUniqueId());

            // for players with cooldown, check if cooldown has passed
            if ((throwTime - lastPlayerPearl) >= plugin.cooldown) {
                p.sendMessage("You can throw an enderpearl!");
                return true;
            }

            p.sendMessage(plugin.getLangConfig().getString("enderpearlCooldown").replace("{time}", String.format("%.1f", remainingCooldown(p, throwTime))));
            return false;
        }

    }
    if you study the above code for a few minutes... everything looks in order right? no... everything fires except for when i throw an enderpearl, when i do, non of the messages pop up, the valid throw method isn't even called! please help me been staring at the code for hours i need some fresh eyes... let me repeat... i can get the first 2 if statements to work by left clicking a block or right clicking a door with an enderpearl... but nothing runs after the //apply codlin to player -.- and i don't know why

    if any more info is needed, just say... i may have forgotten something I'm half asleep now that i have been staring at this problem for so long
     
    #1 AdrianPMC, Jul 12, 2015
    Last edited: Jul 13, 2015
  2. getItemInHand() Doesn't that return null if you used an empty hand? I would check if it does. Otherwise, errorz!
    Cancelling the event on monitor, bad boy! Tsssk.

    What are you trying to accomplish with your plugin?
     
  3. if you read my code you will clearly notice that i have checked for if temInHand == null AND itemInHand != ENDER_PEARL

    im not sure what you mean by cancelling event on monitor... nor what tsssk means xD, I'm assuming you mean the event handler thing at the top that ignores canceled, please explain i would love to know what you mean :)

    i am trying to accomplish something where if you use an enderpearl, you can't use another for 5 seconds... the plugin.cooldown has been printed on startup and it is exactly what i wanted plugin.cooldown = 5000 the reason I'm adding those messages in is for developing purposes to see what code is running and what isn't, i can replicate every scenario for every piece of code to work except for

    Code (Text):
    // apply cooldown to player
            long now = System.currentTimeMillis();
            if (validthrow(p, now)) {
                // allow throw, set cooldown
                    lastThrow.put(p.getUniqueId(), now);
                    p.sendMessage("allowed throw!");
            } else {
                event.setCancelled(true);
            }
    and i have no idea why, still looking for answers and more fresh eyes will be a great help thanks :D
     
  4. Material itemInHand = p.getInventory().getItemInHand().getType();

    You should put a check to make sure the item isn't null.
    You're only checking if the material isn't null but not the item itself.
     
  5. if i click with my hand it runs that code like it knows i don't have an item in my hand... and doesn't checking if the material is null mean in turn that the item has to be null

    i have added it in just checking now if it fixes the problem :) pretty sure it won't though because I'm trying to check if the item is an enderpearl, so in theory when i right click an enderpearl the item shouldn't be null and the code should be running... but it doesn't
     
  6. Ok here try something like this.

    Check if item in hand is not null. (Not the item type, the item itself)
    Check if item in hand's type is Enderpearl (use .equals)
    Do stuff.
     
  7. Hmm, Why don't you just listen to the playerteleportevent and if the cause == enderpearl -> setCancelled. Then you don't have to deal with any inventory clickity business.
     
    • Agree Agree x 2
  8. because i don't want to have to wait for the enderpearl to land to stop it, this is a cooldown for enderpearls which means you shouldn't be able to throw them in the first place until the cool down has passed, think of it this way - it either looks good and preforms like it should with more effort, or it looks bad and doesn't feel right with less effort (i prefer the can't throw enderpearl at all, it looks neater)
     
  9. ok, everything work now... sort of, when i click a block with an enderpearl, the codlin works PERFECTLY :D but when i click the air with an enderpearl... nothing happens and i mean nothing, i get no messages saying the method started, or i did an action its like it just skips all of the code :/ is that because the event doesn't fire when you right click air?
     
  10. Check if the action is for the air too.
     
    #10 Conjurate, Jul 13, 2015
    Last edited: Jul 13, 2015
  11. figured it out, i forgot to remove the IgnoreCanceled because apparently bukkit cancels the left and right click air xD
     
  12. I don't think Bukkit does that.

    Anyway, cancelling an event on Monitor is highly discouraged.


    I made such a plugin a long time ago as well, I could simply solve this with this:

    Code (Text):
    @EventHandler
        public void onPearl(PlayerInteractEvent e) {
            if ((e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) && e.getItem() != null && e.getItem().getType() == Material.ENDER_PEARL) {
                if (Utils.canUsePearl(e.getPlayer())) {
                    Utils.setTimer(e.getPlayer());
                } else {
                    e.setCancelled(true);
                }
            }
        }

    Sorry for the spoon feeding.
     
  13. oh you see my friend i have found about 12 sources that tell me bucket does do that and when i ignore canceled it doesn't fire if you left or right click air with any time xD