grid

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package grid is the runtime entity manager layered on top of kit/spatial: cell-bucketed objects, on-demand loading driven by observer positions, idle-cell unloading, phase-mask filtering, and a visitor/Notifier pattern for region operations (visibility, area-of-effect, broadcast).

Layering vs kit/spatial:

  • kit/spatial answers "which objects intersect this region" (pure data structures).
  • kit/game/grid answers "which subset of the world is loaded", "visit every loaded object in this region with phase filtering", "unload cells no observer is watching".

Use cases: persistent open zones, MMO-shape worlds, phased content (story progression, instanced layers over the same map). Per the architectural invariants, the package never imports kit/unreal/* or project services — DB/content-pack lookups happen behind the caller-supplied Loader[T] interface.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrCellNotLoaded   = errors.New("grid: cell not loaded")
	ErrUnknownEntity   = errors.New("grid: unknown entity id")
	ErrUnknownObserver = errors.New("grid: unknown observer id")
)

Errors surfaced by the grid.

Functions

func Match

func Match(obj, query Phase) bool

Match reports whether an object with phase `obj` should be included in a query carrying mask `query`. PhaseAny (0) on either side is a wildcard: a PhaseAny object is visible to every query, and a PhaseAny query sees every object.

Types

type AOENotifier

type AOENotifier[T Locatable] struct {
	Center geometry.Vec3
	Apply  func(item T, distance float32)
}

AOENotifier applies a damage / heal / status function to each object in range. Distance is supplied so the function can falloff.

func (AOENotifier[T]) OnDone

func (a AOENotifier[T]) OnDone()

OnDone implements Notifier.

func (AOENotifier[T]) OnVisit

func (a AOENotifier[T]) OnVisit(_ GridKey, item T)

OnVisit implements Notifier.

type Config

type Config[T Locatable] struct {
	// CellSize is the edge length, in world units, of one cell.
	CellSize float32
	// Loader supplies on-demand cell contents. Required.
	Loader Loader[T]
	// Unload controls cell eviction. Zero IdleDuration disables idle
	// unload (cells stay loaded once activated).
	Unload UnloadPolicy
	// Spatial is the backing spatial index used by Visit*. Required.
	Spatial spatial.Index[T]
	// Clock supplies the current time; defaults to time.Now.
	Clock func() time.Time
}

Config configures a Grid.

type Grid

type Grid[T Locatable] struct {
	// contains filtered or unexported fields
}

Grid is the cell-bucketed entity manager. Safe for concurrent use.

func New

func New[T Locatable](cfg Config[T]) *Grid[T]

New constructs a Grid from a Config.

func (*Grid[T]) AddObserver

func (g *Grid[T]) AddObserver(ctx context.Context, id ObserverID, pos geometry.Vec3, phase Phase) error

AddObserver registers an observer and triggers load of all cells within ObserverRange.

func (*Grid[T]) EnsureLoaded

func (g *Grid[T]) EnsureLoaded(ctx context.Context, key GridKey) error

EnsureLoaded force-loads a cell. Useful for tests and warming.

func (*Grid[T]) Insert

func (g *Grid[T]) Insert(ctx context.Context, id uint64, item T) error

Insert places an item in the grid. The cell is loaded if not already. Caller-supplied id must be unique across all Insert calls.

func (*Grid[T]) LoadedKeys

func (g *Grid[T]) LoadedKeys() []GridKey

LoadedKeys returns the set of currently-loaded cell keys. Order is unspecified.

func (*Grid[T]) Move

func (g *Grid[T]) Move(ctx context.Context, id uint64, item T) error

Move updates an item's position. If it crosses a cell boundary the destination cell is loaded.

func (*Grid[T]) MoveObserver

func (g *Grid[T]) MoveObserver(ctx context.Context, id ObserverID, pos geometry.Vec3, phase Phase) error

MoveObserver updates an observer's position. Newly-overlapping cells are loaded; previously-overlapping cells are not unloaded eagerly — idle unload sweeps handle that.

func (*Grid[T]) Remove

func (g *Grid[T]) Remove(id uint64) error

Remove drops an item. The owning cell stays loaded.

func (*Grid[T]) RemoveObserver

func (g *Grid[T]) RemoveObserver(id ObserverID)

RemoveObserver drops an observer. The cells they were keeping warm fall under idle unload.

func (*Grid[T]) Size

func (g *Grid[T]) Size() int

Size returns the total number of entities currently in the grid.

func (*Grid[T]) SweepIdle

func (g *Grid[T]) SweepIdle(ctx context.Context) (int, error)

SweepIdle unloads cells with no observer within ObserverRange that have been untouched for IdleDuration. Returns the number of cells unloaded. Callers typically invoke this from a periodic ticker.

func (*Grid[T]) Unload

func (g *Grid[T]) Unload(ctx context.Context, key GridKey) error

Unload force-evicts a cell, calling Loader.Save with its current items and removing them from the grid and spatial index.

func (*Grid[T]) VisitAll

func (g *Grid[T]) VisitAll(phase Phase, n Notifier[T])

VisitAll walks every phase-matching object in every loaded cell. Expensive; intended for global events (weather, day/night) rather than per-tick use.

func (*Grid[T]) VisitCell

func (g *Grid[T]) VisitCell(key GridKey, phase Phase, n Notifier[T])

VisitCell walks every phase-matching object in a single loaded cell. If the cell isn't loaded the notifier sees no items but OnDone still fires.

func (*Grid[T]) VisitRange

func (g *Grid[T]) VisitRange(center geometry.Vec3, radius float32, phase Phase, n Notifier[T])

VisitRange walks every loaded cell that intersects a sphere of `radius` around `center`, invokes `n.OnVisit` for each phase-matching object inside the sphere, then calls `n.OnDone`.

type GridKey

type GridKey struct {
	X, Z int32
}

GridKey is a 2D cell coordinate (x, z plane). The y axis is ignored for cell bucketing — height changes don't move an object between cells.

type Loader

type Loader[T any] interface {
	Load(ctx context.Context, key GridKey) ([]T, error)
	Save(ctx context.Context, key GridKey, items []T) error
}

Loader is the seam between the grid and the project's persistence / content layer. Load is invoked when a cell is first activated; Save (optional, may no-op) is invoked when a cell is unloaded so the caller can checkpoint any per-cell state it cares about.

type LoaderFunc

type LoaderFunc[T any] struct {
	LoadFn func(ctx context.Context, key GridKey) ([]T, error)
	SaveFn func(ctx context.Context, key GridKey, items []T) error
}

LoaderFunc adapts a pair of functions to the Loader interface. Use when the save side is a no-op.

func (LoaderFunc[T]) Load

func (f LoaderFunc[T]) Load(ctx context.Context, key GridKey) ([]T, error)

Load implements Loader.

func (LoaderFunc[T]) Save

func (f LoaderFunc[T]) Save(ctx context.Context, key GridKey, items []T) error

Save implements Loader.

type Locatable

type Locatable interface {
	spatial.Locatable
	Phaseable
}

Locatable is the union the grid needs: spatial.Locatable (for the backing index) + Phaseable (for filtering).

type MessageNotifier

type MessageNotifier[T Locatable, M any] struct {
	Msg  M
	Send func(item T, msg M)
}

MessageNotifier broadcasts a typed message to each object in range (sound propagation, chat, party events).

func (MessageNotifier[T, M]) OnDone

func (m MessageNotifier[T, M]) OnDone()

OnDone implements Notifier.

func (MessageNotifier[T, M]) OnVisit

func (m MessageNotifier[T, M]) OnVisit(_ GridKey, item T)

OnVisit implements Notifier.

type Notifier

type Notifier[T any] interface {
	OnVisit(cell GridKey, item T)
	OnDone()
}

Notifier is a visitor invoked once per object the grid walks during a Visit* operation. OnDone fires after the walk completes, even if no objects were visited.

type NotifierFunc

type NotifierFunc[T any] func(cell GridKey, item T)

NotifierFunc adapts a function to the Notifier interface; OnDone is a no-op.

func (NotifierFunc[T]) OnDone

func (f NotifierFunc[T]) OnDone()

OnDone implements Notifier.

func (NotifierFunc[T]) OnVisit

func (f NotifierFunc[T]) OnVisit(cell GridKey, item T)

OnVisit implements Notifier.

type ObserverID

type ObserverID uint64

ObserverID identifies an observer (typically a player). Observers drive cell load/unload via their position.

type Phase

type Phase uint32

Phase is a bitmask used to segregate objects into instanced layers. The reserved value 0 means ANY — objects in phase 0 are visible to every query regardless of mask. Consumers define their own bit assignments (e.g. story chapters, instanced battlegrounds).

const PhaseAny Phase = 0

PhaseAny is the reserved bit value visible to all queries.

type Phaseable

type Phaseable interface {
	// Phase returns the bitmask this object belongs to. PhaseAny (0)
	// means visible to every query.
	Phase() Phase
}

Phaseable is implemented by any value the grid manages.

type UnloadPolicy

type UnloadPolicy struct {
	// IdleDuration: how long a cell must be unobserved before unload.
	// Zero disables idle unload.
	IdleDuration time.Duration
	// ObserverRange: distance within which an observer keeps surrounding
	// cells "observed" (loaded). Must be > 0.
	ObserverRange float32
}

UnloadPolicy controls when a cell becomes eligible for unload.

type VisibilityNotifier

type VisibilityNotifier[T Locatable] struct {
	Observer ObserverID
	Send     func(observer ObserverID, item T)
}

VisibilityNotifier is the canonical "tell each observer about each nearby object" visitor. Pair with VisitRange to drive client-side entity creation.

func (VisibilityNotifier[T]) OnDone

func (v VisibilityNotifier[T]) OnDone()

OnDone implements Notifier.

func (VisibilityNotifier[T]) OnVisit

func (v VisibilityNotifier[T]) OnVisit(_ GridKey, item T)

OnVisit implements Notifier.

Jump to

Keyboard shortcuts

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