HashMap Help

Discussion in 'Plugin Development' started by xYourFreindx, Jun 2, 2014.

Thread Status:
Not open for further replies.
  1. Hey, I started a plugin, it was supposed to be VERY quick and easy...
    But I keep running into a problem.
    I'm trying to make it so that a player can place a hopper, and then ONLY he can break it.
    But as it turns out...
    My current setup makes it so that the player that placed it, cannot open it.​
    I only have me to test it with right now, so Idk about other players.​
    Code:java
    1. package com.gmail.xyourfreindx.protectedhoppers;
    2.  
    3.  
    4. import java.util.HashMap;
    5.  
    6. import org.bukkit.Location;
    7. import org.bukkit.Material;
    8. import org.bukkit.event.EventHandler;
    9. import org.bukkit.event.Listener;
    10. import org.bukkit.event.block.Action;
    11. import org.bukkit.event.block.BlockBreakEvent;
    12. import org.bukkit.event.block.BlockPlaceEvent;
    13. import org.bukkit.event.player.PlayerInteractEvent;
    14. import org.bukkit.plugin.PluginDescriptionFile;
    15. import org.bukkit.plugin.java.JavaPlugin;
    16.  
    17. public class ProtectedHoppers extends JavaPlugin implements Listener {
    18. public HashMap<Location, String> bl = new HashMap<Location, String>();
    19. public void onEnable()
    20. {
    21. PluginDescriptionFile pdfFile = getDescription();
    22. getServer().getPluginManager().registerEvents(this, this);
    23. getLogger().info(pdfFile.getName() + " v" + pdfFile.getVersion() + " has been enabled");
    24. }
    25. public void onDisable() {
    26. PluginDescriptionFile pdfFile = getDescription();
    27. getLogger().info(pdfFile.getName() + " v" + pdfFile.getVersion() + " has been disabled");
    28. }
    29. @EventHandler
    30. public void onBlockInteract(PlayerInteractEvent e) {
    31. if ((e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) && (e.getClickedBlock().getType().equals(Material.HOPPER))) {
    32. Location location = e.getClickedBlock().getLocation();
    33. String player = e.getPlayer().getUniqueId().toString();
    34. if (bl.get(location) != null){
    35. if (bl.get(location) != player && (!(e.getPlayer().hasPermission("ph.d")))) {
    36. e.setCancelled(true);
    37. }
    38. }
    39. }
    40. }
    41. @EventHandler
    42. public void onBlockPlace(BlockPlaceEvent e) {
    43. if (e.getBlock().getType().equals(Material.HOPPER)) {
    44. bl.put(e.getBlock().getLocation(), e.getPlayer().getUniqueId().toString());
    45. }
    46. }
    47.  
    48. @EventHandler
    49. public void onBlockBreak(BlockBreakEvent e) {
    50. if (e.getBlock().getType().equals(Material.HOPPER)) {
    51. bl.remove(e.getBlock().getLocation());
    52. }
    53. }
    54. }
    55.  

     
  2. Offline

    JeremyPark

    You need to create a getter for the hashmap. (I think) You could shortcut, and make the hashmap static, but that isn't good practice.
     
  3. JeremyPark Unfortunately, I do not believe this is the issue.
     
  4. Offline

    gabizou

    xYourFreindx
    In line 36 of your code:
    Code:java
    1.  
    2. if(bl.get(location)!= player && (!(e.getPlayer().hasPermission("ph.d")))){
    3.  

    you're doing a comparison with a String. In Java, if you want to make sure an object "equals" another object, not that it's the same instance of said object, you need to use
    Code:java
    1.  
    2. objectA.equals(objectB)
    3.  

    otherwise, you're creating a new object and checking if the object is the same instance as the String object in your hash map, which in this listener, will never equal.

    I'm not sure if that will fix the issue entirely, but I'm pretty sure that if you're doing this in many places, you'll have issues.
    To fix, rewrite that line as so:
    Code:java
    1.  
    2. if(player.equalsIgnoreCase(bl.get(location)) && (!(e.getPlayer().hasPermission("ph.d")))){
    3.  


    The reason why I use player. instead of bl.get(location). is because bl.get() may return null and you'd have an NPE, whereas player is guaranteed to be instantiated by the lines above.

    Furthermore, when putting a Location into the HashMap, I'd recommend cloning the location of the block instead of just storing the instance of the location the block has. The reason for this is that you're defensively linking a location in your own HashMap instead of linking the Location belonging to a Block which is regarded to be still in use by the GC and might have a memory leak.

    Then again, I might be completely wrong in that assumption, but for me, I defensively clone objects like this to avoid having modifications performed on that object while it's still in the HashMap or other Collection.
     
    xYourFreindx likes this.
  5. Offline

    Nateb1121


    The scope of the HashMap is the whole class, it works how OP is doing it. (Although it doesn't follow encapsulation ;)) Though getters and setters would be a good idea if you ever want to have another class that looks at that HashMap and modifies it.

    gabizou I think you're actually spot on with that as the issue. Line 35 is the big issue, since you're using ==/!= comparison it's comparing memory addresses rather than lexicographically (isn't theory fun?) and with strings a == will never be equal. Gabizou's solution should fix your issues nicely.
     
    xYourFreindx likes this.
  6. Nateb1121 gabizou Gosh darn it!
    You're completely right.
    I cannot believe I hadn't noticed that.
    That was something I was taught 15 billion times in basic java...
    Thanks so much.
     
    Nateb1121 likes this.
Thread Status:
Not open for further replies.

Share This Page