Convenient Python wrapper library for Bukkit API integration with Paper server
Project description
papermc_bukkit - Python Bukkit Wrapper
Convenient Python wrapper library for developing Minecraft plugins on Paper servers using Python 3.12 via GraalVM.
Overview
papermc_bukkit makes it easy to develop Paper/Spigot server plugins in Python. Write your plugin logic in Python while having full access to the Bukkit API and Java ecosystem.
from papermc_bukkit import BukkitServer, Logger
class MyPlugin:
def on_enable(self):
logger = Logger.create(self)
logger.info(f"Server running: {BukkitServer.get_server().getName()}")
for player in BukkitServer.get_all_players():
player.sendMessage("§6Welcome to my Python plugin!")
Features
- ✅ Direct Bukkit API Access - Use Java imports directly
- ✅ Convenient Wrapper Classes - Simple Python interface to Bukkit
- ✅ Event System - Register and handle server events
- ✅ Command System - Create custom commands easily
- ✅ Configuration Files - Simple YAML config management
- ✅ Logging Integration - Server-integrated logging
- ✅ Task Scheduling - Sync and async task scheduling
Installation
For Plugin Development
- Install Python 3.12
- Install GraalVM JDK 24+ with Python support
- Install this wrapper:
pip install papermc_bukkit
Package Your Plugin
Create a ZIP archive with:
plugin.zip
├── paper-plugin.yml # Plugin metadata
├── plugin.py # Your Python code
└── requirements.txt # Optional Python dependencies
Quick Start
1. Create paper-plugin.yml
name: MyAwesomePlugin
version: 1.0.0
description: An awesome Python-powered plugin
authors:
- Your Name
paper-api-version: 1.20
2. Create plugin.py
from org.bukkit import Bukkit
from org.bukkit.event import EventPriority
from papermc_bukkit import BukkitServer, Logger, EventListener
class Plugin:
def __init__(self):
self.logger = None
def on_load(self):
"""Called when plugin is loaded (before on_enable)"""
pass
def on_enable(self):
"""Called when plugin is enabled"""
self.logger = Logger.create(self)
self.logger.info("Plugin enabled!")
# Broadcast message to all players
BukkitServer.broadcast("§6A Python plugin has loaded!")
# Schedule a task
BukkitServer.schedule_sync_task(
self,
lambda: self.logger.info("Task executed!"),
delay=20 # 1 second delay
)
def on_disable(self):
"""Called when plugin is disabled"""
if self.logger:
self.logger.info("Plugin disabled!")
3. Package as ZIP
zip plugin.zip paper-plugin.yml plugin.py
4. Deploy
Copy your ZIP to the plugins/ directory on your Paper server.
Core Components
BukkitServer
Static utility class for server operations:
get_server()- Get Bukkit server instanceget_player(name)- Find player by nameget_all_players()- Get all online playersget_world(name)- Get world by namebroadcast(message)- Broadcast to all playersschedule_sync_task(plugin, callable, delay)schedule_async_task(plugin, callable, delay)schedule_repeating_task(plugin, callable, delay, period)
Logger
Log messages to server console:
logger = Logger.create(my_plugin)
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
logger.debug("Debug message")
EventListener
Register event handlers:
@EventListener.register(my_plugin, PlayerJoinEvent)
def on_player_join(event):
player = event.getPlayer()
player.sendMessage("Welcome!")
Config
Manage YAML configuration files:
config = Config("plugins/MyPlugin/config.yml")
config.load()
value = config.get("setting.key", default="default_value")
config.set("setting.key", "new_value")
config.save()
PythonPluginCommand
Register custom commands:
@PythonPluginCommand.register(my_plugin, "mycommand",
description="My custom command")
def handle_mycommand(sender, args):
sender.sendMessage("Command executed!")
return True
Direct Java Imports
You can import and use any Bukkit or Java class directly:
from org.bukkit import Bukkit, Material
from org.bukkit.entity import Player
from org.bukkit.event.player import PlayerJoinEvent
from java.util import UUID
# Use Java classes as normal
uuid = UUID.randomUUID()
Examples
Command Handler
@PythonPluginCommand.register(self, "teleport")
def handle_teleport(sender, args):
if len(args) < 2:
sender.sendMessage("Usage: /teleport <x> <y>")
return False
try:
x = float(args[0])
y = float(args[1])
player = BukkitServer.get_player(sender.getName())
if player:
player.teleport(player.getLocation().add(x, y, 0))
sender.sendMessage("Teleported!")
return True
except ValueError:
sender.sendMessage("Invalid coordinates")
return False
Async Task
def my_async_work():
# Do heavy computation
result = expensive_calculation()
# Schedule sync task to apply result
BukkitServer.schedule_sync_task(
self,
lambda: apply_result(result)
)
BukkitServer.schedule_async_task(self, my_async_work)
Configuration
config = Config("plugins/MyPlugin/config.yml")
config.load()
# Load settings
max_players = config.get("settings.max-players", default=100)
difficulty = config.get("difficulty", default="normal")
# Update settings
config.set("last-saved", str(datetime.now()))
config.save()
Limitations
- Python 3.12 only - Fixed version for stability
- Restart to reload - No hot reload, restart server to update plugin
- GraalVM required - Needs GraalVM JDK 24+ with Python support
- Performance - Python slower than Java, suitable for most tasks
- Single context - Each plugin runs in isolated GraalVM context
Future Enhancements
- Event decorator syntax
- Async/await support
- Advanced type hints
- Auto-dependency installation from requirements.txt
- Command builder utilities
- Plugin hot reload capability
Support & Troubleshooting
Plugin Won't Load?
- Check
logs/latest.logfor errors - Verify
paper-plugin.ymlYAML syntax - Ensure
plugin.pycontainsPluginclass - Check Python 3.12 compatibility
Import Errors?
# Use full qualified names
from org.bukkit import Bukkit
from java.util import UUID
# Or use the wrapper
from papermc_bukkit import BukkitServer
Performance Issues?
- Use
schedule_async_task()for heavy operations - Avoid synchronous I/O on main thread
- Consider using Java for critical-path code
Contributing
Contributions welcome! Please submit issues and pull requests to the GitHub repository.
License
MIT License - See LICENSE file for details
Resources
- Paper Server - High-performance Minecraft server
- Bukkit API - Server API documentation
- GraalVM - Polyglot virtual machine
- Python Guide - Python 3.12 documentation
Made with ❤️ for the Minecraft community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file papermc_bukkit-1.0.0.tar.gz.
File metadata
- Download URL: papermc_bukkit-1.0.0.tar.gz
- Upload date:
- Size: 7.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7dd7aedd2a8fe9388dd0bcace12b219640b8048edae4d820a22e901a6ca9a9b5
|
|
| MD5 |
cb9732c0e5e88a3fa9aa07692dda210b
|
|
| BLAKE2b-256 |
d8defbfeb8cbf4874346c73870650d601ed75575bf5ee31a0645989b70b97a90
|
File details
Details for the file papermc_bukkit-1.0.0-py3-none-any.whl.
File metadata
- Download URL: papermc_bukkit-1.0.0-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23029bb0d3663639b17247882f38afc0f95fa415a6acb8649f962673a557e474
|
|
| MD5 |
0788df48e9d86a5b3a3a0bf2b5eeeb29
|
|
| BLAKE2b-256 |
a3ee814c2c77a19bcd382a2a58a038ba3972a2fcab1d29df14502475b2f62952
|