Solved [Help] checking ItemStack in inventory

Discussion in 'Plugin Development' started by DeluXeNationMC, Jun 15, 2014.

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

    Ice3ider4

    DeluXeNationMC Okay I found the problem:
    You're checking whether the player has an arrow of the given type in his inventory as soon as the arrow hits the other player. So you check it after you shot the arrow but the arrow isn't in the inventory anymore ^^
    To fix this you have to check if the arrow is a fire arrow. Maybe this helps you it's a nice way to identifiy the arrow "type": https://forums.bukkit.org/threads/tagging-projectiles.121797/
     
  2. Offline

    DeluXeNationMC

    https://forums.bukkit.org/threads/tagging-projectiles.121797/ I am sorry but I don't understand this at all, there must be another way..

    Bump

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

    fireblast709

  4. Offline

    DeluXeNationMC

    I am not "Running away" I said I don't understand and that there must be another way to do this.
    Thanks for the link. I am trying to figure out how to implement this into my code.
    EDIT: I have no idea how to implement this.
     
  5. Offline

    RingOfStorms

    Arrow a = /..spawn arrow../
    a.setMetadata("fire_arrow", new FixedMetadataValue(plugin, null));

    (You can also change null to whatever object you want and pull it out later, aka the shooter's team or something useful)

    When the arrow hits, use
    if(a.hasMetadata("fire_arrow"))
    //do Stuff
     
  6. Offline

    DeluXeNationMC

    fireblast709 Can you please show me some example code because I really don't know :(
     
  7. Offline

    GeorgeeeHD

    DeluXeNationMC what that post about meta data means is you are basically adding invisible data to users to an entity, in this case the arrow. Do what I said before and add:

    event.getProjectile().setMetadata("specialArrow", new FixedMetadataValue(this, "fireArrow"));

    In your event, the damager is the arrow so you can check if it has meta data of what we did above "fireArrow" by doing:

    Arrow a = (Arrow) event.getDamager();

    if(a.hasMetadata("specialArrow")) {
    if(a.getMetadata("specialArrow").equals("fireArrow")) {
    //Entity was damaged by your special fire arrow.
    }
    }

    its kind of like a hashmap for your arrow, if you know what those are and know how to use them then just imagine it like that
     
  8. Offline

    DeluXeNationMC

    Thanks so much for this example code!
    Code:java
    1. @EventHandler
    2. public void onPlayerDamage10(EntityShootBowEvent event){
    3.  
    4. event.getProjectile().setMetadata("specialArrow", new FixedMetadataValue(this, "fireArrow"));
    5. Arrow arrow = (Arrow)event.getDamager();
    6.  
    7. if(event.getEntity() instanceof Player){
    8.  
    9. }
    10. }
    11. }

    GeorgeeeHD "Arrow arrow = (Arrow)event.getDamager();" I'm pretty sure there isn't a event.getDamager(); in this event
    EDIT: Shouldn't that be: event.getProjectile(); ?
     
  9. Offline

    GeorgeeeHD

    DeluXeNationMC yeah, do this tho

    Code:java
    1. @EventHandler
    2. public void onPlayerDamage10(EntityShootBowEvent event){
    3.  
    4. if(event.getEntity() instanceof Player){
    5. Player p = (Player) event.getEntity();
    6. //Check if they have special arrow in p.getInventory(); {
    7. event.getProjectile().setMetadata("specialArrow", new FixedMetadataValue(this, "fireArrow"));
    8. Arrow arrow = (Arrow)event.getDamager();
    9. //}
    10. }
    11. }
    12. }
     
    Ice3ider4 likes this.
  10. Offline

    DeluXeNationMC

    GeorgeeeHD
    I still get a red underline under event.getDamager();
    Code:java
    1. @EventHandler
    2. public void onPlayerDamage10(EntityShootBowEvent event){
    3. ItemStack itemFireArrow = new ItemStack(Material.ARROW, 1);
    4. ItemMeta metaFireArrow = itemFireArrow.getItemMeta();
    5. metaFireArrow.setDisplayName(ChatColor.WHITE + "Fire Arrow");
    6. itemFireArrow.setItemMeta(metaFireArrow);
    7.  
    8. if(event.getEntity() instanceof Player){
    9. Player player = (Player) event.getEntity();
    10. if(player.getInventory().contains(itemFireArrow)){
    11. event.getProjectile().setMetadata("specialArrow", new FixedMetadataValue(this, "fireArrow"));
    12. Arrow arrow = (Arrow)event.getDamager(); //I dont understand how this could ever be event.getDamager();
    13. if(arrow.hasMetadata("specialArrow")){
    14. if(arrow.getMetadata("specialArrow").equals("fireArrow")){
    15. Player victim = (Player)event.getEntity();
    16.  
    17. victim.sendMessage(ChatColor.GOLD + "Works");
    18. }
    19. }
    20. }
    21. }
    22. }
    23. }
     
  11. Offline

    GeorgeeeHD

    DeluXeNationMC you do it in two separate events, do that applying of the metadata in the EntityShootBow and then line 12-19 in an EntityDamageByEntityEvent also checking if the damager instanceof Arrow
     
  12. Offline

    DeluXeNationMC

    Code:java
    1. @EventHandler
    2. public void onBowShoot1(EntityShootBowEvent event){
    3. ItemStack itemFireArrow = new ItemStack(Material.ARROW, 1);
    4. ItemMeta metaFireArrow = itemFireArrow.getItemMeta();
    5. metaFireArrow.setDisplayName(ChatColor.WHITE + "Fire Arrow");
    6. itemFireArrow.setItemMeta(metaFireArrow);
    7.  
    8. if(event.getEntity() instanceof Player){
    9. Player player = (Player) event.getEntity();
    10. if(player.getInventory().contains(itemFireArrow)){
    11. event.getProjectile().setMetadata("specialArrow", new FixedMetadataValue(main, "fireArrow"));
    12. }
    13. }
    14. }
    15. @SuppressWarnings("deprecation")
    16. @EventHandler
    17. public void onPlayerDamage3(EntityDamageByEntityEvent event){
    18. if(event.getDamager() instanceof Arrow){
    19. Arrow arrow = (Arrow)event.getDamager();
    20. if(arrow.getShooter() instanceof Player){
    21. Player attacker = (Player)arrow.getShooter();
    22. if(arrow.hasMetadata("specialArrow")){
    23. if(arrow.getMetadata("specialArrow").equals("fireArrow")){
    24.  
    25. Player victim = (Player)event.getEntity();
    26. victim.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 100, 1));
    27. }
    28. }
    29. }
    30. }
    31. }
    32. }

    GeorgeeeHD Can you see what i'm doing wrong? :(
     
  13. Offline

    DeluXeNationMC

    AdamQpzm ?

    Bump

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

    xTigerRebornx

    DeluXeNationMC
    Code:
    if(arrow.getMetadata("specialArrow").equals("fireArrow")){
    Metadatable#getMetadata() returns a List<MetadataValue>, which will (almost) never equal a String.
    You have to get the MetadataValue from the List, then check if it is then your String (probably using asString())
     
  15. Offline

    DeluXeNationMC

    xTigerRebornx Thanks for the reply! I have no idea how to do this, could you please point me in the right direction?
     
  16. Offline

    xTigerRebornx

    DeluXeNationMC Loop through that List, then look at MetadataValue and its methods, and find out which one will give you a String that you can use to check
     
  17. Offline

    DeluXeNationMC

    xTigerRebornx if(arrow.getMetadata("specialArrow").toString().contains("fireArrow")){ I thought I had it but this doesn't work. :(
     
  18. Offline

    xize

    DeluXeNationMC

    hmm what about checking the ItemStack the player has in hand?
    since it looks you are checking when the damage is caused on the player you still can check on the ItemStack the player has in hand with p.getItemInHand().

    now to verify your stack is that kind of custom/effect bow I recommend a few things:

    1. the lazy way you could do a check if the item has ItemMeta then as follows use equals to check if that ItemMeta matches that means all the lores and displaynames have to match its a whole different than using == because that only checks the type not the contents of that ItemStack object, you could do this easily by using a pre made ItemStack todo the equals check against to.

    2. just use a String and strip the colors if that ItemStack has a name and compair the ItemStack name with that string.
     
  19. Offline

    DeluXeNationMC

    xize I already know how to do that, I want to check an ItemStack in the players inventory.
     
  20. Offline

    xize

    DeluXeNationMC

    in that case I probably would use .containsAtleast(ItemStack yourpremadebow, int miniumAmount)
     
  21. Offline

    xTigerRebornx

    DeluXeNationMC Like I've made clear in my previous posts, the getMetadata() method returns a List, meaning more then one thing can be present. Since there can be more then one thing, you have to loop over that list returned, and then you will have a MetadataValue. This MetadataValue has methods, look at what methods it has, there is one that gives you the value as a String.
     
    Mattkx9 likes this.
  22. Offline

    Mattkx9

    This should be a lot simpler than you're making it...
     
  23. Offline

    RingOfStorms

    You can do exactly what I said. For his needs he can set the metadata to null, and just check if it has the metadata fire_arrow. No need to even use the metadata in this case.
     
    AdamQpzm likes this.
  24. Offline

    DeluXeNationMC

    Extremelyd1 Ice3ider4 AdamQpzm GeorgeeeHD fireblast709 RingOfStorms xTigerRebornx Mattkx9 Thank you all! What I have learnt better: Checking before casting, MetaData (Which I now find really useful and use alot). Again thanks to everyone for learning me something new :) I won't let you guys down.
    I have one question though with: if(arrow.hasMetadata("fire_arrow")); why not a braket at the end (Since it is an if statement), I have tried this and then the code doesn't work but a ; it works fine.
     
  25. Offline

    fireblast709

    DeluXeNationMC a ; would render it useless lol. It is generally used accidently, thus creating a bug.
     
  26. Offline

    DeluXeNationMC

    fireblast709 Unfortunately when I shoot myself with a normal arrow it also sets me on fire:
    Code:java
    1. //Fire Arrow
    2. @EventHandler
    3. public void onBowShoot1(EntityShootBowEvent event){
    4. ItemStack itemFireArrow = new ItemStack(Material.ARROW, 1);
    5. ItemMeta metaFireArrow = itemFireArrow.getItemMeta();
    6. metaFireArrow.setDisplayName(ChatColor.WHITE + "Fire Arrow");
    7. itemFireArrow.setItemMeta(metaFireArrow);
    8.  
    9. if(event.getEntity() instanceof Player){
    10. Player player = (Player) event.getEntity();
    11. if(player.getInventory().contains(itemFireArrow)){
    12. Arrow arrow = (Arrow) event.getProjectile();
    13. arrow.setMetadata("fire_Arrow", new FixedMetadataValue(main, null));
    14. }
    15. }
    16. }
    17. @EventHandler
    18. public void onPlayerDamage3(EntityDamageByEntityEvent event){
    19. if(event.getDamager() instanceof Arrow){
    20. Arrow arrow = (Arrow)event.getDamager();
    21. if(arrow.getShooter() instanceof Player){
    22. Player attacker = (Player)arrow.getShooter();
    23. if(arrow.hasMetadata("fire_Arrow"));
    24. Player victim = (Player)event.getEntity();
    25. victim.setFireTicks(100);
    26. }
    27. }
    28. }
    29. }

    EDIT: When I change the ; with a braket it doesn't set me on fire.
     
  27. Offline

    FabeGabeMC

    Try creating a HashMap<String, Arrow> saving the player's name and the arrow.
    First of all, create the hashmap. In your onDisable() make sure you clear it.
    Then, check for the ShootBowEvent and check if the entity shooter is an instance of a player, then check if the arrow's name is "Fire Arrow".
    If it coincides (or is equal to the arrow you created (ItemStack)), put the arrow in the HashMap, with the key of the player's name: p.getName();.
    After this, check for EntityDamageByEntityEvent and check if the entity damager is an instance of an arrow.
    Then, copy this code (just in case) after the instanceof.
    http://pastebin.com/tjLMXpTi
    After that, check if the entity damager (arrow)'s shooter is a Player & if the player's name's value in the HashMap is the arrow.
    Finally, set the fire ticks.
     
  28. Offline

    RingOfStorms

    I don't want to be terribly rude, but the code you have given as an example is really bad, messy, and version dependent. I realize you probably learned this thinking it is good code, but that is kind of the problem with these forums (people learn from bad code and then teach others with the same bad code)

    First off, you don't need a hashmap as the projectile has a getShooter function built in that you can check. I would also strongly advise never storing an entity of any type in any kind of list. It leads to memory leaks and other problems.

    Secondly, manually typing any entity that is not living is a horrible idea and has the potential to break every update. Instead you can check an instanceof LivingEntity. That will return true if the entity is an instance of a living entity. No need for the long list of manually typed entity types.
     
  29. Offline

    FabeGabeMC

  30. Offline

    fireblast709

    RingOfStorms Collections.newSetFromMap(new WeakHashMap<T, Boolean>()); solves your memory leak issue
     
Thread Status:
Not open for further replies.

Share This Page