Solved Little bast... erm Hashmap issue

Discussion in 'Plugin Development' started by Luke_Lax, Dec 11, 2013.

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

    Wingzzz

    Luke_Lax
    Don't worry about the terminology Luke, just take it slow and think over what you need to do.

    I recommend taking the time to understand what the BukkitRunnable is capable of (in comparison to what a normal Runnable can do etc-). Also, if you don't understand what a Runnable is for and how to use one I'd recommend experimenting with those as well- but the BukkitRunnable can provide the same functionality, although as a default implementation (albeit abstract).

    Not many people know about BukkitRunnable's unfortunately, nor do many understand the difference between itself and a Runnable. Understanding the difference and similarities is key. If you know what both of them are, and what they're both capable of, you'll be able to better make the choice in which one you wish to use.

    Edit: Prior comment scratched--
     
  2. Offline

    Sagacious_Zed Bukkit Docs

    Luke_Lax

    Invocation
    This is an example of a method invocation. The following line invokes the method runTaskLater on the object assigned to runnable. runTaskLater was passed two parameters, plugin and delay. plugin is of type JavaPlugin and delay is of type int.
    Code:
    runnable.runTaskLater(plugin, delay);
    Objects of type BukkitRunnable have several run methods defined, you can see all the methods defined for BukkitRunnable on the JavaDoc http://jd.bukkit.org/rb/apidocs/index.html?org/bukkit/scheduler/BukkitRunnable.html

    Scope
    from http://en.wikipedia.org/wiki/Scope_(computer_science)
    As an example, the parameter location is only in scope within the contractor. location is no longer in scope in the method bar.
    Code:
    public class Foo {
        
        public Foo(Location location) {
        // location is in scope
        }
        
        public bar() {
        // location is not in scope
        }
    }
    Top Level Class
    In Java Classes can be defined nested; within another class or method. They also be defined anonymously, i.e. without name. Top Level Class is one that resided within its own matching source file.

    Wingzzz Please read what I have written in this thread. BukkitRunnables should not be be scheduled with the scheduler. BukkitRunnables should be told to run with the corresponding schedule. The examples on the wiki page are different from what you have just written for this very reason.

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

    Wingzzz

    Looked over your posts, thanks a great deal! I've been overlooking such an important aspect- this will definitely help in the future :)
     
  4. Offline

    Luke_Lax

    Wingzzz Thanks for taking the time to write that! Helped explain things :) However, this still doesn't help me with the fact that I can't stop my repeating task; I can create one, execute one etc but not stop it when I want to (and they need to be individually stopped so I'd need to get the taskID). Then you also get hit by a Sagacious_Zed wiki post! :p
    Just so I know what page everyone is on: does anyone here actually know how to cancel a repeating task with it's taskID, not just "Bukkit.getScheduler().cancelTask()", actually getting the specific ID then cancelling that? The way I first went about this in the OP was, what I thought, the correct way but after being explained what I already have, I'm back at the start having no clue how to stop an individual repeating task! :p
     
  5. Offline

    Sagacious_Zed Bukkit Docs

    Luke_Lax If you are intent on scheduling a BukkitRunnable with the scheduler. You need to explore the locations being returned to you. A location is only equal if every single bit of the coordinates and yaw are equal. This property of Locations makes Locations horrible keys, because of the inexactness of floating point numbers.
     
    The_Doctor_123 likes this.
  6. Offline

    The_Doctor_123

    Sagacious_Zed
    If needed, the keys should have a yaw/pitch value of 0.0 to make things easier.
     
  7. Offline

    Wingzzz

    My apoligies. I actually mis-lead you due to my own difference in knowledge on the topic. Please review Sagacious_Zed's posts. What is being said is that you need to schedule BukkitRunnables via their own methods and not the scheduler.

    Take the code shown on the wiki for example:

    Code:java
    1. import org.bukkit.plugin.java.JavaPlugin;
    2. import org.bukkit.scheduler.BukkitRunnable;
    3.  
    4. public class ExampleSelfCancelingTask extends BukkitRunnable {
    5.  
    6. private final JavaPlugin plugin;
    7.  
    8. private int counter;
    9.  
    10. public ExampleSelfCancelingTask(JavaPlugin plugin, int counter) {
    11. this.plugin = plugin;
    12. if (counter < 1) {
    13. throw new illegalArgumentException("counter must be greater than 1");
    14. } else {
    15. this.counter = counter;
    16. }
    17. }
    18.  
    19. public void run() {
    20. // What you want to schedule goes here
    21. if (counter > 0) {
    22. plugin.getServer().broadcastMessage("Commence greeting in " + counter--);
    23. } else {
    24. plugin.getServer().broadcastMessage("Welcome to Bukkit! Remember to read the documentation!")
    25. this.cancel();
    26. }
    27. }
    28.  
    29. }



    Then to call it, you simply do:

    Code:java
    1. import org.bukkit.event.EventHandler;
    2. import org.bukkit.event.Listener;
    3. import org.bukkit.event.player.PlayerJoinEvent;
    4. import org.bukkit.plugin.java.JavaPlugin;
    5. import org.bukkit.scheduler.BukkitRunnable;
    6. import org.bukkit.scheduler.BukkitTask;
    7.  
    8. public final class ExamplePlugin extends JavaPlugin {
    9.  
    10. @Override
    11. public void onEnable() {
    12. new ExampleListener(this);
    13. }
    14. }
    15.  
    16. class ExampleListener implements Listener {
    17.  
    18. private final ExamplePlugin plugin;
    19.  
    20. public ExampleListener(ExamplePlugin plugin) {
    21. this.plugin = plugin;
    22. plugin.getServer().getPluginManager().registerEvents(this, plugin);
    23. }
    24.  
    25. @EventHandler
    26. public void onJoin(PlayerJoinEvent event) {
    27. // Create the task and schedule
    28. BukkitTask task = new ExampleSelfCancelingTask(this.plugin, 5).runTaskTimer(this.plugin, 10, 20);
    29. }
    30.  
    31. }


    Where I was going wrong is that I was scheduling my tasks via the BukkitScheduler, at that point they were no longer able to be cancelled.
     
  8. Offline

    Sagacious_Zed Bukkit Docs

    This tip is better served if directed at Luke_Lax
     
  9. Offline

    The_Doctor_123

    Luke_Lax
    Hey, you there, Sagacious_Zed would like me to tell you..
     
  10. Offline

    Luke_Lax

    But every time, the yaw and pitch are always 0, but the coords are not the same except, it's the same block? I feel like I'm in that film, 1408 D:
     
  11. Offline

    Luke_Lax

    The_Doctor_123
    If the Location is a horrible key for the value, what else could I use, as it must be unique? :)
     
  12. Offline

    The_Doctor_123

    Luke_Lax
    It's not horrible as long as they contain the same values..
     
  13. Offline

    Sagacious_Zed Bukkit Docs

    I maintained that Locations are horrible because their equality relies on the intricacies of floating point operations.
     
  14. Offline

    The_Doctor_123

    Sagacious_Zed
    I see. Although, sometimes you can just bite the bullet and take the inefficient route, as long as the project is for yourself.
     
  15. Offline

    Wingzzz

    Where's the fun in that then?
     
  16. Offline

    Luke_Lax

    The_Doctor_123 Wingzzz Sagacious_Zed
    Yeah this project is for my own server, it's a lot more stressful than it needs to be. I'm thinking I may just have to resort to putting the location and taksID in a file and have someone type out a command to stop it since it's impossible to get the key from the BlockBreakEvent, although that's really inefficient D:
     
  17. Offline

    Luke_Lax

    @The_Doctor_123 @Wingzzz @Sagacious_Zed
    I'm sorry to bring this back up but I really need to find a solution :( I can't use the blocks location, is it possible to set block data with placed blocks? Maybe I can set it's data to the taskID?
     
  18. Offline

    NathanWolf

    Do you need it to be persistent? Otherwise I think there is a block metadata API you could use for that.

    Though honestly I think that's just a hashmap of blocks under the hood, which begs the question why it's not just working for you in the first place.

    I have to admit I kind of lost track of this thread when it veered off into scheduler stuff. Was the issue that the coordinates in the events weren't matching up to each other? That seems pretty crazy.

    If you are having floating point issues (Location actually does a raw binary compare of the float data, but maybe something is off), you could make your own version of it with int coordinates, maybe call it BlockLocation. You could start with the Location source code to get an idea of the equality and hashCode methods you need to implement.
     
  19. Offline

    Luke_Lax

    Yeah, the issue is, is that the coordinates for the same block in the same world are different in the onPlace and onBreak method. You'd think I've done some stupid mistake like using .getX() instead of .getY() or something like that but I've literally copied and pasted this into both my place and break:
    Code:
    Location equivalent = new Location(Loc.getWorld(), Loc.getX(), Loc.getY(), Loc.getZ());
    There's no yaw, no pitch so no issue in that. The X, Y and Z values are literally are different and I don't know why :|
     
  20. Offline

    NathanWolf

    Did you try .getBlockX(), etc?
     
  21. Offline

    Luke_Lax

    Hehe, yeah, nothing makes them the same

    I was hoping; since Sag said locations are horrible, that he could tell me an alternative but he hasn't, do you know? My only other guess would be Block meta
     
  22. Offline

    NathanWolf

    Luke_Lax can you post or pastebin your full code? I'm pretty curious about this one, what you're doing seems reasonably simple and I don't know why it wouldn't work. The two blocks off thing is just weird, that can't be real behavior or tons of things would break... Right?
     
  23. Offline

    Luke_Lax


    Yeah totally agree, here's a pastebin of my current code (The variable for the Location is "Sml" rather than "Loc" - I used that to help not confuse people, but I changed them over with no issue): http://pastebin.com/CNAa8jPR
     
  24. Offline

    NathanWolf

    Cool! I'm traveling today, so i won't get to this right away, but at this point I kind of want to build it and try it out :)
     
  25. Offline

    Luke_Lax

    Feel free! I really hope we can squash this bug. In theory it should be so simple, why does it never work out that way! :p
     
  26. Offline

    NathanWolf

    Ok, well- unfortunately my findings have amounted to "works for me!" :\

    I took your code, added the necessary Plugin embellishments, and made three changes:

    http://pastebin.com/THRvcYGf

    1. Removed the y + 2 work-around
    2. Removed permission checks
    3. Changed ENDER_PORTAL_FRAME to GLOWSTONE

    That last one was mainly so I could test this out. I'm not actually sure how you're breaking the portal frame blocks :)

    But anyway, it seemed to work exactly as expected. (ok, I did make one more change, made run() spit out particles so I could see it working :p)

    So my best guess at this point is it's something to do with the ender portal frame block itself.

    Can you try just changing that material in your own plugin code to see if it magically works?
     
    Luke_Lax likes this.
  27. Offline

    Luke_Lax


    When you said "1. Removed the y + 2 work-around", I thought: huh? I don't have a workaround?

    I then looked and saw what you was referencing, although it's so make my run() action occur 2 block above the block placed... I just realised I was using the edited method as the location ... All I did was make my SnowMachine(final Location Sml) to take another Location which is unedited the whole way through and... it works!!!!!!!!!!!!!!

    Lol, thank you so much NathanWolf !!!!!
    And to all those who tried helping =D
     
  28. Offline

    NathanWolf

    Lol, well I'm glad there is no funky mystery here after all... I kept looking at your code thinking that +2 was there to make it work, I didn't expect it to be the whole problem :)

    Very glad to see this thread finally marked solved :D
     
    Luke_Lax likes this.
Thread Status:
Not open for further replies.

Share This Page