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


    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:

    • 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, 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).

    The plugin will create a default configuration file on startup as plugins/RubyBukkit/config.yml.
        plugins-path: plugins
        debug: true
        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.

    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{} 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

    If you like RubyBukkit, you can donate some Bitcoins to my address.
    One-time addresses and other forms of donation on request.
    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 "" 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: {
        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.

    class OnlinePlayers < RubyPlugin
       def onEnable
          print getDescription.getFullName + " enabled."
       def onDisable; 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.
    import 'org.bukkit.event.Event'
    Nested classes and the values in a Java enum are separated with a :: instead of a period.
    def onEnable
       pm = getServer.getPluginManager
       pm.registerEvent(Event::Type::PLAYER_LOGIN,, Event::Priority::Normal, self)
    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.
    registerEvent(Event::Type::PLAYER_LOGIN, Event::Priority::Normal) {
       player = loginEvent.getPlayer    
       # do something with player / loginEvent
    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):
    scheduleSyncTask { print "Hello World!" }
    You can also register delayed and repeating tasks:
    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 are registered in the plugin description (the 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.
    def onCommand(sender, command, label, args)
       listPlayersTo sender
    Ruby libraries
    • Permissions - lib/permissions.rb
      Setup: require 'lib/permissions'
      Usage: player.has("permission.node")


    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


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


    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


    Give me better example plugins ;-)
  5. Offline


    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


    your amazing :)
  7. Offline


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


    Which version, which Ruby script?
  9. Offline


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


    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.
    I use it and I am very happy with it.
  11. Offline


    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 where people can find it?
  12. Offline


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


    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


  14. Offline


    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.

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


    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


    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


    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


    We all have those moments. = D

Share This Page