Skip to main content
GRPG uses an event-driven scripting system for creating interactive game content. Scripts are written in Go and registered during server initialization.

Script Types

There are three main types of content scripts:
  1. Object Interaction Scripts - Handle player interactions with objects
  2. NPC Talk Scripts - Handle dialogue with NPCs
  3. NPC Spawning - Place NPCs in the world

Object Interaction Scripts

OnObjInteract

Register an interaction handler for an object using OnObjInteract:
server-go/content/berry_bush.go
package content

import (
	"server/scripts"
	"server/shared"
)

func init() {
	scripts.OnObjInteract(scripts.BERRY_BUSH, func(ctx *scripts.ObjInteractCtx) {
		if ctx.GetObjState() == 0 {
			ctx.SetObjState(1)
			ctx.PlayerInvAdd(scripts.BERRIES)
			ctx.PlayerAddXp(shared.Foraging, 100)

			ctx.AddTimer(100, func() {
				ctx.SetObjState(0)
			})
		}
	})
}

ObjInteractCtx API

The interaction context provides methods for manipulating object state and player data:
GetObjState()
uint8
Returns the current state of the object (0-255)
SetObjState(new uint8)
void
Updates the object state and broadcasts the change to nearby players
PlayerInvAdd(itemId ItemConstant)
void
Adds an item to the player’s inventory and sends an update packet
PlayerAddXp(skill Skill, xpAmount uint32)
void
Grants XP to the player for the specified skill and sends an update packet
AddTimer(ticks uint32, fn func())
void
Schedules a callback to execute after the specified number of game ticks
Object states are synchronized automatically. When you call SetObjState(), all players in the chunk receive an ObjUpdate packet.

NPC Talk Scripts

OnTalkNpc

Register a dialogue handler for an NPC:
server-go/content/test_npc.go
package content

import "server/scripts"

func init() {
	scripts.OnTalkNpc(scripts.TEST, func(ctx *scripts.NpcTalkCtx) {
		ctx.ClearDialogueQueue()

		ctx.TalkPlayer("hello, test")
		ctx.TalkNpc("...")
		ctx.TalkPlayer("C U")

		ctx.StartDialogue()
	})
}

NpcTalkCtx API

ClearDialogueQueue()
void
Clears the player’s dialogue queue and sends a clear talkbox packet
TalkPlayer(msg string)
void
Adds a player dialogue line to the queue
TalkNpc(msg string)
void
Adds an NPC dialogue line to the queue
StartDialogue()
void
Begins playing the dialogue sequence to the player
Dialogue is displayed sequentially. The client advances through the queue as the player presses the interact key.

NPC Spawning

SpawnNpc

Place NPCs in the world during initialization:
server-go/content/test_npc.go
scripts.SpawnNpc(scripts.TEST, 3, 3, 2)
// Spawns TEST NPC at position (3,3) with a wander range of 2 tiles
Parameters:
  • npcId - The NPC type constant
  • x - X coordinate in the world
  • y - Y coordinate in the world
  • wanderRange - Number of tiles the NPC can wander from spawn point
NPCs are spawned during server initialization. The spawn positions are static and cannot be changed at runtime without server restart.

Registration System

All content scripts use the init() function to register handlers:
server-go/scripts/listeners.go
func OnObjInteract(objId ObjConstant, fnc ObjInteractFunc) {
	pendingObjInteracts = append(pendingObjInteracts, PendingObjInteract{
		id: objId,
		fn: fnc,
	})
}

func OnTalkNpc(npcId NpcConstant, fnc NpcTalkFunc) {
	pendingNpcTalks = append(pendingNpcTalks, pendingNpcTalk{
		id: npcId,
		fn: fnc,
	})
}

func SpawnNpc(npcId NpcConstant, x uint32, y uint32, wanderRange uint8) {
	pendingNpcSpawns = append(pendingNpcSpawns, pendingNpcSpawn{
		npcId:       npcId,
		x:           x,
		y:           y,
		wanderRange: wanderRange,
	})
}
The ScriptManager processes these pending registrations during server startup:
  • Object interaction scripts are stored in InteractScripts map
  • NPC talk scripts are stored in NpcTalkScripts map
  • NPC spawns create entries in game.TrackedNpcs

Constants

Content uses type-safe constants for referencing game entities:
server-go/scripts/constants.go
type ObjConstant uint16
type NpcConstant uint16
type ItemConstant uint16

const (
	_ ObjConstant = iota
	BERRY_BUSH
)

const (
	_ NpcConstant = iota
	TEST
)

const (
	_ ItemConstant = iota
	BERRIES
)
These constants should eventually be auto-generated from .gcfg files as part of the data-packer tool.

Next Steps

Objects

Learn about the object system and state management

NPCs

Understand NPC behavior and movement

Build docs developers (and LLMs) love