I can't change the item a player is holding

Discussion in 'Plugin Development' started by MrZoraman, Jan 1, 2013.

Thread Status:
Not open for further replies.
  1. Someone asked me to make a plugin that fills up the health bar when soup is consumed. Doesn't sound too hard, so why not?

    Code:
    Code (Text):
    1. public class InstaHealSoup extends JavaPlugin implements Listener
    2. {
    3.     public static InstaHealSoup plugin;
    4.     public Logger logger;
    5.    
    6.     @Override
    7.     public void onEnable()
    8.     {
    9.         plugin = this;
    10.         logger = this.getLogger();
    11.        
    12.         getServer().getPluginManager().registerEvents(this, this);
    13.     }
    14.    
    15.     @Override
    16.     public void onDisable()
    17.     {
    18.         logger = null;
    19.         plugin = null;
    20.     }
    21.    
    22.     @EventHandler
    23.     public void onUse(PlayerInteractEvent event)
    24.     {
    25.         if(event.getAction().equals(Action.RIGHT_CLICK_AIR) || event.getAction().equals(Action.RIGHT_CLICK_BLOCK))
    26.         {
    27.             if(event.getPlayer().hasPermission("instaHealSoup.use"))
    28.             {
    29.                 if(event.getPlayer().getItemInHand().getType().equals(Material.MUSHROOM_SOUP))
    30.                 {
    31.                     event.getPlayer().setItemInHand(new ItemStack(Material.BOWL, 1));
    32.                     event.getPlayer().setHealth(20);
    33.                 }
    34.             }
    35.         }
    36.     }
    37. }
    The player's inventory is not changing, however. The item he is holding remains to be the mushroom soup. It will not change to just a bowl. I can't even remove the item in his hand, and I have tried every single trick I've found on the forums. Setting it to null, the Inventory.clear method, setting it to Material.AIR.., none of them are working. I also threw in updateInventory() method, even though it was depricated, and that didn't change my results. Any help is appreciated. Thanks!
     
  2. do something like this,
    Code (Text):
    1. @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
    2.     public void onPlayerInteractEvent(PlayerInteractEvent e){
    3.      
    4.             final int l = e.getPlayer().getFoodLevel();
    5.             final Player p = e.getPlayer();
    6.          
    7.             ItemStack i = e.getPlayer().getItemInHand();
    8.             if(i.getType().equals(Material.MUSHROOM_STEW)){
    9.                 //schedule a task to see if they have eaten the stew(maybe the time could be a little faster idk)
    10.                Bukkit.getServer().getPluginManager().getPlugin("pluginname").getServer().getScheduler().scheduleSyncDelayedTaskBukkit.getServer().getPluginManager().getPlugin("pluginname"), new Runnable(){
    11.                     public void run(){
    12.                         if(p.getFoodLevel() > l && p.getItemInHand().getType().equals(Material.BOWL)){
    13.                          
    14.                             p.setHealth(20);
    15.                     }
    16.                 },90L);
    17.             }
    18.         }
    19.     }
     
  3. This code presents the popular bug that MineZ had where you could have an item in one hand, click, then swap to another item and receive benefits of using the item even though you didn't use it. With MineZ, this was you right clicking with a water bottle, opening your inventory, and swapping it for an empty bottle to get your thirst refilled. With this, I could see people abusing it even easier by having a soup in slot 1 and a bowl in slot 2 and right clicking with slot 1 and swapping to slot 2 every time they want full health.

    Bukkit actually has an event that you can use to prevent this from happening (when eating food, but not drinking potions). Here's some code to get you started:
    Code (Text):
    1.  
    2. @EventHandler(priority = EventPriority.NORMAL)
    3. public void onFoodLevelChange(FoodLevelChangeEvent e) {
    4.     Entity ent = e.getEntity();
    5.     if (ent instanceof Player) {
    6.         Player p = (Player)ent;
    7.         ItemStack hand = p.getItemInHand();
    8.        
    9.         int pre = p.getFoodLevel();
    10.         int post = Math.min(e.getFoodLevel(), 20);
    11.        
    12.         if (post-pre > 0) {
    13.             p.sendMessage(String.format("You ate some %s and gained %d hunger.", WordUtils.capitalize(hand.getType().name().replace("_", " ").toLowerCase()), post-pre));
    14.         }
    15.     }
    16. }
    17.  
     
  4. fireblast709
    Yes the player does get healed

    Thank you for all of your help guys, but everything in the plugin works how I want it to so far. The only problem is that I can't change the item in the player's hand from a bowl of soup to an empty bowl.
     
  5. what about setting the type of the item in hand to empty bowl?
     
  6. Just like my code above, this is a way you can get what you want and not have to manually set their held item or make schedulers and is pretty much fool-proof in terms of your players being able to exploit the fact that you're not checking if they swap items around.

    It checks ItemMeta for a special item name (from the Anvil or from you setting another name using ItemMeta) but defaults to the Minecraft name for the item if an ItemMeta name doesn't exist. As a result of this, you can check the name against a string of your liking and do special things if it matches something such as cactus soup. You can even add colors to the items by using the ItemMeta, but make sure you add that to the check. :D

    Code (Text):
    1.  
    2. @EventHandler(priority = EventPriority.NORMAL)
    3. public void onFoodLevelChange(FoodLevelChangeEvent e) {
    4.     Entity ent = e.getEntity();
    5.     if (ent instanceof Player) {
    6.         Player p = (Player)ent;
    7.         ItemStack hand = p.getItemInHand();
    8.        
    9.         ItemMeta im = hand.getItemMeta();
    10.        
    11.         String itemName = im.getDisplayName();
    12.         if (itemName == null) { itemName = hand.getType().toString().toLowerCase().replace("_", " "); }
    13.        
    14.         int pre = p.getFoodLevel();
    15.         int post = Math.min(e.getFoodLevel(), 20);
    16.        
    17.         if (post-pre > 0) {
    18.             if (itemName.equalsIgnoreCase("cactus soup")) {
    19.                 p.setHealth(20);
    20.                 p.sendMessage(String.format("You ate some %s and were healed to full health.", itemName));
    21.             } else {
    22.                 p.sendMessage(String.format("You ate some %s and gained %d hunger.", itemName, post-pre));
    23.             }
    24.         }
    25.     }
    26. }
    27.  
     
  7. mhm but im afraid you missed the part in my code where i checked the food level.
    i do think of things like this you know.
     
  8. Hey, I just offered. If you don't want it, you don't have to take it.

    Anyways, good luck. :)
     
  9. wasnt me asking the question...
     
  10. Offline

    Sparta

    Don't put MATERIALNAME, 1. Just do player.setItemInHand().setType(Material.BOWL);
     
Thread Status:
Not open for further replies.

Share This Page