[INACTIVE][DEV] jxpl - javax.script Plugin Loader r5 [556]

Discussion in 'Inactive/Unsupported Plugins' started by angelsl, Feb 6, 2011.

  1. Offline

    angelsl

    jxpl - The javax.scripting Plugin Loader

    Version: r5

    jxpl is a plugin providing a plugin loader that loads whatever script frameworks work with javax.script, and are Invocable.

    End-user Usage: Place scripts in the scripts/ directory in the root directory (where plugins/ is). Do not place scripts in plugins/.

    Developer Usage: Example scripts are lined below. It should contain everything you need to get started. Note that Java comes with only Mozilla Rhino 1.6R2, and nothing else. Should you want to script using other languages (provided they work with ScriptEngineManager in javax.script), you will need to include the framework in your classpath yourself.

    Some available languages (and examples, if available):
    For examples, see the language list above.

    Download binary: https://github.com/downloads/angelsl/jxpl/jxpl.jar
    Git repository: https://github.com/angelsl/jxpl/

    Changelog:
    • r5
      • Fix for Issue #5 - jxpl not working too well after reloads N.B. Hacky fix. Real fix is to change 3 lines of code in Bukkit. But will the Bukkit team do it? NO.
      • Added a reloadScript() method into the ScriptPlugin class. This enables single scripts to be reloaded without having to /reload the server.
    • r4
      • Fix for Bukkit 490+ by verrier
      • Fix importScript utility method by holic
      • Move the listener into an inner class by holic
      • Attempt at getting jxpl to be nice to /reload
    • r3 (all by Myers)
      • Remove long constructor
      • Changed PluginHelper access modifier so Python works
    • r2 API changes may break existing scripts!
      • Moved script-specific methods out into an inner class.
      • Server can now be accessed as a variable
      • Predefined variable (helper, plugin, server) names can now be changed.
      • Added helper methods to include scripts and read file contents.
      • Added getScriptEngine() for plugin > script communication.
      • Updated example scripts to reflect API changes.
    • r1
      • Changed versioning system.
      • Removed onCommand method. Until commands can be registered on-the-go, that command system will not be available.
      • Standardised what happens when jxpl is (un/re)loaded. On unload, all scripts' events are disabled. Scripts may still act on their own if they have set timers, such as setTImeout in JavaScript. On reload, all scripts' events are reenabled.
      • Officially renamed to jxpl.
    • 0.0.1
      • Initial release
    Todo:

    • Implement reloading of scripts & proper disabling of plugin (requires proper unloading of scripts)
      • Need to wait for Bukkit devs to implement proper un/reloading themselves.
      • N.B. ATM you can /reload (but it reloads all plugins.)
     
    Verrier and megabytes like this.
  2. Offline

    Myers Carpenter

    great!

    I think maybe you linked to the wrong jar?
     
  3. Offline

    angelsl

  4. Offline

    Myers Carpenter

    I was unable to get a python script to work :(.

    I downloaded your code from github, change were the source location, added a pom.xml to build with maven (like Bukkit itself), downloaded jython installer jar from here:

    http://sourceforge.net/projects/jyt...5.2rc3/jython_installer-2.5.2rc3.jar/download

    Installed the "standalone jar" version (which they had a direct download for just this). Copied that into my server directory in "libs" and ran this shell script:


    Code:
    #!/bin/sh
    java -Xms1024M -Xmx1024M -cp libs/jython.jar -jar target/craftbukkit-0.0.1-SNAPSHOT.jar
    

    The output:

    Code:
    2011-02-06 18:37:32 [INFO] Starting minecraft server version Beta 1.2_01
    2011-02-06 18:37:32 [INFO] Loading properties
    2011-02-06 18:37:32 [INFO] Starting Minecraft server on *:25565
    2011-02-06 18:37:32 [INFO] This server is running Craftbukkit version unknown (MC: 1.2_01)
    2011-02-06 18:37:32 [INFO] Preparing level "world"
    2011-02-06 18:37:32 [INFO] Preparing start region
    2011-02-06 18:37:34 [INFO] Preparing spawn area: 44%
    2011-02-06 18:37:34 [INFO] Initialising javax.script script loader ...
    2011-02-06 18:37:35 [INFO] Adding file extension ".js" for scripting engine "Mozilla Rhino".
    2011-02-06 18:37:35 [INFO] Done! For help, type "help" or "?"
    No python. Any ideas?
     
  5. Offline

    angelsl

    Jython must be included before Craftbukkit in the classpath it seems.

    Try
    Code:
    java -Xms1024M -Xmx1024M -cp libs/jython.jar:target/craftbukkit-0.0.1-SNAPSHOT.jar org.bukkit.craftbukkit.Main
    (modify accordingly for Windows)
     
  6. Offline

    Myers Carpenter

    That worked! Thanks.

    Doing that same thing I got ruby working as well:

    Code:
    require 'java'
    
    
    scriptName = "RbExampleScript"
    scriptVersion = "1"
    
    
    Event = org.bukkit.event.Event
    Level = java.util.logging.Level
    
    
    def onEnable()
      $plugin.log(Level::INFO, "RbExampleScript loaded!")
      $plugin.registerEvent(Event::Type::PLAYER_JOIN, Event::Priority::Lowest, "onPlayerJoin")
    end
    
    
    def onDisable()
      $plugin.log(Level::INFO, "RbExampleScript unloaded!")
    end
    
    
    def onCommand(sender, command, label, args)
      return False
    end
    
    
    def onPlayerJoin(type, args)
      $plugin.getServer().broadcastMessage("RbExampleScript says hi, " + args.getPlayer().getName())
    end
    --- merged: Feb 7, 2011 2:00 PM ---
    Have you looked at the pull request that let's you unregister listeners?

    https://github.com/Bukkit/Bukkit/pull/58

    Another idea is to use some of the same methods found in the groovy plugin that let's folks run code from a command:

    http://forums.bukkit.org/threads/dev-groovybukkit-v-a-plugin-for-writing-groovy-plugins.1267/
     
  7. Offline

    angelsl

    Revision 1.
    • Rename to jxpl
    • Change versioning system
    • Full changelog in original post
    Also note that you can use Groovy, Ruby, Python, among other languages. I believe Lua, Haskell, Scheme and Tcl are supported as well. Go search for the JSR 223 compliant implementations.
     
  8. Offline

    megabytes

    Eeeeee! Thank you for this! I'm a total Java noob, but I absolutely love Javascript. Now I can finally start writing my own plugins! Wohooooo~

    Edit: Excuse me for being incredible new to Rhino, but how would I go about adding JSON support? Any recommendations for async timers like the browser-based setTimeout()? And what's the overhead like for a few dozen small scripts as opposed to a dozen or so plugins?

    Figured out the setTimeout/Interval stuff thanks to env.js:
    Code:
        
    	function setTimeout(fn, time) {
    		var timer;
    		return timer = setInterval(function() {
    			fn();
    			timer.stop();
    		}, time);
    	}
    	
    	function setInterval(fn, time) {
    		var timer = new java.lang.Thread(new java.lang.Runnable({
    			run: function() {
    				while(1) {
    					java.lang.Thread.currentThread().sleep(time);
    					fn();
    				}
    			}
    		}));
    		
    		timer.start();
    		return timer;
    	}
    	
     
  9. Offline

    angelsl

    I believe everything in standard JavaScript should be present in Rhino. Also, there shouldn't be much overhead other than parsing the scripts (and env.js).

    Note that just like normal plugins, you are still not able to fully reload specific scripts on the fly. The only way is to /reload, which reloads every plugin and script.

    Finally, what do you need JSON for?
     
  10. Offline

    megabytes

    Thanks for the reply. It'll be great to reload specific scripts in the future, but /reload works fine for now.

    I'd like to use JSON for my script configs and possibly for finer-grained logging.

    Another few questions for you:
    1. Is it possible to "include" files outside of reading them into a string and running it through eval?
    2. Is it possible for scripts to use functions that exist in other loaded scripts without having to explicitly include them in each script? i.e. if I wanted to load script with just utilities like setTimeout/Interval, readFile, writeFile, etc., how would I access and use those functions from another script?
    3. Same goes for a plugin using a script's functions or vice versa - is it possible? If so, do you have any example code you can point me to? Still trying to wrap my head around how the two (Java and JS) fit together and communicate with one another.
    Thanks again for this great plugin! I've already got two handy scripts running on my server and will be releasing them here soon :)
     
  11. Offline

    angelsl

    JSON
    JSON is JavaScript Object Notation, if you are unaware. You can simply include it at the top of your script and leave some comments.. e.g.:

    PHP:
    // Configuration
    var config = {
        
    "property1""value1"
        "makeServerExplode"
    false
        
    };
    // DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING OR YOUR SERVER WILL PROBABLY MORPH INTO A URANIUM ATOMIC BOMB.. AND DETONATE.

    scriptName "LALALA"
    scriptVersion "0"

    // and so on
    Question 1
    I could provide a helper.includeScript().

    Question 2
    See question 1. Simply include the script should do.

    Question 3
    Java -> Scripts: Get the plugin, get the scripting engine (I will provide plugin.getScriptingEngine()), and do whatever.
    Scripts -> Java: getServer().getPluginManager().getPlugin("...").doStuff(). Don't need to cast.
     
  12. Offline

    Myers Carpenter

    re: the timer issue. You might want to look at the Bukkit Scheduler to do this rather that start another thread.
     
  13. Offline

    megabytes

    Right, but I'm thinking along the lines of stored configs, which would need JSON.stringify and JSON.parse.
    --- merged: Feb 10, 2011 11:42 PM ---
    Thanks for the tip. I'll look into that :)
     
  14. Offline

    cyberbobjr

    Nice work !
    I think to make some scripts for logging events in my bukkit webadmin (the output is coming soon :))
     
  15. Offline

    angelsl

    I believe it should already be there? Have you tried?
     
  16. Offline

    megabytes

    Yea, I've tried several names and import paths, but no luck. Any ideas?

    A safe way to include script files would more or less take care of the JSON.parse need in terms of loading configs, but JSON.stringify is still needed to write configs, etc.

    Edit: Hmm, org.json.simple.JSONObject seems to be in here now. I was trying to load a few JSON libraries to see what'd work, and this one seems to be in here without a jar file. Now all I really need is a way for plugins to interact with scripts. :)
     
  17. Offline

    oliverw92

    You are actually my god right now :D I used to use the ScriptingAPI plugin for hMod, now there is finally a replacement for Bukkit :D
     
    megabytes likes this.
  18. Offline

    angelsl

    r2 is released. Please take note that API changes may break existing scripts.

    r2 API changes may break existing scripts!
    • Moved script-specific methods out into an inner class.
    • Server can now be accessed as a variable
    • Predefined variable (helper, plugin, server) names can now be changed.
    • Added helper methods to include scripts and read file contents.
    • Added getScriptEngine() for plugin > script communication.
    • Updated example scripts to reflect API changes.
    Please open an issue for feature requests from now onwards.
     
  19. Offline

    megabytes

    Thanks angelsl!
     
  20. Offline

    oliverw92

    Do you have any insight on how to spawn a mob with JS? Not really sure how to do this - I've tried looking at the sources of some plugins that do it but I don't really understand Java enough to understand what is going on!
     
  21. Offline

    megabytes

    I dissected the SpawnMob plugin and came up with the following code. Put this in your onEnable function and you'll spawn a giant zombie at your feet every time you send a message:
    PHP:
    with(JavaImporter(org.bukkit.event)) {
        
    helper.registerEvent(Event.Type.PLAYER_CHATEvent.Priority.Highest'onPlayerChat');
    }

    onPlayerChat = function(typeevent) {
        var 
    player event.getPlayer(),
            
    world player.getWorld().getHandle();
        
    with(JavaImporter(org.bukkit.craftbukkit.entitynet.minecraft.server)) {
            try {
                var 
    mob = new CraftGiant(server, new EntityGiantZombie(world));
                
    mob.teleportTo(player.getLocation());
                
    world.a(mob.getHandle());
            } catch(
    e) {
                
    // spawn failed
            
    }
        }
    };
     
  22. Offline

    angelsl

    I advise against accessing Notchian or Craftbukkit classes directly. Your scripts would not work with any other server implementation.
     
  23. Offline

    megabytes

    How would you do it, then?
     
  24. Offline

    14mRh4X0r

    Could you perhaps add a toggle-able interactive console? Could prove useful for debugging plugins :)
     
  25. Offline

    oliverw92

    megabytes I can't seem to get that to work - the giant spawns but instantly disappears.
    --- merged: Feb 16, 2011 1:16 PM ---
    Worked out why - you can't spawn mobs with that method unless mobs are on in server.properties.


    I've delved into the net.minecraft.server.World functions in an attempt to get round this issue, but the functions i need are protected inside the World class.Has anyone got any experience with the JavaAdapter rhino function? I am trying to use it to extend the world class and put my own class in there that can be called from outside, but I can't seem to get it to work. Here is what i am trying:

    Code:
    with(JavaImporter(org.bukkit.craftbukkit.entity, net.minecraft.server)) {
                                    try {
                                        worldHandle = world.getHandle();
                                        //Create new CraftMob
                                        var mob = new CraftCreeper(server, new EntityCreeper(worldHandle));
                                        //Create new location obj and send mob to it
                                        var mobLoc = new org.bukkit.Location(world, posLoc.x, posLoc.y, posLoc.z);
                                        mob.teleportTo(player.getLocation());
                                        //Attatch it to the world
                                        entity = mob.getHandle();
                                        importPackage(java.awt);
                                        var MathHelper = new net.minecraft.server.MathHelper;
                                        var mWorld = new JavaAdapter(worldHandle, {
                                                                         hackMob: function (i, j, entity) {
                                                                            this.c(i, j).a(entity);
                                                                            this.b.add(entity);
                                                                            this.b(entity);
                                                                        }
                                                                     });
                                        var i = MathHelper.b(entity.locX / 16.0);
                                        var j = MathHelper.b(entity.locZ / 16.0);
                                        mWorld.hackMob(i, j, entity);
                                    } catch (e) {
                                        helper.log(Level.INFO, "[MobSpawner] Unable to spawn mob! "+e);
                                    }
                                }        
    Java errors saying i'm not using JavaAdapter correctly when i try that :(
     
  26. Offline

    angelsl

    r3 by Myers
    • Remove long constructor
    • Changed PluginHelper access modifier so Python works
     
  27. Offline

    shayneo

    edit: Scratch that. Got it going!
     
  28. Offline

    angelsl

    r4
    • Fix for Bukkit 490+ by verrier
    • Fix importScript utility method by holic
    • Move the listener into an inner class by holic
    • Attempt at getting jxpl to be nice to /reload
     
  29. Offline

    angelsl

    r5
    • Fix for Issue #5 - jxpl not working too well after reloads N.B. Hacky fix. Real fix is to change 3 lines of code in Bukkit. But will the Bukkit team do it? NO.
    • Added a reloadScript() method into the ScriptPlugin class. This enables single scripts to be reloaded without having to /reload the server.
     
  30. Offline

    Redyugi

    I wish I could have seen this earlier. I rather hate Java and have been learning it for my server, but Python is just my cup of tea. Can't wait to try this out. Thanks :)
     

Share This Page