Build plugins
without the pain.
No NMS. No reflection. No version-specific hacks. Just clean, type-safe APIs.
// Sending a title packet
Object packet = Class.forName("net.minecraft.server."
+ VERSION + ".PacketPlayOutTitle")
.getConstructor(...).newInstance(...);
player.getClass().getMethod("getHandle")
.invoke(player).getClass()
.getField("playerConnection").get(...)
.getClass().getMethod("sendPacket", ...)
.invoke(connection, packet);
// Breaks every update. Good luck.
// Rewriting chat in a plugin
context.register_event_handler::<PlayerChatEvent, _>(
PrefixChat,
EventPriority::Normal,
true,
)?;
impl EventHandler<PlayerChatEvent> for PrefixChat {
fn handle(&self, _server: Server, mut event: PlayerChatEventData) -> PlayerChatEventData {
event.message = format!("[Pumpkin] {}", event.message);
event
}
}
Every Player, One Plugin
Native Java + Bedrock support. Multi-version built in. Write once, reach everyone.
Typed Commands & Events
Register commands and hook typed plugin events without reflection, NMS, or version-specific hacks.
Async by Default
Built on Tokio. No main thread bottleneck. Heavy tasks don't freeze the server.
Memory Safe
Rust guarantees. No null pointers, no memory leaks, no data races.
Quick Start Guide
Creating a new project
Pumpkin plugins use the Cargo build system.
The complete code for this plugin can be found as a template on GitHub.
Installing the toolchain
Before we can compile a plugin, we have to have the wasm32-wasip2 target installed. You can install the target by running:
rustup target add wasm32-wasip2
Initializing a new crate
First we need to create a new project folder. You can do this by running this command in the folder you created:
cargo new <project-name> --lib
After adding this, we want to create a new directory called .cargo and add in a config.toml file with the following contents:
[build]
target = "wasm32-wasip2"
Altogether your new folder structure should look like this:
├── .cargo/
│ └── config.toml
├── src/
│ └── lib.rs
├── Cargo.toml
└── Cargo.lock
Configuring the crate
Since Pumpkin plugins are loaded at runtime as dynamic libraries, we need to tell Cargo to build this crate as one.
Cargo.toml
[package]
name = "hello-pumpkin-wasm"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
Next we need to add some basic dependencies. Since Pumpkin is still in early development, the internal crates aren't published to crates.io, so we need to tell Cargo to download the dependencies directly from GitHub.
Cargo.toml
[package]
name = "hello-pumpkin"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
# This is the api crate that makes creating plugins easier, and has wit definitions
pumpkin-plugin-api = { version = "0.1.0", git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-plugin-api" }
tracing = "0.1"
Refer to the documentation for more.
Installation
First, you need to install the pumpkin-api-py library:
pip install pumpkin-api-py
Creating your first plugin
Create a file named main.py and add the following content:
from pumpkin_api import (
Plugin, PluginMetadata, register_plugin,
server, event, command, text, context
)
class MyPlugin(Plugin):
def metadata(self) -> PluginMetadata:
return PluginMetadata(
name="my-plugin",
version="0.1.0",
authors=["you"],
description="An example plugin."
)
def on_load(self, ctx: context.Context) -> None:
print("Python plugin loaded!")
# Register an event handler
self.register_event(ctx, event.EventType.PLAYER_JOIN_EVENT, self.on_player_join)
def on_player_join(self, srv: server.Server, evt: event.PlayerJoinEventData) -> event.PlayerJoinEventData:
print(f"Player {evt.player.get_name()} joined!")
return evt
register_plugin(MyPlugin)
Building the plugin
Build your plugin into a WebAssembly component using the provided build tool:
pumpkin-api-build main -o my_plugin.wasm
This will generate a my_plugin.wasm file that you can place in the plugins folder of your Pumpkin server.
Refer to the documentation for more.
Installation
You will need the .NET SDK and the WASI workload to compile C# plugins for Pumpkin.
dotnet workload install wasi-experimental
Creating your first plugin
Create a new class library and add the following code:
using Pumpkin.API;
public class MyPlugin : IPlugin {
public PluginMetadata GetMetadata() => new() {
Name = "my-csharp-plugin",
Version = "0.1.0",
Authors = new[] { "you" },
Description = "A simple C# plugin for Pumpkin"
};
public void OnLoad(IContext ctx) {
Console.WriteLine("C# plugin loaded!");
}
}
Building the plugin
Compile the plugin to WebAssembly using the WASI runtime identifier:
dotnet build -c Release /p:RuntimeIdentifier=wasi-wasm
This will generate a .wasm file in your output directory that can be loaded by Pumpkin.
Refer to the documentation for more.
Installation
You will need the wasi-sdk to compile C/C++ plugins for Pumpkin. Download the latest release from the wasi-sdk repository.
The complete code for this plugin can be found in the pumpkin-api-c repository.
Creating your first plugin
Create a file named main.c and add the following content:
#include "pumpkin_api.h"
#include <stdio.h>
// Define the plugin's metadata
pumpkin_metadata_t get_meta(void) {
static const char* authors[] = {"you"};
return (pumpkin_metadata_t) {
.name = "my-c-plugin",
.version = "0.1.0",
.authors = authors,
.authors_count = 1,
.description = "A simple C plugin for Pumpkin",
.dependencies_count = 0
};
}
// Callback executed when the plugin is loaded
void on_load(plugin_own_context_t ctx) {
printf("C plugin loaded!\n");
}
// Register the plugin with the API
REGISTER_PUMPKIN_PLUGIN(((pumpkin_plugin_t){
.get_metadata = get_meta,
.on_load = on_load
}))
Building the plugin
To compile this plugin into a WebAssembly component, use clang from the wasi-sdk:
/path/to/wasi-sdk/bin/clang -O3 \
-Iinclude -Isrc/gen \
src/gen/plugin.c src/pumpkin_api.c main.c \
-o my_plugin.wasm \
-mexec-model=reactor
This will generate a my_plugin.wasm file that can be loaded by Pumpkin.
Refer to the GitHub repository for more.
Installation
You will need Go 1.23 or later and tinygo to compile Go plugins for Pumpkin.
brew tap tinygo-org/tools && brew install tinygo
Creating your first plugin
Create a file named main.go and add the following content:
package main
import (
"fmt"
"github.com/pumpkin-mc/pumpkin-api-go"
)
type MyPlugin struct{}
func (p *MyPlugin) Metadata() pumpkin.PluginMetadata {
return pumpkin.PluginMetadata{
Name: "my-go-plugin",
Version: "0.1.0",
Authors: []string{"you"},
Description: "A simple Go plugin for Pumpkin",
}
}
func (p *MyPlugin) OnLoad(ctx pumpkin.Context) {
fmt.Println("Go plugin loaded!")
}
func main() {
pumpkin.RegisterPlugin(&MyPlugin{})
}
Building the plugin
Compile the plugin to WebAssembly using tinygo:
tinygo build -o my_plugin.wasm -target=wasi main.go
This will generate a my_plugin.wasm file that can be loaded by Pumpkin.
Refer to the documentation for more.