Skip to main content

Plugin Template

The fastest way to start building with Gate is to use our official plugin template. It provides a complete, working example with all the boilerplate configured.

What’s Included

The gate-plugin-template repository includes:
  • Pre-configured Go module with Gate dependencies
  • Example plugin code demonstrating common patterns
  • Build configuration with Makefile
  • Docker support for containerized deployments
  • CI/CD examples for automated builds
  • Documentation and code comments

Quick Start

1

Fork or Clone the Template

Visit the gate-plugin-template repository and fork it to your GitHub account, or clone it directly:
git clone https://github.com/minekube/gate-plugin-template.git my-gate-plugin
cd my-gate-plugin
2

Install Dependencies

Download the required Go modules:
go mod download
This will fetch Gate and all its dependencies.
3

Explore the Code

Open plugin.go to see the example plugin implementation. The template includes:
  • Plugin initialization hook
  • Example command registration
  • Event listener examples
  • Common API usage patterns
4

Build and Run

Compile and run your plugin:
go build -o gate-plugin
./gate-plugin
Or use the provided Makefile:
make run
5

Connect and Test

Connect to your proxy using a Minecraft client:
Server Address: localhost:25565
Try the example commands included in the template.

Template Structure

The template is organized as follows:
gate-plugin-template/
├── plugin.go           # Main plugin implementation
├── go.mod             # Go module definition
├── go.sum             # Dependency checksums
├── config.yml         # Gate configuration file
├── Makefile           # Build automation
├── Dockerfile         # Container image definition
├── .github/
│   └── workflows/     # CI/CD workflows
└── README.md          # Documentation

Key Files

plugin.go: Contains your plugin’s main logic
package main

import (
    "context"
    "go.minekube.com/gate/cmd/gate"
    "go.minekube.com/gate/pkg/edition/java/proxy"
)

func main() {
    // Register plugin
    proxy.Plugins = append(proxy.Plugins, proxy.Plugin{
        Name: "MyPlugin",
        Init: func(ctx context.Context, p *proxy.Proxy) error {
            // Your initialization code
            return initPlugin(p)
        },
    })

    // Start Gate
    gate.Execute()
}
go.mod: Declares your module and Gate dependency
module github.com/yourusername/my-gate-plugin

go 1.21

require (
    go.minekube.com/gate v0.62.3
    go.minekube.com/brigodier v0.0.2
    go.minekube.com/common v0.3.0
    github.com/robinbraemer/event v0.1.1
)
config.yml: Gate’s configuration file
config:
  bind: 0.0.0.0:25565
  servers:
    lobby:
      address: localhost:25566
    survival:
      address: localhost:25567
  try:
    - lobby

Customizing the Template

1. Update Module Name

Edit go.mod to reflect your project:
module github.com/yourusername/my-awesome-plugin

go 1.21

require (
    go.minekube.com/gate v0.62.3
    // ... other dependencies
)
Then update imports:
go mod tidy

2. Rename Your Plugin

In plugin.go, change the plugin name:
proxy.Plugins = append(proxy.Plugins, proxy.Plugin{
    Name: "MyAwesomePlugin", // Your plugin name here
    Init: func(ctx context.Context, p *proxy.Proxy) error {
        return initMyPlugin(p)
    },
})

3. Add Your Features

Extend the initialization function to add your custom logic:
func initMyPlugin(p *proxy.Proxy) error {
    // Register commands
    registerCommands(p)
    
    // Subscribe to events
    subscribeToEvents(p)
    
    // Initialize your systems
    setupDatabase()
    
    return nil
}

Common Patterns

The template demonstrates several common patterns:

Command Registration

import (
    "go.minekube.com/brigodier"
    "go.minekube.com/gate/pkg/command"
)

func registerCommands(p *proxy.Proxy) {
    p.Command().Register(
        brigodier.Literal("hello").Executes(
            command.Command(func(c *command.Context) error {
                return c.Source.SendMessage(
                    &component.Text{Content: "Hello from Gate!"},
                )
            }),
        ),
    )
}

Event Subscription

import (
    "github.com/robinbraemer/event"
    "go.minekube.com/gate/pkg/edition/java/proxy"
)

func subscribeToEvents(p *proxy.Proxy) {
    event.Subscribe(p.Event(), 0, onPlayerJoin)
}

func onPlayerJoin(e *proxy.PostLoginEvent) {
    player := e.Player()
    logger.Info("Player joined", "username", player.Username())
}

Accessing Player Data

func showPlayerInfo(p proxy.Player) {
    // Get player details
    username := p.Username()
    uuid := p.ID()
    ping := p.Ping()
    
    // Get current server
    if server := p.CurrentServer(); server != nil {
        serverName := server.Server().ServerInfo().Name()
    }
    
    // Send message
    p.SendMessage(&component.Text{
        Content: fmt.Sprintf("Hello %s!", username),
    })
}

Building for Production

Compile Optimized Binary

CGO_ENABLED=0 go build -ldflags="-s -w" -o gate-plugin
Flags:
  • CGO_ENABLED=0: Disable C dependencies for pure Go binary
  • -ldflags="-s -w": Strip debug info to reduce binary size

Cross-Compile for Linux

From macOS or Windows:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o gate-plugin-linux

Docker Build

The template includes a Dockerfile:
docker build -t my-gate-plugin .
docker run -p 25565:25565 my-gate-plugin

Configuration Management

Environment Variables

Gate supports environment variable overrides:
export GATE_BIND=0.0.0.0:25565
export GATE_VELOCITY_SECRET=your-secret-here
./gate-plugin

Custom Config Path

./gate-plugin --config /path/to/custom-config.yml

Config Validation

Gate validates your configuration on startup and logs any errors or warnings.

Troubleshooting

Build Errors

Solution: Download dependencies first:
go mod download
go mod tidy
Solution: Update your go.mod and download missing packages:
go get -u go.minekube.com/gate@latest
go mod tidy
Solution: Check for config.yml in the working directory:
ls -la config.yml
# If missing, create one from the template

Runtime Issues

Solution: Another process is using port 25565. Either stop it or change the port in config.yml:
config:
  bind: 0.0.0.0:25566  # Use a different port
Solution: Verify backend servers are running and accessible:
# Test connection to backend
telnet localhost 25566
Check your config.yml server addresses are correct.
Solution: Ensure commands are registered before Gate starts:
func Init(ctx context.Context, p *proxy.Proxy) error {
    registerCommands(p)  // Must be in Init function
    return nil
}

Updating Gate Version

To update to the latest Gate version:
go get -u go.minekube.com/gate@latest
go mod tidy
go build
Check the changelog for breaking changes.

Next Steps

Now that you have the template running:

Learn Commands

Register custom commands for your players

Handle Events

React to player actions and server events

View Examples

Study the complete simple-proxy example

API Reference

Explore the full API documentation

Resources

Build docs developers (and LLMs) love