Solved Make it so a player can't pick up items after a certain amount of seconds?

Discussion in 'Plugin Development' started by darkbro100, Jul 15, 2013.

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

    darkbro100

    I want to make it so after 30 seconds, a player can't pick up iron armor. How exactly would I go about doing this?
     
  2. Offline

    xTrollxDudex

    darkbro100
    Add them to a hashset, Make a timer to remove them in thirty seconds, listen for player pickup item event, check if they are in a hashset, cancel.
     
  3. Offline

    darkbro100


    What would I put in the List for the hashset?
     
  4. Offline

    foodyling

     
  5. Offline

    xTrollxDudex

  6. Offline

    Harry5573

    ArrayList<String> cantPickup = new ArrayList<String>();

    cantPickup.add(p.getName());
    cantPickup.remove(p.getName());

    @EventHandler
    public void onJoin(PlayerJoinEvent e) {
    //Scheduled task here to do the following after 30 seconds
    cantPickup.add(e.getPlayer().getName());


    @EventHandler
    public void onPlayerPickupArmour(PlayerPickupItemEvent e) {
    if (//Get if its armour) {
    if (cantPickup.contains(e.getPlayer().getName())) {
    e.setCancelled(true);
     
  7. Offline

    xTrollxDudex

    Harry5573
    He wants people to not be able to pickup for 30 seconds, not after 30 seconds not be able to pickup items :p
    Also, use a hashset, there is a slight performance improvement because hashsets aren't ordered
     
  8. Offline

    Harry5573

    Code:
    after 30 seconds, a player can't pick up iron armor. 
    :p he does want it after
     
    xTrollxDudex likes this.
  9. Offline

    darkbro100

    After the armor piece is dropped, I want it so the player can't pick it up for 30 seconds.

    Some help would be great as I try to figure it out myself.
     
  10. Offline

    iFamasssxD

    Code:
    @EventHandler
        public void OnPlayerPickup(PlayerPickupItemEvent event){
            ItemStack item = event.getItem().getItemStack();
            Material itemType = item.getType();
            if(itemType == Material.IRON_CHESTPLATE){
                event.getItem().setPickupDelay(30 * 20);
            }
        }
    This isnt tested but should work.
     
  11. Offline

    darkbro100


    This still wasn't what I need help with. I need help with the HashSet and the Timer part.
     
  12. Offline

    flaaghara

  13. Offline

    iFamasssxD

    darkbro100 this should make it so you dont need to do that..
     
  14. Offline

    flaaghara

    iFamasssxD
    This code resets the pickup delay by 30 seconds whenever the player tries to pick up the iron armor. So in actuality, it's as if the player will never be able to pick up the armor. I'm not completely sure, but from the looks of it since that doesn't cancel the pickup event the player will be able to grab the piece of armor anyways with no delay.

    darkbro100 You'll want to stick with the HashSet and Scheduler implementation for this. If you can tell us what event/command you're trying to use to start this 30 second countdown then perhaps we can nudge you in the right direction.
     
  15. Offline

    darkbro100


    On a PlayerDropItemEvent or a PlayerDeathEvent. If they drop an iron armor piece...it then starts the timer.
     
  16. Offline

    flaaghara

    darkbro100 So do you want it that no player is able to pick up the item, or just the player who died/dropped it won't be able to?
     
  17. Offline

    darkbro100


    Whoever dropped the item....it sets a timer. After 30 seconds, that item can't be picked up.
     
  18. Offline

    flaaghara

    darkbro100 So here's what you need to do. Have 2 Event Handlers listening for a PlayerDropItemEvent or a PlayerDeathEvent. In the PlayerDropItemEvent, check the dropped item to see if it's your key item. If it is, then add the player's name from that event who dropped it to the HashSet. Then you'll have to call the method runTaskLater() from the Bukkit Scheduling API to run a task to remove that player from that HashSet 30 seconds later. PlayerDeathEvent has a method getDrops() which will return a List<ItemStack>. You have to iterate through the whole list to see if your key item is in there. If it is, again you must add the player to the HashSet. Then you would have a listener for PlayerPickupItemEvent. If the item picked up is the key item, you'd have the method check the HashSet for the player's name. If the HashSet has his name, cancel the event. If not, then you'd return and do nothing.
     
  19. Offline

    darkbro100


    Hm, okay. Thanks.

    flaaghara Does doing this deny the player who dropped it after 30 seconds? Or all the online players? Because I want it so all the online players can't pick it up after 30 seconds.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 3, 2016
  20. Offline

    flaaghara

    darkbro100
    That's what I asked you and you said:


    In the case of all players not being able to pick up the item, why don't you just despawn the item after 30 seconds?
     
  21. Offline

    darkbro100

    flaaghara So just once that item is dropped, make a scheduled task and after 30 seconds clear the item?
     
  22. Offline

    flaaghara

    darkbro100 Yes. You'll have to store a reference to that ItemStack and use remove() to delete it in 30 seconds using the scheduler.
     
  23. Offline

    darkbro100


    Here's what I got so far.

    Code:
     @EventHandler
    public void secondDrop(PlayerDropItemEvent e) {
    if (e.getItemDrop().getItemStack().getType() == Material.IRON_HELMET
    || e.getItemDrop().getItemStack().getType() == Material.IRON_CHESTPLATE
    || e.getItemDrop().getItemStack().getType() == Material.IRON_LEGGINGS
    || e.getItemDrop().getItemStack().getType() == Material.IRON_BOOTS) {
     
    Bukkit.getServer().getScheduler().runTaskTimer(this, new Runnable() {
    public void run() {
    if(number != 0) {
    number--;
    } else {
    e.getItemDrop().remove();
    }
    }
    }, 0L, 20L);
    }
    }
    
     
  24. Offline

    flaaghara

    darkbro100 Not sure what number is. Also, use the method runTaskLater(). Other than that conceptually I think you've got it down.
     
  25. Offline

    darkbro100


    Code:
    @EventHandler
    public void secondDrop(PlayerDropItemEvent e) {
    if (e.getItemDrop().getItemStack().getType() == Material.IRON_HELMET
    || e.getItemDrop().getItemStack().getType() == Material.IRON_CHESTPLATE
    || e.getItemDrop().getItemStack().getType() == Material.IRON_LEGGINGS
    || e.getItemDrop().getItemStack().getType() == Material.IRON_BOOTS) {
     
    Bukkit.getServer().getScheduler().runTaskLater(this, new Runnable() {
    public void run() {
    if(number != 0) {
    number--;
    } else {
    e.getItemDrop().remove();
    }
    }
    }, 0L);
    }
     
    }
    

    Quick question, I get an error on "e" on the line:
    Code:
    e.getItemDrop().remove();
    
     
  26. Offline

    flaaghara

    darkbro100 E must be final I presume. Add this line before the line starting with Bukkit.getServer():

    Code:java
    1. final PlayerDropItemEvent finalEvent = e;


    Then change this line
    Code:java
    1. e.getItemDrop().remove();

    to this one:
    Code:java
    1. finalEvent.getItemDrop().remove();


    "Cannot refer to a non-final variable event inside an inner class defined in a different method." This is just a quick fix we're using.
     
  27. Offline

    darkbro100

    Okay, got this all down.

    Now, whenever a player drops one of those specified items, after the presumed amount of time(30 seconds), it either crashes the player, or the item doesn't disappear. Help?

    Code:
    int number = 5;
    @EventHandler
    public void secondDrop(PlayerDropItemEvent e) {
    if (e.getItemDrop().getItemStack().getType() == Material.IRON_HELMET
    || e.getItemDrop().getItemStack().getType() == Material.IRON_CHESTPLATE
    || e.getItemDrop().getItemStack().getType() == Material.IRON_LEGGINGS
    || e.getItemDrop().getItemStack().getType() == Material.IRON_BOOTS) {
    final PlayerDropItemEvent finalEvent = e;
    Bukkit.getServer().getScheduler().runTaskLater(this, new Runnable() {
    public void run() {
    if(number != 0) {
    number--;
    } else {
    finalEvent.getItemDrop().remove();
    }
    }
    }, 0L);
    }
    }
     
  28. Offline

    flaaghara

    darkbro100 Did you look at the API for how to use the method? First off, what is this line all about?

    Code:java
    1. if(number != 0)


    I still don't know what you're accomplishing with number. Secondly, you're setting the time to be 0 ticks. Look up how to change that to your desired time.
     
  29. Offline

    darkbro100

    flaaghara Updated it

    Code:
    @EventHandler
    public void secondDrop(PlayerDropItemEvent e) {
    if (e.getItemDrop().getItemStack().getType() == Material.IRON_HELMET
    || e.getItemDrop().getItemStack().getType() == Material.IRON_CHESTPLATE
    || e.getItemDrop().getItemStack().getType() == Material.IRON_LEGGINGS
    || e.getItemDrop().getItemStack().getType() == Material.IRON_BOOTS) {
    final PlayerDropItemEvent finalEvent = e;
    Bukkit.getServer().getScheduler().runTaskLater(this, new Runnable() {
    public void run() {
     
    finalEvent.getItemDrop().remove();
    }
    }, 20 * 30L);
    }
     
    }
    

    EDIT: That code above works. Thanks!


    However, as for the PlayerDeathEvent, is this how it would go?

    Code:
    @EventHandler
    public void onPlayerDrop(PlayerDeathEvent e) {
    for(ItemStack items : e.getDrops()) {
    if(items.getType() == Material.IRON_HELMET
    || items.getType() == Material.IRON_CHESTPLATE
    || items.getType() == Material.IRON_LEGGINGS
    || items.getType() == Material.IRON_BOOTS
    || items.getType() == Material.DIAMOND_HELMET
    || items.getType() == Material.DIAMOND_CHESTPLATE
    || items.getType() == Material.DIAMOND_LEGGINGS
    || items.getType() == Material.DIAMOND_BOOTS) {
     
    final PlayerDeathEvent finalEvent = e;
    Bukkit.getServer().getScheduler().runTaskLater(this, new Runnable() {
    public void run() {
    finalEvent.getDrops().clear();
    }
    }, 20 * 30L);
    }
    }
    }
    
     
  30. Offline

    flaaghara

    darkbro100 Good to hear! In the second event handler, this line
    Code:java
    1. finalEvent.getDrops().clear();

    is clearing the list of drops for every piece of iron armor which, after the first clear, won't do much of anything. Unless I'm mistaken, I'm pretty sure you don't want to clear ALL the drops from a player's death right? In that case, all you need to do is change that line to
    Code:java
    1. finalEvent.items.remove();

    Consider changing 'items' to 'item' because in reality the for-loop is iterating through the list of the player's drops one by one (this just improves readability).
     
Thread Status:
Not open for further replies.

Share This Page