Skip to content

Repository files navigation

Toomo 🐍 → 🎮

Write Minecraft Bukkit plugins in Python. Zero Java required.

Toomo lets you write Bukkit/Spigot/Paper plugins using pure Python, powered by GraalPy (GraalVM's Python runtime). Define event handlers with decorators, register commands, and access the full Bukkit API — all without touching a single line of Java.

from toomo import ToomoPlugin, on_event, on_command
from toomo.events import PLAYER_JOIN, PLAYER_QUIT

class MyPlugin(ToomoPlugin):
    def on_enable(self):
        self.logger.info("Hello from Python!")

    @on_event(PLAYER_JOIN)
    def on_join(self, event):
        player = event.getPlayer()
        player.sendMessage(f"Welcome, {player.getName()}!")

    @on_command("hello")
    def hello(self, sender, cmd, label, args):
        sender.sendMessage("Hello from Python!")
        return True

How It Works

Your Python code  ──→  toomo build  ──→  plugin.jar
                             │
              ┌──────────────┼──────────────┐
              │ Java Bootstrap (auto-generated) │
              │ GraalPy Runtime (bundled)       │
              │ Bukkit Bindings (auto-wired)    │
              └─────────────────────────────────┘
  1. You write Python using toomo's decorators and bindings
  2. toomo build compiles a thin Java bootstrap + bundles your Python
  3. Drop the JAR into your server's plugins/ folder
  4. Server runs GraalVM — Python executes natively on the JVM

Quick Start

Prerequisites

  • Development machine: Python 3.11+, uv
  • Minecraft server: GraalVM JDK 23+ with GraalPy

Install toomo

pip install toomo
# or
uv tool install toomo

Create a plugin

toomo init MyFirstPlugin
cd MyFirstPlugin

This creates:

MyFirstPlugin/
├── toomo.toml    # Plugin configuration
├── plugin.py     # Your plugin code
└── .gitignore

Configure

Edit toomo.toml:

[plugin]
name = "MyFirstPlugin"
version = "1.0.0"
api_version = "1.21"
main = "plugin"
description = "My first Python Bukkit plugin"

[[commands]]
name = "hello"
description = "Says hello"
usage = "/hello"

[[permissions]]
name = "myplugin.use"
description = "Allows using myplugin"
default = "true"

Build

toomo build

Output: build/MyFirstPlugin-1.0.0.jar

Deploy

  1. Make sure your Minecraft server runs on GraalVM JDK 23+
  2. Copy the JAR to your server's plugins/ folder
  3. Start/restart the server

Configuration Reference

toomo.toml

Section Key Type Description
[plugin] name string Plugin name
[plugin] version string Plugin version
[plugin] api_version string Bukkit API version (e.g., "1.21")
[plugin] main string Python module name (default: "plugin")
[plugin] description string Plugin description
[[commands]] name string Command name (without /)
[[commands]] description string Command description
[[commands]] usage string Usage hint
[[commands]] aliases string[] Command aliases
[[commands]] permission string Required permission
[[permissions]] name string Permission node
[[permissions]] description string Permission description
[[permissions]] default string Default value (true/false/op)
depend string[] Hard dependencies
soft_depend string[] Soft dependencies

API Reference

ToomoPlugin

Base class for all plugins. Provides:

Method/Property Description
on_enable() Called when plugin loads
on_disable() Called when plugin unloads
.logger Java Logger instance
.server Bukkit Server instance
.name Plugin name
.data_folder Plugin data directory
.get_config() Get config.yml
.save_config() Save default config
.save_resource(path) Extract resource from JAR

Event Decorator

@on_event('org.bukkit.event.player.PlayerJoinEvent')
def handler(self, event):
    # event is a Bukkit Event object — use Java methods directly
    player = event.getPlayer()

Common events available as constants in toomo.events:

Constant Event
PLAYER_JOIN PlayerJoinEvent
PLAYER_QUIT PlayerQuitEvent
PLAYER_CHAT AsyncPlayerChatEvent
PLAYER_MOVE PlayerMoveEvent
PLAYER_DEATH PlayerDeathEvent
BLOCK_BREAK BlockBreakEvent
BLOCK_PLACE BlockPlaceEvent
ENTITY_DAMAGE EntityDamageEvent
... (80+ event constants)

Command Decorator

@on_command('commandname')
def handler(self, sender, command, label, args):
    # sender: CommandSender (Player or ConsoleCommandSender)
    # command: Command object
    # label: string used to invoke the command
    # args: list of strings
    return True  # Return True to indicate success

Bukkit Interop

Access any Bukkit/Java class directly via GraalPy:

# From within your plugin methods:
Bukkit = java.type('org.bukkit.Bukkit')
worlds = Bukkit.getWorlds()

Material = java.type('org.bukkit.Material')
diamond = Material.DIAMOND

# Or use the convenience wrapper:
from toomo import bukkit
bukkit.Bukkit.broadcastMessage("Hello!")

Requirements

Development

  • Python 3.11+
  • uv (recommended)

Server

  • GraalVM JDK 23+ with GraalPy
    # Install GraalVM + GraalPy
    gu install python
  • Paper/Spigot server for Minecraft 1.21+

Why GraalPy?

GraalPy runs Python code directly on the JVM with full access to Java classes and libraries. This means your Python plugin can interact with the Bukkit API as if it were native Java — no bridges, no RPC, no performance penalty.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages