Cardinal
API Reference
World

World

The World object is the manager of everything happening in the game. It deals with registering components, systems, messages, and queries, as well as ticking the game simulation forward. World objects use Redis (opens in a new tab) to store the game's state.

package main
 
import (
	"log"
	"time"
 
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	redisAddr := os.Getenv("REDIS_ADDR")
	redisPassword := os.Getenv("REDIS_PASSWORD")
 
	world, err := cardinal.NewWorld(
		redisAddr,
		redisPassword,
		cardinal.WithNamespace("my-world"),
		cardinal.WithReceiptHistorySize(10),
		cardinal.WithTickInterval(500 * time.Millisecond),
		cardinal.WithPort("4001"),
	)
	if err != nil {
		log.Fatal(err)
	}
}

NewWorld

NewWorld creates a new World object.

func NewWorld(addr, password string, opts ...WorldOption) (*World, error)

Parameters

ParameterTypeDescription
addrstringThe address of the redis DB to use for storage.
passwordstringThe password of the redis DB to use for storage.
opts...WorldOptionOptions for configuring the world.

Return Values

TypeDescription
*WorldA pointer to the newly created World instance.
errorAn error indicating any issues during creation.

Options

WithAdapter

The WithAdapter world option enables World objects to read/write transactions to/from the sequencer (EVM base shard), and rebuild game state from those transactions. When running World Engine in production, the WithAdapter option must be used.

func WithAdapter(adapter shard.Adapter) Option
ParameterTypeDescription
adaptershard.AdapterThe adapter to be associated with World.

WithReceiptHistorySize

The WithReceiptHistorySize option informs the World object on how many ticks the World should keep receipts for. For example, if we are on tick 40, and have a receipt history size of 5, the World will have receipts for ticks 35-39. On tick 41, the World will have receipts for ticks 36-40. If this option is not set, a default history size of 10 will be used.

func WithReceiptHistorySize(size int) Option
ParameterTypeDescription
sizeintThe size of the receipt history to be set for World.

WithNamespace

The WithNamespace allows the World to have a custom Namespace. Namespaces are used to differentiate World objects that post data to the EVM base shard.

func WithNamespace(id string) Option
ParameterTypeDescription
nsstringThe namespace to be set for World.

WithPort

The WithPort option allows for a custom port to be set for the World's server. If this option is unset, Cardinal checks for a CARDINAL_PORT environment variable. If that is also unset, it uses a default port of 4040.

func WithPort(port string) WorldOption
ParameterTypeDescription
portstringThe port number for the world's server.

WithDisableSignatureVerification

The WithDisableSignatureVerification disables signature verification on the World's server. This should only be used for testing.

func WithDisableSignatureVerification() WorldOption

This method has no parameters.

WithTickChannel

The WithTickChannel sets the channel that will be used to initiate ticks. If unset, ticks will be executed once every second.

func WithTickChannel(ch <-chan time.Time) WorldOption
ParameterTypeDescription
ch<-chan time.TimeThe tick channel that will begin each game tick.
Example
// option to make ticks happen every 500 milliseconds.
opt := WithLoopInterval(time.Tick(500*time.Millisecond))

Methods

RegisterSystems

RegisterSystems registers one or more systems to the World. Systems are executed in the order of which they were added to the world.

func RegisterSystems(w *World, s ...System)

Example

package main
 
import (
	"github.com/my-username/my-world-engine-project/systems"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	// Systems will run in order in which they are added:
	// 1. MoveSystem
	// 2. HealthRegenSystem
	// 3. AttackSystem
	cardinal.RegisterSystems(world, systems.MoveSystem, systems.HealthRegenSystem, systems.AttackSystem)
}

Parameters

ParameterTypeDescription
world*WorldA pointer to a World instance.
s...SystemVariadic parameter for systems to be added to the World.

RegisterComponents

RegisterComponents registers one or more components to the World. Upon registration, components are assigned an ID. IDs are assigned incrementally, starting from 0, in the order in which they were passed to the method.

⚠️

RegisterComponents can be only be called once. Subsequent calls to the method will return an error.

func RegisterComponent[T metadata.Component](world *World) error

Example

package main
 
import (
	"log"
	"github.com/my-username/my-world-engine-project/component"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	err := cardinal.RegisterComponent[LocationComponet](world)
	if err != nil {
		log.Fatal(err)
	}
	err = cardinal.RegisterComponent[AttackPowerComponent](world)
	if err != nil {
		log.Fatal(err)
	}
	err = cardinal.RegisterComponent[HealthComponent](world)
	if err != nil {
		log.Fatal(err)
	}
 
	// Alternative RegisterComponent pattern with less error checking:
	err = errors.Join(
		cardinal.RegisterComponent[LocationComponet](world),
		cardinal.RegisterComponent[AttackPowerComponent](world),
		cardinal.RegisterComponent[HealthComponent](world),
	)
	if err != nil {
		log.Fatal(err)
	}
}

Parameters

ParameterTypeDescription
Ttype parameterA component struct that implements the Name method.
world*WorldA pointer to a World instance.

Return Value

TypeDescription
errorAn error indicating any issues that occurred during the component registration.

RegisterQueries

RegisterQueries registers the queries in the World. This allows the Query endpoints to be automatically generated.

func RegisterQueries(w *World, queries ...AnyQueryType) error

Example

package main
 
import (
	"log"
 
	"github.com/my-username/my-world-engine-project/query"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	err := cardinal.RegisterQueries(world,
		query.QueryLocation,
		query.QueryHealth,
		query.QueryAttackPower,
	)
	if err != nil {
		log.Fatal(err)
	}
}

Parameters

ParameterTypeDescription
world*WorldA pointer to a World instance.
queries...AnyQueryTypeVariadic parameter for IQuery instances to be registered.

Return Value

TypeDescription
errorAn error indicating any issues that occurred during the query registration.

RegisterMessages

RegisterMessages registers messages in the World. This allows message endpoints to be automatically generated.

⚠️

RegisterMessages can be only be called once. Subsequent calls to the method will return an error.

func RegisterMessages(w *World, msgs ...AnyMessage) error

Example

package main
 
import (
	"log"
 
	"github.com/my-username/my-world-engine-project/msg"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	err := cardinal.RegisterMessages(world,
		msg.Move,
		msg.Attack,
	)
	if err != nil {
		log.Fatal(err)
	}
}

Parameters

ParameterTypeDescription
world*WorldA pointer to a World instance.
msgs...AnyMessageVariadic parameter for Message instances to be registered.

Return Value

TypeDescription
errorAn error indicating any issues that occurred during the message registration.

CreateMany

CreateMany creates a specified amount of entities with a specified set of components.

func CreateMany(wCtx WorldContext, num int, components ...metadata.Component) ([]EntityID, error)

Example

package main
 
import (
	"log"
 
	"github.com/my-username/my-world-engine-project/components"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	// create 10 entities with the location and health component.
	entityIDs, err := cardinal.CreateMany(worldCtx,
		10,
		components.Location{},
		components.Health{},
	)
	if err != nil {
		log.Fatal(err)
	}
}

Parameters

ParameterTypeDescription
worldCtxWorldContextA WorldContext object passed in to your System.
numintThe number of entities to create.
components...metadata.ComponentVariadic parameter for components to associate with the created entities.

Return Values

TypeDescription
[]EntityIDA slice of EntityID representing the IDs of the created entities.
errorAn error indicating any issues that occurred during the creation process.

Create

Create creates a single entity with a given set of components.

func Create(wCtx WorldContext, components ...metadata.Component) (EntityID, error)

Example

package main
 
import (
	"log"
 
	"github.com/my-username/my-world-engine-project/components"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	// create an entity with the location and health component.
	entityID, err := cardinal.Create(worldCtx
		components.Location{},
		components.Health{},
	)
	if err != nil {
		log.Fatal(err)
	}
}

Parameters

ParameterTypeDescription
worldCtxWorldContextA WorldContext object passed in to your System.
components...metadata.ComponentVariadic parameter for components to associate with the created entity.

Return Values

TypeDescription
EntityIDThe ID of the created entity.
errorAn error indicating any issues that occurred during the creation process.

Remove

Remove removes a given entity from the World.

func Remove(wCtx WorldContext, id EntityID) error

Example

package main
 
import (
	"log"
 
	"github.com/my-username/my-world-engine-project/components"
	"pkg.world.dev/world-engine/cardinal"
)
 
func main() {
	// ... world setup ...
 
	// create an entity with the location and health component.
	entityID, err := cardinal.Create(worldCtx,
		components.Location{},
		components.Health{},
	)
	if err != nil {
		log.Fatal(err)
	}
 
	// remove the entity we just created
	err = cardinal.Remove(worldCtx, entityID)
	if err != nil {
		log.Fatal(err)
	}
}

Parameters

ParameterTypeDescription
worldCtxWorldContextA WorldContext object passed in to your System.
identity.IDThe entity ID to be removed from the world.

Return Value

TypeDescription
errorAn error indicating any issues that occurred during the removal process.

StartGame

StartGame starts the game by loading any previously saved game state, spinning up the message/query handler, and starting the game ticks. This method blocks the main Go routine. If for whatever reason execution needs to continue after calling this method, it should be called in a separate go routine.

func (w *World) StartGame() error

Return Value

TypeDescription
errorAn error indicating any issues when starting the game.