Inactive [DEV/MISC] RubyBukkit v0.8 - Write plugins in JRuby [1.1-R6, ..., 1.2.4-R1.0]

Discussion in 'Inactive/Unsupported Plugins' started by Zeerix, Jul 6, 2011.

  1. Offline

    Zeerix

    RubyBukkit - Write plugins in JRuby
    Version: v0.8

    This is a custom plugin loader that enables you to write Bukkit plugins as short Ruby/JRuby scripts.

    Below are some example plugins in Ruby.
    And there is an explanation on How to Write Plugins in Ruby in the next post.

    View RubyBukkit on BukkitDev: http://dev.bukkit.org/server-mods/rubybukkit/

    Features:
    • Loads Bukkit plugins in Ruby/JRuby

    Download, Installation:

    Just drop the jar into the plugins folder. Additionally, you need the JRuby runtime version 1.6.x. You can download it from http://jruby.org/download, for example the tar.gz or the zip.
    Extract jruby.jar from the folder lib/ in the archive and drop the file into plugins/RubyBukkit (create that folder).

    Configuration:
    The plugin will create a default configuration file on startup as plugins/RubyBukkit/config.yml.
    Code:
    settings:
        plugins-path: plugins
        debug: true
    runtime:
        ruby-version: '1.8'
        jruby-path: plugins/RubyBukkit/jruby.jar
    
    • plugins-path - the folder which this plugins looks for Ruby plugins in. All files with extension .rb are loaded. You can change this path to separate the normal Java plugins from Ruby plugins.
    • debug - enables/disabled debug output about plugin loading
    • ruby-version - JRuby version compatibility mode: '1.8' or '1.9'
    • jruby-path - location of the jruby runtime

    Example plugins:
    Here is a list of some example plugins. There's also an explanation on How to Write Plugins in Ruby in the next post.
    • [GEN/INFO] OnlinePlayers - Displays list of online players on login and by a command.
    • [WGEN] RubyMoon - Ruby version of the custom map generator BukkitFullOfMoon by Dinnerbone.
    • [ADMN] GarbageCollect - Registers a command that forces a garbage collection cycle.
    • [INFO] Uptime - Displays time since server start on /uptime.
    • [MISC/MECH] CustomRecipes - Adds some custom recipes for the crafting grid. Can easily be changed to add new recipes.

    Changelog:
    Version 0.8
    • Updated for CraftBukkit 1.1-R6.
    • registerEvent method changed.
      Use: registerEvent(org.bukkit.event.ThePackage.TheNameOfTheEvent, :Normal) { |event| /* code */ }
    Version 0.7.1
    • Updated for CraftBukkit 1.1-R1.
    Version 0.7
    • Changes for the new event system in CraftBukkit 1.1 dev builds:
      • RubyPlugin#registerEvent accepts Event.Type.EVENT_NAME, EventName.class and :EventName
    • Implemented new methods of org.bukkit.plugin.Plugin in RubyPlugin: getLogger and createRegisteredListeners
    Version 0.6
    • Added new methods for CraftBukkit 1.1 dev builds:
      • Methods for event timing measurement
      • saveResource, saveDefaultconfig
    Version 0.5
    • Implemented new Bukkit Configuration API
    • Activated JIT
    • Added classpath for Rubygems
    Show Spoiler

    Version 0.4.4
    • Fixed a bug in plugin.registerEvent forwarder method
    Version 0.4.3
    • Implemented plugin.getConfiguration()
    • Changed plugin.registerEvent to additionally take symbols and strings where enums are expected
    • Added overridable library files for Plugin.is{} block and a RubyPlugin class mixin
    Version 0.4.2
    • Moved Ruby library path from bukkit/ to lib/ (i.e. require 'lib/permissions')
    Version 0.4.1
    • Changed loading of JRuby runtime; less memory problems on /reload
    Version 0.4
    • First public release
    • Implemented virtual 'plugin.yml' inside the Ruby script
    • Implemented support for RubyBukkit-boundled and custom Ruby libraries
    • Added library for simple Permissions, PermissionsEx and GroupManager support


    Donation:
    If you like RubyBukkit, you can donate some Bitcoins to my address.
    One-time addresses and other forms of donation on request.
    RubyBukkit
    How to write a Ruby plugin

    A Ruby plugin lives in one single file called 'PluginName.rb'. The loader executes these files to get the class definitions and the plugin descriptions. Since there is no plugin.yml, that information is also read from the script file itself.

    The plugin OnlinePlayers will be used as an example. You can read the full source code behind the link.

    Plugin description
    The loader generates the plugin description from information that you provide in the Ruby script.
    The script calls "Plugin.is" with a Ruby block. In this block, method calls named like the plugin.yml nodes are used to provide the neccessary information.
    You must at least provide values for name and version.
    You can use Symbols and Strings interchangeably.
    Code:
    Plugin.is {
        name "OnlinePlayers"
        version "0.3"
        author "Zeerix"
        description "Displays list of online players on login and by a command"
        commands :list => {
            :description => "Show online players.",
            :usage => "/list",
            :aliases => [ :players, :online ]
        }
    }
    
    Main class
    The main plugin class muss inherit from RubyPlugin and define the methods onEnable and onDisable.
    The name of this class must be what you wrote in the plugin description.
    Actually, the class' name must be the same as the 'main' node in the plugin description, which defaults to the
    'name' node if you don't provide one.

    Code:
    class OnlinePlayers < RubyPlugin
       def onEnable
          print getDescription.getFullName + " enabled."
       end
       def onDisable; end
    end
    
    Java/Bukkit classes
    You can use Java classes with the full package name or import the classes just like in Java.
    Unlike Java, the import statement takes a string as argument.
    Code:
    import 'org.bukkit.event.Event'
    Nested classes and the values in a Java enum are separated with a :: instead of a period.
    Code:
    def onEnable
       pm = getServer.getPluginManager
       pm.registerEvent(Event::Type::PLAYER_LOGIN, MyListener.new, Event::Priority::Normal, self)
    end
    Events
    Additionally to the normal Bukkit interface for event/listener registration (see above), the class RubyPlugin defines the method registerEvent which lets you register a Ruby block as listener.
    This is useful for a small plugin where you don't want to create extra classes for the listeners.
    Code:
    registerEvent(Event::Type::PLAYER_LOGIN, Event::Priority::Normal) {
       |loginEvent|
       player = loginEvent.getPlayer    
       # do something with player / loginEvent
    }
    
    Scheduler
    There are also convenience methods in RubyPlugin to register tasks in the scheduler.
    The simplest one just takes a block and executes it synchronously (in the main thread):
    Code:
    scheduleSyncTask { print "Hello World!" }
    You can also register delayed and repeating tasks:
    Code:
    scheduleSyncDelayedTask(20) { print "after 20 ticks." }
    scheduleSyncRepeatingTask(10, 20) { print "after 10 ticks, every 20 ticks." }
    
    There is also an Async variant for all three.

    Commands
    Commands are registered in the plugin description (the Plugin.is block, see above).
    If a command is used by a player or in the console, the onCommand method is called.
    Use sender.isPlayer or sender.is_a?(Player) to check if it was used by a player or in the console.
    Don't forget to return true.
    Code:
    def onCommand(sender, command, label, args)
       listPlayersTo sender
       true
    end
    
    Ruby libraries
    <todo>
    • Permissions - lib/permissions.rb
      Code:
      Setup: require 'lib/permissions'
      Usage: player.has("permission.node")
      

    <reserved>

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 17, 2016
    Coelho, TZer0 and nacs like this.
  2. Offline

    Seta

    Simple amazing. I <3 Ruby :D
     
  3. Offline

    DisabledHamster

    Just to say... This is pretty damn awesome.

    Though... From all the sample plugins I've seen - guys. Your Ruby is shockingly disgusting. Fix it kthx (@Nijikokun)
     
  4. Offline

    Zeerix

    Give me better example plugins ;-)
     
  5. Offline

    Sevenos

    Sad I haven't found this before - will try it asap. As Ruby is my main language for the last 4 years now, I could do all the complex stuff in ruby and marry it with a java plugin to do the hard work (high frequency events).
     
  6. Offline

    zaack

    your amazing :)
     
  7. Offline

    Deleted user

    Caused by: org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `ConsoleCommandSender' for #<Java::OrgBukkitCraftbukkit::CraftServer:0x4e1ba9a0>
    What's up with this? :confused:
     
  8. Offline

    Zeerix

    Which version, which Ruby script?
     
  9. Offline

    Deleted user

    v1.5, and I messed up some of the code in my plugin. Sorry about that.
     
  10. Offline

    Chaazd

    Uhh, sorry to break the news to you, but there is already a far more advanced and easier way to use ruby
    with bukkit. It's called Purugin and is made by the main contributor to Jruby. https://github.com/enebo/Purugin/
    I use it and I am very happy with it.
     
  11. Offline

    Zeerix

    I have seen that already.
    Why do you think it is easier to use than this? As far as I know it's the same as mine, except that he wraps more of the Bukkit API with Ruby classes.

    I wonder why Thomas Enebo didn't put it on Bukkit.org where people can find it?
     
  12. Offline

    Coelho

    Easy to use and very expandable! Had no issues with it while writing my plugin. <3
    Thanks!
     
  13. Offline

    mstram

    Can someone post a simple redstone example ?

    I..e with redstone dust connected to a block, how to read / write to the "side / port" of the block

    thx

    Mike
     
  14. Offline

    Zeerix

    Updated for the new RB (1.1-R6) and the new event system.

    You have to change the event registering methods to use the class name instead of a :RubySymbol or Event.Type.

    Example:
    Code:
    import 'org.bukkit.event.player.PlayerLoginEvent'
    
    registerEvent(PlayerLoginEvent, :Normal) {
        |loginEvent|
        player = loginEvent.getPlayer    
        # ...
    }
    
     
    Coelho likes this.
  15. Offline

    prophesix

    sorry I'm a noob but i can essentially build my own custom server written with this plugin? ranks? colors? chat channels? levels? races? my own custom commands? surnames? skills??? 0.O
     
  16. Offline

    Coops

    Well maybe but if you developed a bunch of plugins that already exist and did it in ruby... You would be half god lol.
    Not to mention ruby is not as good performance wise as java.
     
  17. Offline

    prophesix


    Thought so, so it is an entirely different language... just wasn't sure, sorry I'm such a noob... Tho I have learned a thing or two since march =P
     
  18. Offline

    Coops

    We all have those moments. = D
     

Share This Page