Knight docs
EN ID
GitHub
← All plugins

Welcome

Smallest complete Go plugin: one native and one hook.

Kind
Go reference
Status
reference implementation
Natives
WelcomeCount WelcomeJoins
Hooks
player::connect

Enable

Add the path to server.plugins (or `plugins` in server.cfg).

knight
server.plugins = ["examples/plugins/welcome"];

Workflow

flowchart LR
  A["plugin.Register in init()"] --> B["Init(api)"]
  B -->|RegisterNative| C["WelcomeCount / WelcomeJoins"]
  B -->|Hook| D["player::connect"]
  D --> E["Log the join"]
  C --> F["Gamemode reads counters"]

Source

examples/plugins/welcome/welcome.go 60 lines
go
// Package welcome is a reference Knight Go plugin.
//
// It shows the two things a plugin can do:
//
//   - expose a native to .sa gamemodes (WelcomeCount)
//   - observe/participate in an event with a hook (player::connect)
//
// Build it into a server by blank-importing this package from a small main:
//
//	import _ "knight/examples/plugins/welcome"
package welcome

import (
	"fmt"

	"knight/pkg/plugin"
)

type welcome struct {
	api   plugin.API
	joins int64
}

func init() { plugin.Register(func() plugin.Plugin { return &welcome{} }) }

func (w *welcome) Info() plugin.Info {
	return plugin.Info{Name: "welcome", Version: "1.0.0", Author: "Knight examples"}
}

func (w *welcome) Init(api plugin.API) error {
	w.api = api
	// Callable from .sa:  let n = WelcomeCount();
	api.RegisterNative("WelcomeCount", w.count)
	// Callable from .sa:  let n = WelcomeJoins();
	api.RegisterNative("WelcomeJoins", w.joinsSoFar)
	// Runs before gamemode handlers thanks to PriorityEarly.
	api.Hook("player::connect", plugin.PriorityEarly, w.onConnect)
	return nil
}

func (w *welcome) onConnect(ctx plugin.Ctx) bool {
	w.joins++
	name, _ := ctx.PlayerName(int(ctx.Int(0)))
	w.api.Log("welcome: %s joined (%d total)", name, w.joins)
	return true // true = keep going; false would veto the event
}

func (w *welcome) count(ctx plugin.Ctx, args []plugin.Value) plugin.Value {
	return plugin.IntV(int64(ctx.PlayerCount()))
}

func (w *welcome) joinsSoFar(ctx plugin.Ctx, args []plugin.Value) plugin.Value {
	return plugin.IntV(w.joins)
}

func (w *welcome) Shutdown() {}

// Format is a helper used by the example tests.
func Format(name string) string { return fmt.Sprintf("Welcome, %s!", name) }