dfplugin

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: MIT Imports: 12 Imported by: 0

README

df-plugin

Lightweight plugin and event bus for the df-mc/dragonfly Minecraft Bedrock server.

Register callbacks for events emitted by Dragonfly's player.Handler, world.Handler, and inventory.Handler interfaces — no need to implement the full interfaces yourself.

Install

go get github.com/ahnsunggwan45/df-plugin

Requires Go 1.23+ and github.com/df-mc/dragonfly.

Quick start

Wire the plugin manager into your server:

package main

import (
    "log/slog"

    "github.com/df-mc/dragonfly/server"
    "github.com/df-mc/dragonfly/server/player/chat"

    "github.com/ahnsunggwan45/df-plugin"

    // Blank-import your plugins so their init() runs.
    _ "yourmodule/plugins/joinannounce"
)

func main() {
    chat.Global.Subscribe(chat.StdoutSubscriber{})
    dfplugin.LogLoaded(slog.Default())

    srv := server.DefaultConfig().MustNew()
    srv.CloseOnProgramEnd()

    // Attach world handler to each built-in dimension.
    dfplugin.InstallWorld(srv.World())
    dfplugin.InstallWorld(srv.Nether())
    dfplugin.InstallWorld(srv.End())

    srv.Listen()
    for p := range srv.Accept() {
        dfplugin.Install(p) // attaches player + inventory handlers, fires OnJoin
    }
}

Writing a plugin

Each plugin is just a package whose init() calls dfplugin.Register. Set only the event fields you care about — the rest stay nil.

package joinannounce

import (
    "fmt"

    "github.com/df-mc/dragonfly/server/player"
    "github.com/df-mc/dragonfly/server/player/chat"

    "github.com/ahnsunggwan45/df-plugin"
)

func init() {
    dfplugin.Register(dfplugin.Plugin{
        Name: "joinannounce",
        OnJoin: func(p *player.Player) {
            _, _ = chat.Global.WriteString(fmt.Sprintf("%s joined the server.", p.Name()))
        },
        OnQuit: func(p *player.Player) {
            _, _ = chat.Global.WriteString(fmt.Sprintf("%s left the server.", p.Name()))
        },
    })
}

Then blank-import the plugin package from your main package so its init() runs.

Supported events

Player events (36)

Attached per player via dfplugin.Install(p).

OnJoin, OnQuit, OnMove, OnJump, OnTeleport, OnChangeWorld, OnToggleSprint, OnToggleSneak, OnChat, OnFoodLoss, OnHeal, OnHurt, OnDeath, OnRespawn, OnSkinChange, OnFireExtinguish, OnStartBreak, OnBlockBreak, OnBlockPlace, OnBlockPick, OnItemUse, OnItemUseOnBlock, OnItemUseOnEntity, OnItemRelease, OnItemConsume, OnAttackEntity, OnExperienceGain, OnPunchAir, OnSignEdit, OnSleep, OnLecternPageTurn, OnItemDamage, OnItemPickup, OnHeldSlotChange, OnItemDrop, OnTransfer, OnCommand, OnDiagnostics.

World events (12)

Attached per world via dfplugin.InstallWorld(w).

OnLiquidFlow, OnLiquidDecay, OnLiquidHarden, OnSound, OnFireSpread, OnBlockBurn, OnCropTrample, OnLeavesDecay, OnEntitySpawn, OnEntityDespawn, OnExplosion, OnWorldClose.

Inventory events (3)

dfplugin.Install(p) attaches them to the player's main inventory. For other inventories (armour, ender chest, custom containers) call inv.Handle(dfplugin.InventoryHandler()) yourself.

OnInventoryTake, OnInventoryPlace, OnInventoryDrop.

Cancelling and mutating events

Most callbacks receive a *Context (player, world, or inventory). Call ctx.Cancel() to cancel the event. Pointer arguments (e.g. msg *string, damage *float64, drops *[]item.Stack, entities *[]world.Entity) may be reassigned to mutate the event payload.

OnChat: func(ctx *player.Context, p *player.Player, msg *string) {
    if strings.Contains(*msg, "badword") {
        ctx.Cancel()
        return
    }
    *msg = "[chat] " + *msg
},
OnExplosion: func(ctx *world.Context, position mgl64.Vec3, entities *[]world.Entity, blocks *[]cube.Pos, itemDropChance *float64, spawnFire *bool) {
    *blocks = nil // explosion no longer breaks blocks
},
OnInventoryDrop: func(ctx *inventory.Context, slot int, it item.Stack) {
    ctx.Cancel() // disable item dropping from inventories
},

Example

A runnable example server lives under example/. It bundles the joinannounce plugin and produces a working Bedrock server on :19132:

git clone https://github.com/ahnsunggwan45/df-plugin
cd df-plugin/example
go run .

Connect with a Bedrock client to localhost:19132 and you should see <name> joined the server. in chat.

License

MIT

Documentation

Overview

Package dfplugin provides a lightweight plugin/event-bus layer for the df-mc/dragonfly Minecraft Bedrock server. Plugins are registered via Register() (typically from init()) and receive callbacks for events emitted by Dragonfly's player.Handler, world.Handler and inventory.Handler interfaces.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Install

func Install(p *player.Player)

Install attaches the composite player and inventory handlers to a player and fires OnJoin hooks. Call this once per player from the srv.Accept() loop.

func InstallWorld added in v0.2.0

func InstallWorld(w *world.World)

InstallWorld attaches the composite world handler to a world. Call this once per world on server startup (typically for srv.World(), srv.Nether(), srv.End()).

func InventoryHandler added in v0.2.0

func InventoryHandler() inventory.Handler

InventoryHandler returns an inventory.Handler that fans out to all registered plugins' OnInventory* callbacks. Attach it to any inventory you want plugins to observe.

func LogLoaded

func LogLoaded(log *slog.Logger)

LogLoaded prints the list of registered plugins to the given logger.

func Register

func Register(p Plugin)

Register adds a plugin to the global registry. Call this from an init() function in the plugin's package and ensure the package is imported (typically via a blank import in the application's main package).

Types

type Plugin

type Plugin struct {
	Name string

	// Player events (attached per player via Install).
	OnJoin            func(p *player.Player)
	OnMove            func(ctx *player.Context, p *player.Player, newPos mgl64.Vec3, newRot cube.Rotation)
	OnJump            func(p *player.Player)
	OnTeleport        func(ctx *player.Context, p *player.Player, pos mgl64.Vec3)
	OnChangeWorld     func(p *player.Player, before, after *world.World)
	OnToggleSprint    func(ctx *player.Context, p *player.Player, after bool)
	OnToggleSneak     func(ctx *player.Context, p *player.Player, after bool)
	OnChat            func(ctx *player.Context, p *player.Player, msg *string)
	OnFoodLoss        func(ctx *player.Context, p *player.Player, from int, to *int)
	OnHeal            func(ctx *player.Context, p *player.Player, health *float64, src world.HealingSource)
	OnHurt            func(ctx *player.Context, p *player.Player, damage *float64, immune bool, attackImmunity *time.Duration, src world.DamageSource)
	OnDeath           func(p *player.Player, src world.DamageSource, keepInv *bool)
	OnRespawn         func(p *player.Player, pos *mgl64.Vec3, w **world.World)
	OnSkinChange      func(ctx *player.Context, p *player.Player, skin *skin.Skin)
	OnFireExtinguish  func(ctx *player.Context, p *player.Player, pos cube.Pos)
	OnStartBreak      func(ctx *player.Context, p *player.Player, pos cube.Pos)
	OnBlockBreak      func(ctx *player.Context, p *player.Player, pos cube.Pos, drops *[]item.Stack, xp *int)
	OnBlockPlace      func(ctx *player.Context, p *player.Player, pos cube.Pos, b world.Block)
	OnBlockPick       func(ctx *player.Context, p *player.Player, pos cube.Pos, b world.Block)
	OnItemUse         func(ctx *player.Context, p *player.Player)
	OnItemUseOnBlock  func(ctx *player.Context, p *player.Player, pos cube.Pos, face cube.Face, clickPos mgl64.Vec3)
	OnItemUseOnEntity func(ctx *player.Context, p *player.Player, e world.Entity)
	OnItemRelease     func(ctx *player.Context, p *player.Player, i item.Stack, dur time.Duration)
	OnItemConsume     func(ctx *player.Context, p *player.Player, i item.Stack)
	OnAttackEntity    func(ctx *player.Context, p *player.Player, e world.Entity, force, height *float64, critical *bool)
	OnExperienceGain  func(ctx *player.Context, p *player.Player, amount *int)
	OnPunchAir        func(ctx *player.Context, p *player.Player)
	OnSignEdit        func(ctx *player.Context, p *player.Player, pos cube.Pos, frontSide bool, oldText, newText string)
	OnSleep           func(ctx *player.Context, p *player.Player, sendReminder *bool)
	OnLecternPageTurn func(ctx *player.Context, p *player.Player, pos cube.Pos, oldPage int, newPage *int)
	OnItemDamage      func(ctx *player.Context, p *player.Player, i item.Stack, damage *int)
	OnItemPickup      func(ctx *player.Context, p *player.Player, i *item.Stack)
	OnHeldSlotChange  func(ctx *player.Context, p *player.Player, from, to int)
	OnItemDrop        func(ctx *player.Context, p *player.Player, s item.Stack)
	OnTransfer        func(ctx *player.Context, p *player.Player, addr *net.UDPAddr)
	OnCommand         func(ctx *player.Context, p *player.Player, command cmd.Command, args []string)
	OnQuit            func(p *player.Player)
	OnDiagnostics     func(p *player.Player, d session.Diagnostics)

	// World events (attached per world via InstallWorld).
	OnLiquidFlow    func(ctx *world.Context, from, into cube.Pos, liquid world.Liquid, replaced world.Block)
	OnLiquidDecay   func(ctx *world.Context, pos cube.Pos, before, after world.Liquid)
	OnLiquidHarden  func(ctx *world.Context, hardenedPos cube.Pos, liquidHardened, otherLiquid, newBlock world.Block)
	OnSound         func(ctx *world.Context, s world.Sound, pos mgl64.Vec3)
	OnFireSpread    func(ctx *world.Context, from, to cube.Pos)
	OnBlockBurn     func(ctx *world.Context, pos cube.Pos)
	OnCropTrample   func(ctx *world.Context, pos cube.Pos)
	OnLeavesDecay   func(ctx *world.Context, pos cube.Pos)
	OnEntitySpawn   func(tx *world.Tx, e world.Entity)
	OnEntityDespawn func(tx *world.Tx, e world.Entity)
	OnExplosion     func(ctx *world.Context, position mgl64.Vec3, entities *[]world.Entity, blocks *[]cube.Pos, itemDropChance *float64, spawnFire *bool)
	OnWorldClose    func(tx *world.Tx)

	// Inventory events. Attached to the player's main inventory by Install.
	// Hook other inventories (armour, ender chest, containers) manually with
	// inv.Handle(dfplugin.InventoryHandler()).
	OnInventoryTake  func(ctx *inventory.Context, slot int, it item.Stack)
	OnInventoryPlace func(ctx *inventory.Context, slot int, it item.Stack)
	OnInventoryDrop  func(ctx *inventory.Context, slot int, it item.Stack)
}

Plugin describes a unit of behavior. Set only the fields whose events you care about — the rest stay nil and are skipped at dispatch time.

func Plugins

func Plugins() []Plugin

Plugins returns a snapshot of currently registered plugins.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL