mcrpc

package module
v0.0.0-...-9423a92 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 16 Imported by: 0

README

MCRPC - Minecraft Server Management Protocol Client

CI Go Report Card GoDoc

A Go client library for the Minecraft Server Management Protocol (MSMP), providing JSON-RPC 2.0 over WebSocket support for managing Minecraft Java Edition dedicated servers.

[!Warning]

Most of this project is handled by the AI.

While I try my best to review the full project structure, there may some errors occur.

Features

  • Full Protocol Support: Complete implementation of all MSMP methods
  • Secure Connections: TLS support with client certificates
  • Event Notifications: Real-time event handling for player joins, server status, etc.
  • Type-Safe API: Strongly typed request/response structures
  • Concurrent-Safe: Thread-safe operations for multi-goroutine use

Installation

go get github.com/fi-xz/mcrpc

Quick Start

package main

import (
    "context"
    "crypto/tls"
    "fmt"
    "log"

    "github.com/fi-xz/mcrpc"
)

func main() {
    ctx := context.Background()

    // Load certificate (only if the server requires client authentication)
    cert, err := tls.LoadX509KeyPair("cert.crt", "cert.pem")
    if err != nil {
        log.Fatal(err)
    }

    // Build the client. No I/O happens here, so handlers registered now are
    // guaranteed to be in place before any notification can arrive.
    client := mcrpc.New("localhost:8080", "your-secret",
        mcrpc.WithClientCertificate(cert),
        mcrpc.WithInsecureSkipVerify(), // self-signed certificates only
        mcrpc.WithHandler(mcrpc.Handler{
            OnPlayerJoined: func(player mcrpc.Player) {
                log.Printf("Player joined: %s", player.Name)
            },
        }),
    )

    // Connect. ctx bounds the whole session: cancelling it closes the client.
    if err := client.Start(ctx); err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    // Get server status
    status, err := client.GetServerStatus(ctx)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Server: %s, Players: %d\n", status.Version.Name, len(status.Players))
}

For a plaintext connection, drop the TLS options:

client := mcrpc.New("localhost:8080", "your-secret")

NewHostPort(host, port, secret, opts...) is available when the host and port are held separately.

Lifecycle
Call Effect
New / NewHostPort Builds the value. No connection, no goroutine.
Start(ctx) Dials and begins dispatching. ErrAlreadyStarted if running.
Close() Ends the session. Idempotent, and safe before Start.
Start(ctx) again Reconnects with the same configuration and handler.
IsRunning() Whether a connection is currently held.
DisconnectNotify() Channel closed when the current session ends.

ctx passed to Start bounds the session and is the context handed to every notification callback; cancelling it closes the connection. To bound only the handshake, use WithHandshakeTimeout and pass a longer-lived context to Start.

Server versions

The management API is versioned separately from Minecraft, and it is the API version that protocol behaviour follows:

version, err := client.APIVersion(ctx) // "1.0.0", "3.0.0", …
API Minecraft Notable for this library
1.0.0 1.21.9 Game rule values are strings; keys are camelCase
3.0.0 26.2 Game rule values are native JSON; keys are namespaced. notification/server/activity added
3.1.0 26.3 notification/world/upgrade_* added

Every method and payload shape a server supports can be read from its own OpenRPC document via rpc.discover; APIVersion reads the version field out of it.

API Overview

Server Management
  • GetServerStatus() - Get current server state
  • SaveServer(ctx, flush) - Save world data
  • StopServer(ctx) - Stop the server
  • SendSystemMessage(ctx, message) - Broadcast messages
Player Management
  • GetPlayers(ctx) - List online players
  • KickPlayers(ctx, players...) - Kick players from server
Access Control
  • Allowlist: GetAllowlist, SetAllowlist, AddAllowlist, RemoveAllowlist, ClearAllowlist
  • Bans: GetBanlist, SetBanlist, AddBanlist, RemoveBanlist, ClearBanlist
  • IP Bans: GetIPBanlist, SetIPBanlist, AddIPBanlist, RemoveIPBanlist, ClearIPBanlist
  • Operators: GetOperators, SetOperators, AddOperators, RemoveOperators, ClearOperators

Add*, Remove*, and KickPlayers are variadic, so a single item needs no slice literal. Set* keeps taking a slice, because replacing a whole list is naturally a list operation:

client.AddAllowlist(ctx, mcrpc.PlayerByName("fi_xz"))
client.RemoveIPBanlist(ctx, "1.2.3.4", "5.6.7.8")
client.SetAllowlist(ctx, roster)
Server Settings

All settings support both Get and Set methods:

  • Autosave, Difficulty, MaxPlayers, MOTD
  • GameMode, ViewDistance, SimulationDistance
  • AllowFlight, Allowlist, ForceGameMode
  • SpawnProtectionRadius, PlayerIdleTimeout
  • AcceptTransfers, StatusReplies, and more
Game Rules
  • GetGameRules(ctx) - Get all game rules
  • UpdateGameRule(ctx, rule) - Update a game rule

Game rule values are untyped on the wire, so accessors are provided:

rule, err := client.UpdateGameRule(ctx, mcrpc.BoolRule("minecraft:keep_inventory", true))
if err != nil {
    log.Fatal(err)
}

if enabled, ok := rule.Bool(); ok {
    log.Printf("minecraft:keep_inventory is now %v", enabled)
}

BoolRule, IntRule, and StringRule build updates; Bool(), Int(), and StringValue() read them back, each returning an ok flag.

[!Important]

Game rules changed shape in 1.21.11. Both the key and the value representation differ, verified against live 1.21.9 and 26.2 servers:

1.21.9 – 1.21.10 1.21.11 and later
Key keepInventory minecraft:keep_inventory
Value on the wire "true", "3" (strings) true, 3 (native JSON)

Rules were also renamed to match the "Edit Game Rules" menu, and some had their values inverted, so a key is not always a straight rename.

Bool(), Int(), and StringValue() accept either representation, so reading is version-independent. For writing, build the update from the rule the server sent and the representation is matched for you:

rules, err := client.GetGameRules(ctx)
// ... find the rule you want ...

updated, err := client.UpdateGameRule(ctx, rule.WithBool(true))

WithBool, WithInt, and WithString mirror whatever the server used; UsesStringValues() reports which it is. The standalone BoolRule, IntRule, and StringRule constructors send exactly what you give them, so use those only when you know the server's representation.

Constructing values

Helpers cover the awkward literals:

mcrpc.LiteralMessage("Server restarting in 5 minutes")
mcrpc.TranslatableMessage("chat.type.text", "fi_xz", "hello")

mcrpc.PlayerByName("fi_xz")
mcrpc.PlayerByUUID("a0d8c884-2a79-4c95-8617-a51d27a427ec")

// Ban expiry. Leave Expires empty for a permanent ban.
ban := mcrpc.UserBan{
    Player:  mcrpc.PlayerByName("fi_xz"),
    Reason:  "griefing",
    Expires: mcrpc.BanUntil(time.Now().Add(24 * time.Hour)),
}

if deadline, ok := ban.ExpiresAt(); ok {
    log.Printf("ban lifts at %s", deadline)
}
Error handling

Every method returns errors wrapping *mcrpc.Error, which carries the failing method and the server's JSON-RPC error code:

players, err := client.GetPlayers(ctx)
if err != nil {
    var rpcErr *mcrpc.Error
    if errors.As(err, &rpcErr) {
        log.Printf("%s failed with code %d: %s", rpcErr.Method, rpcErr.Code, rpcErr.Message)
    }
    if errors.Is(err, mcrpc.ErrNotConnected) {
        // the client was never connected, or has been closed
    }
}

The original *jsonrpc2.Error stays reachable through errors.As if you need it.

Tracing the wire

WithTrace reports every JSON-RPC message with its params and result exactly as serialised. Use it to confirm what a struct tag actually produces, what an omitted field looks like on the wire, and what JSON type an untyped value arrives as:

client := mcrpc.New(addr, secret, mcrpc.WithTrace(func(m mcrpc.TraceMessage) {
    log.Print(m)
}))
-> minecraft:allowlist/add #1 {"add":[{"name":"fi_xz","id":""}]}
<- minecraft:allowlist/add #1 [{"name":"fi_xz","id":"a0d8c884-…"}]
<- notify minecraft:notification/allowlist/added [{"name":"fi_xz","id":"a0d8c884-…"}]
-> minecraft:players/kick #2 {"kick":[…]}
<- minecraft:players/kick #2 error -32602 Invalid params

TraceMessage exposes Direction, Method, ID, Notification, Params, Result, ErrorCode, and ErrorMessage; String() produces the lines above. The callback runs on the connection's read and write paths, so it must not block or call back into the client. Trace output should be treated as sensitive.

The integration tests wire this to TEST_TRACE:

TEST_TRACE=1 go test -v -run TestBanlist ./...
Notifications

Callbacks are passed to New as a Handler, so they are in place before the connection exists:

client := mcrpc.New(addr, secret, mcrpc.WithHandler(mcrpc.Handler{
    OnPlayerJoined: func(player mcrpc.Player) {
        log.Printf("Player joined: %s", player.Name)
    },
    OnServerStatus: func(status mcrpc.ServerState) {
        log.Printf("Players online: %d", len(status.Players))
    },
    OnError: func(method string, err error) {
        log.Printf("could not decode %s: %v", method, err)
    },
}))

The Handler is copied into the client, so there is no shared mutable state for the receive goroutine to race against, and the same value can be reused across reconnects or across clients.

OnNotification receives the raw params of every notification, which is the escape hatch when a payload needs handling this package does not provide.

Available handlers:

  • Server: OnServerStarted, OnServerStopping, OnServerSaving, OnServerSaved, OnServerStatus, OnServerActivity (API 3.0.0+, rate limited to one per 30s)
  • Players: OnPlayerJoined, OnPlayerLeft
  • Operators: OnOperatorAdded, OnOperatorRemoved
  • Allowlist: OnAllowlistAdded, OnAllowlistRemoved
  • Bans: OnBanAdded, OnBanRemoved
  • IP Bans: OnIPBanAdded, OnIPBanRemoved
  • Game Rules: OnGameruleUpdated
  • World (API 3.1.0+, Minecraft 26.3): OnWorldUpgradeStarted, OnWorldUpgradeProgress (0–1, rate limited to one per second), OnWorldUpgradeFinished, OnWorldUpgradeFailed. These fire while the server boots, before it finishes coming up, so register them and connect early
  • Catch-all: OnNotification (every notification, with raw params), OnError (a notification whose params could not be decoded)
Reconnecting

The client keeps its configuration and handler across sessions, so reconnecting is Start again:

for {
    if err := client.Start(ctx); err != nil {
        log.Printf("connect failed: %v", err)
    } else {
        <-client.DisconnectNotify()
    }

    select {
    case <-ctx.Done():
        return
    case <-time.After(5 * time.Second):
    }
}

Configuration

Enable management protocol on your server

Modify server.properties:

management-server-enabled=true
management-server-host=0.0.0.0
management-server-port=8080
management-server-secret=your-40-character-secret-here
management-server-tls-enabled=true
management-server-tls-keystore=keystore.p12
management-server-tls-keystore-password=your-password
TLS Certificate

Generate a PKCS12 keystore:

keytool -genkeypair -alias mcrpc -keyalg RSA -keysize 2048 \
  -storetype PKCS12 -keystore keystore.p12 -validity 3650

Testing

Run the test suite:

# Run all tests
go test -v ./...

# Run with race detector
go test -race ./...

# Run with coverage
go test -cover ./...

Requirements

  • Go 1.26.1 or later (see go.mod)
  • Minecraft Java Edition 1.21.9+ with management protocol enabled

Compatibility notes

The API is pre-v1. Connection setup was reworked to remove a data race on notification handlers; the changes below are breaking.

Before Now
Create(ctx, host, port, secret) NewHostPort(host, port, secret) + Start(ctx)
CreateWithTLS(ctx, host, port, secret, &cert, insecure) NewHostPort(host, port, secret, WithClientCertificate(cert), WithInsecureSkipVerify()) + Start(ctx)
MCRPCClient Client
client.OnPlayerJoined = fn WithHandler(Handler{OnPlayerJoined: fn})
client.IsClosed() !client.IsRunning()
client.JSONRPCConn, client.WebsocketConn unexported
AddAllowlist(ctx, []Player{p}) AddAllowlist(ctx, p)

Behavioural changes:

  • The connection is no longer opened by the constructor. New performs no I/O; nothing is dialled until Start. This is what makes handler registration race-free, and it lets the same client reconnect after Close.
  • The context passed to Start bounds the session. Cancelling it closes the connection. Previously the context given to Create only reached notification callbacks and never closed anything, so a short-lived context silently handed every later callback an already-cancelled context.
  • TLS follows the options, not the certificate. WithTLS(nil) connects over wss without a client certificate; previously TLS was only used when a certificate was supplied.
  • Permanent bans omit expires rather than sending an empty string.
  • List parameters serialise as [], never null.

Remaining known issues and their rationale are tracked in docs/ux-proposal.md.

License

MIT License - see LICENSE for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Resources

Documentation

Overview

Package mcrpc provides allowlist management functionality for Minecraft servers.

Package mcrpc provides ban management functionality for Minecraft servers.

Package mcrpc provides a JSON-RPC 2.0 over WebSocket client for managing Minecraft Java Edition servers. It implements the Minecraft Server Management Protocol (MSMP) and supports server management, player management, bans, operators, allowlists, server settings, and real-time notifications.

A client is built, then started:

client := mcrpc.New("localhost:8080", secret,
    mcrpc.WithTLS(nil),
    mcrpc.WithHandler(mcrpc.Handler{
        OnPlayerJoined: func(p mcrpc.Player) { log.Printf("%s joined", p.Name) },
    }),
)

if err := client.Start(ctx); err != nil {
    return err
}
defer client.Close()

players, err := client.GetPlayers(ctx)

New performs no I/O, so notification handlers are in place before the connection exists and can never be missed or raced against. The context given to Start bounds the session: cancelling it closes the connection.

Package mcrpc provides game rule management functionality for Minecraft servers.

Package mcrpc provides notification handling functionality for Minecraft servers.

Package mcrpc provides operator management functionality for Minecraft servers.

Package mcrpc provides player management functionality for Minecraft servers.

Package mcrpc provides server management functionality for Minecraft servers.

Package mcrpc provides server settings management functionality for Minecraft servers.

Package mcrpc re-exports the protocol data types so that callers never need to reference the internal packages that define them.

Index

Constants

View Source
const BanTimeFormat = types.BanTimeFormat

BanTimeFormat is the layout the management protocol uses for ban expiry timestamps.

View Source
const DefaultHandshakeTimeout = 10 * time.Second

DefaultHandshakeTimeout bounds the WebSocket handshake performed by Start unless WithHandshakeTimeout says otherwise.

Variables

View Source
var ErrAlreadyStarted = errors.New("mcrpc: client is already started")

ErrAlreadyStarted is returned by Start when the client already holds a connection. Close it before starting a new session.

View Source
var ErrNotConnected = errors.New("mcrpc: client is not connected")

ErrNotConnected is returned when a call is attempted on a client that has not been started, or whose session has ended.

Functions

func BanUntil

func BanUntil(t time.Time) string

BanUntil formats t as a ban expiry timestamp. Pass the result as the Expires field of a UserBan or IPBan; leave that field empty for a permanent ban.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client manages a Minecraft server over JSON-RPC 2.0 on a WebSocket.

New only builds the value; nothing is dialled and no goroutine runs until Start. That split is what makes notification handlers safe to register: WithHandler is applied before any receive goroutine exists.

A Client is safe for concurrent use, and can be restarted: after Close, a further Start dials again with the same configuration and handler.

func New

func New(addr, secret string, opts ...Option) *Client

New builds a client for the management server at addr, a "host:port" pair. It performs no I/O; call Start to connect.

secret is the value of management-server-secret in server.properties. Without any option the connection is plaintext ws; see WithTLS.

func NewHostPort

func NewHostPort(host string, port int, secret string, opts ...Option) *Client

NewHostPort is New for callers that hold the host and port separately.

func (*Client) APIVersion

func (c *Client) APIVersion(ctx context.Context) (string, error)

APIVersion returns the version of the management API the server implements, as advertised by rpc.discover.

This is the version protocol behaviour is keyed on, not the Minecraft version: 1.0.0 ships with 1.21.9, 3.0.0 with 26.2, and 3.1.0 with 26.3, which is what added the world upgrade notifications. Game rule values, for example, are strings before 3.0.0 and native JSON types from 3.0.0 on.

func (*Client) AddAllowlist

func (c *Client) AddAllowlist(ctx context.Context, add ...Player) ([]Player, error)

AddAllowlist adds the specified players to the allowlist.

func (*Client) AddBanlist

func (c *Client) AddBanlist(ctx context.Context, add ...UserBan) ([]UserBan, error)

AddBanlist adds the specified bans to the ban list.

func (*Client) AddIPBanlist

func (c *Client) AddIPBanlist(ctx context.Context, add ...IncomingIPBan) ([]IPBan, error)

AddIPBanlist adds the specified IP bans to the ban list.

func (*Client) AddOperators

func (c *Client) AddOperators(ctx context.Context, add ...Operator) ([]Operator, error)

AddOperators adds the specified players as operators.

func (*Client) ClearAllowlist

func (c *Client) ClearAllowlist(ctx context.Context) ([]Player, error)

ClearAllowlist removes all players from the allowlist.

func (*Client) ClearBanlist

func (c *Client) ClearBanlist(ctx context.Context) ([]UserBan, error)

ClearBanlist removes all bans from the ban list.

func (*Client) ClearIPBanlist

func (c *Client) ClearIPBanlist(ctx context.Context) ([]IPBan, error)

ClearIPBanlist removes all IP bans from the ban list.

func (*Client) ClearOperators

func (c *Client) ClearOperators(ctx context.Context) ([]Operator, error)

ClearOperators removes all players from the operator list.

func (*Client) Close

func (c *Client) Close() error

Close ends the session and releases the connection. It is safe to call multiple times and on a client that was never started, and it does not prevent a later Start from reconnecting.

func (*Client) DisconnectNotify

func (c *Client) DisconnectNotify() <-chan struct{}

DisconnectNotify returns a channel closed when the current session ends.

The channel belongs to one session: after a Close and a further Start, call this again to observe the new one. For a client that is not running, the returned channel is already closed.

func (*Client) GetAcceptTransfers

func (c *Client) GetAcceptTransfers(ctx context.Context) (bool, error)

GetAcceptTransfers retrieves whether the server accepts player transfers.

func (*Client) GetAllowFlight

func (c *Client) GetAllowFlight(ctx context.Context) (bool, error)

GetAllowFlight retrieves whether flight is allowed in Survival mode.

func (*Client) GetAllowlist

func (c *Client) GetAllowlist(ctx context.Context) ([]Player, error)

GetAllowlist retrieves the current allowlist of players.

func (*Client) GetAutosaveEnabled

func (c *Client) GetAutosaveEnabled(ctx context.Context) (bool, error)

GetAutosaveEnabled retrieves whether automatic world saving is enabled.

func (*Client) GetBanlist

func (c *Client) GetBanlist(ctx context.Context) ([]UserBan, error)

GetBanlist retrieves the current list of banned players.

func (*Client) GetDifficulty

func (c *Client) GetDifficulty(ctx context.Context) (string, error)

GetDifficulty retrieves the current difficulty level of the server.

func (*Client) GetEnforceAllowlist

func (c *Client) GetEnforceAllowlist(ctx context.Context) (bool, error)

GetEnforceAllowlist retrieves whether allowlist enforcement is enabled.

func (*Client) GetEntityBroadcastRange

func (c *Client) GetEntityBroadcastRange(ctx context.Context) (int, error)

GetEntityBroadcastRange retrieves the entity broadcast range percentage.

func (*Client) GetForceGameMode

func (c *Client) GetForceGameMode(ctx context.Context) (bool, error)

GetForceGameMode retrieves whether players are forced to use the default game mode.

func (*Client) GetGameMode

func (c *Client) GetGameMode(ctx context.Context) (string, error)

GetGameMode retrieves the server's default game mode.

func (*Client) GetGameRules

func (c *Client) GetGameRules(ctx context.Context) ([]TypedGameRule, error)

GetGameRules retrieves all game rules and their current values.

func (*Client) GetHideOnlinePlayers

func (c *Client) GetHideOnlinePlayers(ctx context.Context) (bool, error)

GetHideOnlinePlayers retrieves whether online player info is hidden from status queries.

func (*Client) GetIPBanlist

func (c *Client) GetIPBanlist(ctx context.Context) ([]IPBan, error)

GetIPBanlist retrieves the current list of banned IP addresses.

func (*Client) GetMOTD

func (c *Client) GetMOTD(ctx context.Context) (string, error)

GetMOTD retrieves the server's message of the day.

func (*Client) GetMaxPlayers

func (c *Client) GetMaxPlayers(ctx context.Context) (int, error)

GetMaxPlayers retrieves the maximum number of players allowed on the server.

func (*Client) GetOperatorPermissionLevel

func (c *Client) GetOperatorPermissionLevel(ctx context.Context) (int, error)

GetOperatorPermissionLevel retrieves the operator permission level.

func (*Client) GetOperators

func (c *Client) GetOperators(ctx context.Context) ([]Operator, error)

GetOperators retrieves the current list of operators.

func (*Client) GetPauseWhenEmptySeconds

func (c *Client) GetPauseWhenEmptySeconds(ctx context.Context) (int, error)

GetPauseWhenEmptySeconds retrieves the pause when empty timeout in seconds.

func (*Client) GetPlayerIdleTimeout

func (c *Client) GetPlayerIdleTimeout(ctx context.Context) (int, error)

GetPlayerIdleTimeout retrieves the player idle timeout in seconds.

func (*Client) GetPlayers

func (c *Client) GetPlayers(ctx context.Context) ([]Player, error)

GetPlayers retrieves the list of currently online players.

func (*Client) GetServerStatus

func (c *Client) GetServerStatus(ctx context.Context) (ServerState, error)

GetServerStatus retrieves the current status of the server including online players and version information.

func (*Client) GetSimulationDistance

func (c *Client) GetSimulationDistance(ctx context.Context) (int, error)

GetSimulationDistance retrieves the simulation distance in chunks.

func (*Client) GetSpawnProtectionRadius

func (c *Client) GetSpawnProtectionRadius(ctx context.Context) (int, error)

GetSpawnProtectionRadius retrieves the spawn protection radius in blocks.

func (*Client) GetStatusHeartbeatInterval

func (c *Client) GetStatusHeartbeatInterval(ctx context.Context) (int, error)

GetStatusHeartbeatInterval retrieves the status heartbeat interval in seconds.

func (*Client) GetStatusReplies

func (c *Client) GetStatusReplies(ctx context.Context) (bool, error)

GetStatusReplies retrieves whether the server responds to status requests.

func (*Client) GetUseAllowlist

func (c *Client) GetUseAllowlist(ctx context.Context) (bool, error)

GetUseAllowlist retrieves whether the allowlist is enabled.

func (*Client) GetViewDistance

func (c *Client) GetViewDistance(ctx context.Context) (int, error)

GetViewDistance retrieves the view distance in chunks.

func (*Client) IsRunning

func (c *Client) IsRunning() bool

IsRunning reports whether the client currently holds a live connection.

A session that has dropped reports false straight away, without waiting for the watchdog to clear the client's state.

func (*Client) KickPlayers

func (c *Client) KickPlayers(ctx context.Context, kick ...KickPlayer) ([]Player, error)

KickPlayers kicks the specified players from the server with custom messages.

func (*Client) RemoveAllowlist

func (c *Client) RemoveAllowlist(ctx context.Context, remove ...Player) ([]Player, error)

RemoveAllowlist removes the specified players from the allowlist.

func (*Client) RemoveBanlist

func (c *Client) RemoveBanlist(ctx context.Context, remove ...Player) ([]UserBan, error)

RemoveBanlist removes the specified players from the ban list.

func (*Client) RemoveIPBanlist

func (c *Client) RemoveIPBanlist(ctx context.Context, ip ...string) ([]IPBan, error)

RemoveIPBanlist removes the specified IP addresses from the ban list.

func (*Client) RemoveOperators

func (c *Client) RemoveOperators(ctx context.Context, remove ...Player) ([]Operator, error)

RemoveOperators removes the specified players from the operator list.

func (*Client) SaveServer

func (c *Client) SaveServer(ctx context.Context, flush bool) (bool, error)

SaveServer saves the current server state. If flush is true, all pending changes are flushed to disk.

func (*Client) SendSystemMessage

func (c *Client) SendSystemMessage(ctx context.Context, message SystemMessage) (bool, error)

SendSystemMessage sends a system message to the specified players on the server.

func (*Client) SetAcceptTransfers

func (c *Client) SetAcceptTransfers(ctx context.Context, accept bool) (bool, error)

SetAcceptTransfers sets whether the server accepts player transfers.

func (*Client) SetAllowFlight

func (c *Client) SetAllowFlight(ctx context.Context, allowed bool) (bool, error)

SetAllowFlight sets whether flight is allowed in Survival mode.

func (*Client) SetAllowlist

func (c *Client) SetAllowlist(ctx context.Context, players []Player) ([]Player, error)

SetAllowlist sets the allowlist to the specified list of players, replacing the existing list.

func (*Client) SetAutosaveEnabled

func (c *Client) SetAutosaveEnabled(ctx context.Context, enable bool) (bool, error)

SetAutosaveEnabled enables or disables automatic world saving.

func (*Client) SetBanlist

func (c *Client) SetBanlist(ctx context.Context, bans []UserBan) ([]UserBan, error)

SetBanlist sets the ban list to the specified list of bans, replacing the existing list.

func (*Client) SetDifficulty

func (c *Client) SetDifficulty(ctx context.Context, difficulty string) (string, error)

SetDifficulty sets the difficulty level of the server (peaceful, easy, normal, hard).

func (*Client) SetEnforceAllowlist

func (c *Client) SetEnforceAllowlist(ctx context.Context, enforce bool) (bool, error)

SetEnforceAllowlist enables or disables allowlist enforcement.

func (*Client) SetEntityBroadcastRange

func (c *Client) SetEntityBroadcastRange(ctx context.Context, percentagePoints int) (int, error)

SetEntityBroadcastRange sets the entity broadcast range percentage.

func (*Client) SetForceGameMode

func (c *Client) SetForceGameMode(ctx context.Context, force bool) (bool, error)

SetForceGameMode sets whether players are forced to use the default game mode.

func (*Client) SetGameMode

func (c *Client) SetGameMode(ctx context.Context, mode string) (string, error)

SetGameMode sets the server's default game mode (creative, survival, spectator, adventure).

func (*Client) SetHideOnlinePlayers

func (c *Client) SetHideOnlinePlayers(ctx context.Context, hide bool) (bool, error)

SetHideOnlinePlayers sets whether online player info is hidden from status queries.

func (*Client) SetIPBanlist

func (c *Client) SetIPBanlist(ctx context.Context, banlist []IPBan) ([]IPBan, error)

SetIPBanlist sets the IP ban list to the specified list, replacing the existing list.

func (*Client) SetMOTD

func (c *Client) SetMOTD(ctx context.Context, message string) (string, error)

SetMOTD sets the server's message of the day.

func (*Client) SetMaxPlayers

func (c *Client) SetMaxPlayers(ctx context.Context, limit int) (int, error)

SetMaxPlayers sets the maximum number of players allowed on the server.

func (*Client) SetOperatorPermissionLevel

func (c *Client) SetOperatorPermissionLevel(ctx context.Context, level int) (int, error)

SetOperatorPermissionLevel sets the operator permission level.

func (*Client) SetOperators

func (c *Client) SetOperators(ctx context.Context, operators []Operator) ([]Operator, error)

SetOperators sets the operator list to the specified list, replacing the existing list.

func (*Client) SetPauseWhenEmptySeconds

func (c *Client) SetPauseWhenEmptySeconds(ctx context.Context, seconds int) (int, error)

SetPauseWhenEmptySeconds sets the pause when empty timeout in seconds.

func (*Client) SetPlayerIdleTimeout

func (c *Client) SetPlayerIdleTimeout(ctx context.Context, seconds int) (int, error)

SetPlayerIdleTimeout sets the player idle timeout in seconds.

func (*Client) SetSimulationDistance

func (c *Client) SetSimulationDistance(ctx context.Context, distance int) (int, error)

SetSimulationDistance sets the simulation distance in chunks.

func (*Client) SetSpawnProtectionRadius

func (c *Client) SetSpawnProtectionRadius(ctx context.Context, radius int) (int, error)

SetSpawnProtectionRadius sets the spawn protection radius in blocks.

func (*Client) SetStatusHeartbeatInterval

func (c *Client) SetStatusHeartbeatInterval(ctx context.Context, seconds int) (int, error)

SetStatusHeartbeatInterval sets the status heartbeat interval in seconds.

func (*Client) SetStatusReplies

func (c *Client) SetStatusReplies(ctx context.Context, enable bool) (bool, error)

SetStatusReplies sets whether the server responds to status requests.

func (*Client) SetUseAllowlist

func (c *Client) SetUseAllowlist(ctx context.Context, use bool) (bool, error)

SetUseAllowlist enables or disables the allowlist.

func (*Client) SetViewDistance

func (c *Client) SetViewDistance(ctx context.Context, distance int) (int, error)

SetViewDistance sets the view distance in chunks.

func (*Client) Start

func (c *Client) Start(ctx context.Context) error

Start dials the server and begins dispatching notifications. It returns ErrAlreadyStarted if the client is already connected.

ctx bounds the whole session, not just the handshake: cancelling it closes the connection. To bound only the handshake use WithHandshakeTimeout, and pass a context that outlives the session here.

func (*Client) StopServer

func (c *Client) StopServer(ctx context.Context) (bool, error)

StopServer stops the Minecraft server.

func (*Client) UpdateGameRule

func (c *Client) UpdateGameRule(ctx context.Context, gamerule UntypedGameRule) (TypedGameRule, error)

UpdateGameRule updates the value of a specific game rule.

type Error

type Error struct {
	// Method is the JSON-RPC method that failed.
	Method string
	// Code is the JSON-RPC error code, or 0 if the call failed before the
	// server produced a response (transport errors, closed connection).
	Code int64
	// Message is the error message reported by the server, if any.
	Message string
	// Data is the optional payload the server attached to the error.
	Data *json.RawMessage
	// contains filtered or unexported fields
}

Error describes a failed remote call. Every error returned by a Client method wraps the underlying cause, so errors.Is and errors.As both work:

var rpcErr *mcrpc.Error
if errors.As(err, &rpcErr) && rpcErr.Code == -32602 {
    // the server rejected the parameters
}

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying cause, exposing it to errors.Is and errors.As.

type Handler

type Handler struct {
	// OnNotification is called for every notification, before any specific
	// callback below. It receives the raw params, which are nil if the
	// notification carried none.
	OnNotification func(method string, params json.RawMessage)

	// OnError is called when a notification arrives but its params cannot be
	// decoded into the expected type. Without it such notifications are
	// dropped silently.
	OnError func(method string, err error)

	// Server notifications
	OnServerStarted  func()
	OnServerStopping func()
	OnServerSaving   func()
	OnServerSaved    func()
	OnServerStatus   func(status ServerState)
	OnServerActivity func()

	// Player notifications
	OnPlayerJoined func(player Player)
	OnPlayerLeft   func(player Player)

	// Operator notifications
	OnOperatorAdded   func(operator Operator)
	OnOperatorRemoved func(operator Operator)

	// Allowlist notifications
	OnAllowlistAdded   func(player Player)
	OnAllowlistRemoved func(player Player)

	// Ban notifications
	OnBanAdded   func(ban UserBan)
	OnBanRemoved func(player Player)

	// IP ban notifications
	OnIPBanAdded   func(ban IPBan)
	OnIPBanRemoved func(ip string)

	// Gamerule notifications
	OnGameruleUpdated func(gamerule TypedGameRule)

	// World notifications
	OnWorldUpgradeStarted  func()
	OnWorldUpgradeProgress func(progress float64)
	OnWorldUpgradeFinished func()
	OnWorldUpgradeFailed   func(reason string)
}

Handler is the set of callbacks invoked for notifications pushed by the server. Every field is optional; a nil callback means the notification is ignored.

A Handler is passed to New via WithHandler and copied into the client, so mutating your own copy afterwards has no effect on a running client. This is deliberate: the connection's receive goroutine reads these callbacks concurrently, and copying them once at construction keeps that read race-free.

The context passed to a callback is the one given to Start. It is cancelled when the session ends, so a callback that makes further calls should pass it along and expect cancellation.

type IPBan

type IPBan = types.IPBan

IPBan is an alias for types.IPBan, representing a banned IP address.

type IncomingIPBan

type IncomingIPBan = types.IncomingIPBan

IncomingIPBan is an alias for types.IncomingIPBan, representing an incoming IP ban with player information.

type KickPlayer

type KickPlayer = types.KickPlayer

KickPlayer is an alias for types.KickPlayer, representing a player to be kicked with a message.

type Message

type Message = types.Message

Message is an alias for types.Message, representing a translatable or literal message that can be sent to players.

func LiteralMessage

func LiteralMessage(text string) Message

LiteralMessage builds a message carrying plain text.

func TranslatableMessage

func TranslatableMessage(key string, params ...string) Message

TranslatableMessage builds a message the client renders from a translation key, substituting params in order.

type Operator

type Operator = types.Operator

Operator is an alias for types.Operator, representing a server operator.

type Option

type Option func(*Client)

An Option configures a Client. Options are applied by New and are order-independent: the TLS settings they touch are combined into a single configuration when Start dials.

func WithClientCertificate

func WithClientCertificate(cert tls.Certificate) Option

WithClientCertificate makes the client connect over wss and present cert for client certificate authentication. It implies WithTLS.

func WithHandler

func WithHandler(h Handler) Option

WithHandler registers the callbacks invoked for server notifications. The handler is copied, so it must be complete at construction time; see Handler for why.

func WithHandshakeTimeout

func WithHandshakeTimeout(d time.Duration) Option

WithHandshakeTimeout caps how long Start waits for the WebSocket handshake. A non-positive duration removes the cap, leaving the context passed to Start as the only bound. Defaults to DefaultHandshakeTimeout.

func WithInsecureSkipVerify

func WithInsecureSkipVerify() Option

WithInsecureSkipVerify disables verification of the server's certificate and implies WithTLS.

This makes the connection vulnerable to interception: the client will accept any certificate the server offers, including one presented by an attacker. Use it only against servers with self-signed certificates on a network you control.

func WithTLS

func WithTLS(cfg *tls.Config) Option

WithTLS makes the client connect over wss using cfg. A nil cfg selects TLS with default settings, which is what a server that presents a certificate but does not require client authentication needs.

cfg is cloned when the option is applied, so later changes to your copy do not affect the client. That matters beyond tidiness: without it a config shared with something else could turn InsecureSkipVerify on after the client was built, and every dial from then on — including reconnects — would follow.

func WithTrace

func WithTrace(trace func(TraceMessage)) Option

WithTrace reports every JSON-RPC message the client sends and receives, with params and results exactly as they were serialised.

This is a diagnostic aid for confirming what the client puts on the wire and what the server sends back — struct tags, omitted fields, and the JSON types of untyped values. It is called from the connection's read and write paths, so it must not block or call back into the client.

Params may contain the server secret if a future method carries one; treat trace output as sensitive.

type Player

type Player = types.Player

Player is an alias for types.Player, representing a Minecraft player.

func PlayerByName

func PlayerByName(name string) Player

PlayerByName identifies a player by username, for calls where the server resolves the UUID itself.

func PlayerByUUID

func PlayerByUUID(uuid string) Player

PlayerByUUID identifies a player by UUID, for calls where the username is unknown or may have changed.

type ServerState

type ServerState = types.ServerState

ServerState is an alias for types.ServerState, representing the current state of the server.

type SystemMessage

type SystemMessage = types.SystemMessage

SystemMessage is an alias for types.SystemMessage, representing a message broadcast to a set of players.

type TraceDirection

type TraceDirection int

TraceDirection reports which way a traced message travelled.

const (
	// TraceSent marks a message the client wrote to the server.
	TraceSent TraceDirection = iota
	// TraceReceived marks a message the client read from the server.
	TraceReceived
)

func (TraceDirection) String

func (d TraceDirection) String() string

String renders the direction as an arrow, for log output.

type TraceMessage

type TraceMessage struct {
	// Direction is TraceSent or TraceReceived.
	Direction TraceDirection

	// Method names the call or notification. It is empty for a response,
	// unless the originating request is still known, in which case it names
	// that request's method.
	Method string

	// ID is the JSON-RPC request id, empty for a notification.
	ID string

	// Notification reports whether this message expects no response.
	Notification bool

	// Params is the request payload as sent or received, nil when absent.
	Params json.RawMessage

	// Result is the response payload, nil for requests and for error
	// responses.
	Result json.RawMessage

	// ErrorCode and ErrorMessage describe an error response. ErrorCode is 0
	// when the message is not an error.
	ErrorCode    int64
	ErrorMessage string
}

TraceMessage is one JSON-RPC message observed on the connection, carrying the params and result exactly as they were serialised. It is intended for diagnosing protocol mismatches: what a struct tag actually produces, and what JSON type a field actually arrives as.

func (TraceMessage) IsError

func (m TraceMessage) IsError() bool

IsError reports whether the message is an error response.

func (TraceMessage) String

func (m TraceMessage) String() string

String renders the message as one line, suitable for passing straight to a logger:

-> minecraft:allowlist/add #3 {"add":[{"name":"fi_xz","id":""}]}
<- #3 [{"name":"fi_xz","id":"a0d8c884-..."}]
<- notify minecraft:notification/players/joined {"name":"fi_xz",...}

type TypedGameRule

type TypedGameRule = types.TypedGameRule

TypedGameRule is an alias for types.TypedGameRule, representing a game rule with a typed value.

type UntypedGameRule

type UntypedGameRule = types.UntypedGameRule

UntypedGameRule is an alias for types.UntypedGameRule, representing a game rule value whose type is not declared.

func BoolRule

func BoolRule(key string, value bool) UntypedGameRule

BoolRule builds a game rule update carrying a boolean value.

func IntRule

func IntRule(key string, value int) UntypedGameRule

IntRule builds a game rule update carrying an integer value.

func StringRule

func StringRule(key, value string) UntypedGameRule

StringRule builds a game rule update carrying a string value.

type UserBan

type UserBan = types.UserBan

UserBan is an alias for types.UserBan, representing a banned player.

type Version

type Version = types.Version

Version is an alias for types.Version, representing the server version information.

Directories

Path Synopsis
internal
protocol
Package protocol contains request parameter types for Minecraft Server Management Protocol methods.
Package protocol contains request parameter types for Minecraft Server Management Protocol methods.
types
Package types contains data types used by the Minecraft Server Management Protocol.
Package types contains data types used by the Minecraft Server Management Protocol.

Jump to

Keyboard shortcuts

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