Here is a method I use for easier debugging

Discussion in 'Resources' started by TheBeefiest, Jan 19, 2011.

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

    TheBeefiest

    I haven't found a way to easily debug a plugin yet, so here is what I came up with, which is much easier than creating test commands and logging to the server window:

    The program is called Beanshell, its an interactive interpreter type shell (much like python) for java.
    http://www.beanshell.org/


    1. Download the jar for Beanshell.
    2. Include the Beanshell jar into your plugin project.
    3. Code:
      import bsh.Interpreter;
    4. In your JavaPlugin, create a variable:
      Code:
       public Interpreter beanshell;
    5. Create a function that will be used during your development:
    6. Code:
      public void EnableDebug(){
                     //enables the beanshell remote interpreter
                 beanshell = new Interpreter();
                 try {
                     beanshell.set( "plugin", this );  // Provide a reference to your app
                     beanshell.set( "portnum", 1234 );
                     beanshell.eval("setAccessibility(true)"); // turn off access restrictions
                     beanshell.eval("server(portnum)");
                 }
                 catch (Exception e){
                     log("Beanshell initialization failure");
                 }
         
             }
    7. Run this function in your onEnable() to debug, MAKE SURE TO REMOVE FOR RELEASE as that would be a major security flaw. (Server admins, beware of the messages
      • Httpd started on port: 1234
      • Sessiond started on port: 1235
      • These indicate that a developer left the beanshell included with a plugin.
    8. Build your project and install your JAR file into the plugin directory. Start the server.
    9. Use PUTTY or telnet to log into the port you specified +1 (1235 in this case)
    10. This shell is interactive! you can type things like
      Code:
      print(plugin.getServer().getOnlinePlayers());
      to print a list of online players. Or more usefully you can test all your plugin functions
     
  2. Offline

    thegleek

    OMG this does make debugging so much cooler, some examples of some testing for other plugin devs out there:
    Code:
    bsh % print(plugin.getVersion());
    [NowPlaying]: v1.2 (Bruderschaft)
    
    bsh % print(plugin.playerListener.sMaxString);
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    bsh % print(plugin.playerListener.ParseString("","Lorem ipsum dolor sit amet, consectetur " +
    "adipiscing elit. " +
    "Nunc mollis turpis eu tortor pharetra fermentum. " +
    "Donec porttitor condimentum ligula, eu adipiscing " +
    "dui posuere a.",org.bukkit.ChatColor.AQUA));
    [§bLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ,
    §b§bmollis turpis eu tortor pharetra fermentum. Donec ,
    §bporttitor condimentum ligula, eu adipiscing dui posuere a.]
    
    bsh % print(plugin.watching[0]);
    apikey
    
    bsh % print(plugin.Watch.getApiKey(plugin.watching[0]));
    b25b959554ed76058ac220b7b2e0a026
    
    bsh % print(plugin.playerListener.getRecentTrack("YOUR_LASTFM_API_KEY_GOES_HERE","thegleek","deadmau5"));
    []
    
    bsh % print(plugin.playerListener.getRecentTrack("b25b959554ed76058ac220b7b2e0a026","thegleek","thegleek"));
    [§3thegleek§9 is currently listening to: §9Rapper's Ball (feat. , §9Too Short - E-40 ]
    
    bsh % print(plugin.playerListener.aliasList.getSize());
    1
    
    bsh % print(plugin.playerListener.aliasList.lastfmList);
    {thegleek=deadmau5}
    
    bsh % print(plugin.playerListener.aliasList.lastfmList.containsKey("thegleek"));
    true
    bsh % print(plugin.playerListener.aliasList.lastfmList.containsKey("nonexistantplayer"));
    false
    
    bsh % print(plugin.playerListener.findValueInStack("deadmau5", plugin.playerListener.aliasList.lastfmList));
    thegleek
    bsh % print(plugin.playerListener.findValueInStack("nonexistantalias",
    plugin.playerListener.aliasList.lastfmList));
    null
    Note: The API key you see above is a public key used for testing purposes and freely available from http://www.last.fm/api/show?service=278

    Not to over-do it or bore anyone with an overload of details, but this is pretty cool how you can debug "live"...

    Code:
    bsh % print(plugin.playerListener.plugin.getServer().getName());
    Craftbukkit
    
    bsh % print(plugin.playerListener.plugin.getServer().getVersion());
    1.2_01
    
    bsh % print(plugin.getDescription().getName());
    NowPlaying
    
    bsh % print(plugin.getDescription().getVersion());
    1.2
    
    bsh % print(plugin.getDescription().getMain());
    com.bukkit.thegleek.NowPlaying.NowPlaying
    
    bsh % print(plugin.playerListener.plugin.getServer().getOnlinePlayers());
    org.bukkit.entity.Player []: {
    CraftPlayer{name=thegleek},
    }
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek"));
    CraftPlayer{name=thegleek}
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("deadmau5"));
    null
    
    bsh % print(plugin.playerListener.plugin.getServer().matchPlayer("thegleek"));
    [CraftPlayer{name=thegleek}]
    
    bsh % print(plugin.playerListener.plugin.getServer().matchPlayer("deadmau5"));
    []
    
    bsh % print(plugin.playerListener.plugin.getServer().getTime());
    123670617
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getAddress());
    /192.168.0.2:25820
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getEntityId());
    1667
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getHealth());
    20
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").isOnline());
    true
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getLocation());
    Location{world=CraftWorldx=-385.76528108306707y=76.0z=171.6591574988363pitch=13.650383yaw=1029.3087}
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getLocation().y);
    76.0
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getVehicle());
    null
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getWorld());
    CraftWorld
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getLocation().world);
    CraftWorld
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getItemInHand());
    ItemStack{STICK x 1}
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getInventory().getContents());
    org.bukkit.craftbukkit.inventory.CraftItemStack []: {
    ItemStack{STICK x 1},
    ItemStack{TORCH x 64},
    ItemStack{ARROW x 1},
    ItemStack{GRASS x 14},
    ItemStack{DIRT x 2},
    ItemStack{AIR x 0},
    ItemStack{GLASS x 12},
    ItemStack{COBBLESTONE x 58},
    ItemStack{STONE x 63},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{AIR x 0},
    ItemStack{SAND x 58},
    ItemStack{COBBLESTONE x 39},
    ItemStack{STONE x 10},
    }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 6, 2016
  3. Offline

    CompuIves

    Any screenies?
     
  4. Offline

    thegleek

    Didn't think it was needed, but I'll give you 2 examples (with coinciding code):

    Code:
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getDisplayName());
    thegleek
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getName());
    thegleek
    
    bsh % plugin.playerListener.plugin.getServer().getPlayer("thegleek").setDisplayName("deadmau5");
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getName());
    thegleek
    
    bsh % print(plugin.playerListener.plugin.getServer().getPlayer("thegleek").getDisplayName());
    deadmau5
    [​IMG]

    Code:
    bsh % plugin.playerListener.plugin.getServer().broadcastMessage("HELLO WORLD!");
    
    bsh %  plugin.playerListener.plugin.getServer().broadcastMessage(org.bukkit.ChatColor.AQUA + "HELLO WORLD!");
    [​IMG]
     
  5. Offline

    Afforess

    You can enable real time debugging with eclipse, use breakpoints, step through code, etc fairly easily. It's probably more useful than this. You need a custom startup bat file, and to set up eclipse though.
     
  6. Offline

    thegleek

    Ok, I'm game...copy/paste the startup.bat in here... and provide instructions for the eclipse setup... otherwise, why mention it?
     
  7. I think both ways have their uses, here is eclipse:

    java -Xms1024M -Xmx1024M -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y -jar craftbukkit.jar nogui

    This will show something like listening on port 8787

    Mark your breakpoints.

    In Eclipse Run > Debug configurations > Remote java applicaiton > push new icon

    Select project

    Connection properties - Host: localhost Port:8787 (sockect address in the bat)
    Apply
    Debug

    After first debug the configuration will be in your debug history Run > Debug history (or the little bug icon)
    Crafbukkit will then launch in the previous console window
     
  8. Offline

    TheBeefiest

    Yes the biggest problem with this is the lack of auto-completion when typing in functions, you do have to get capitalization perfect as well i think... But being live is a different kind of useful from ementalos method! Both very very important to developers.
     
  9. Offline

    JoeMaximum

    NICE !!
    Thanks for the eclipse setup for remote debug, this look SO MUCH USEFULL :D

    Thanks again !
     
  10. Offline

    MrTurek

    I seem to not be able to use this process. I'm relatively new to plugins for Bukkit... I'm getting a bunch of errors like:
     
  11. Offline

    TheBeefiest

    Mrturek, do you know how to package dependancies together into your jar? Here is a link on how to do it for netbeans: http://java.sun.com/developer/technicalArticles/java_warehouse/single_jar/

    Also you need to make sure your IDE sees the beanshell jar on your classpath, but you should know how to do that since you are using bukkit already.

    Also after you do include the jar, you need to import it as well:
    import bsh.Interpreter;
     
  12. Offline

    EvilSeph

    You could just hook a debug console to the server and use your IDE's debug tools.
     
  13. Offline

    MrTurek

    I've figured it out, but thanks for the tip... if only I figured out sooner....
     
  14. Offline

    SycoPrime

    Neat.
    Now I gotta figure out how to do that. Even neater :)
     
  15. Offline

    kneeven

    I'll add howto attach the debugger in Netbeans in my tutorial TY for all the cool info.
     
  16. Offline

    TheBeefiest

    This sounds interesting, is it different than what ementalo mentioned? If your method is truly interactive and can call any functions you want please post instructions, as getting rid of the beanshell dependancy would be simpler.
     
  17. Offline

    matejdro

    Wow you guys are advanced. I'm using getServer().broadcastMessage(message) to send me debug messages [​IMG]

    I will check out this live debugging with eclipse.
     
  18. Offline

    nidefawl

    this is the most awesome thing I found in a good while :)

    thx for posting this!
     
  19. Offline

    deltahat

  20. Offline

    Magik

    I was using eclipse's built-in debugger to execute the jar and that was working fine up until the console overhaul. After that, the console window in eclipse wouldn't correctly pass keyboard input to bukkit.

    But with the remote debugging ementalo mentioned, that's the perfect ticket! I did not know you could set up java to allow a remote debugger to connect!

    Thanks for the tips, I've been looking for something like this to be able to correctly debug console commands ever since the console overhaul
     
  21. Offline

    p000ison

    very very old thread, but super cool :p
     
Thread Status:
Not open for further replies.

Share This Page