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
Parameter | Type | Description |
---|---|---|
addr | string | The address of the redis DB to use for storage. |
password | string | The password of the redis DB to use for storage. |
opts | ...WorldOption | Options for configuring the world. |
Return Values
Type | Description |
---|---|
*World | A pointer to the newly created World instance. |
error | An 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
Parameter | Type | Description |
---|---|---|
adapter | shard.Adapter | The 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
Parameter | Type | Description |
---|---|---|
size | int | The 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
Parameter | Type | Description |
---|---|---|
ns | string | The 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
Parameter | Type | Description |
---|---|---|
port | string | The 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
Parameter | Type | Description |
---|---|---|
ch | <-chan time.Time | The 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
Parameter | Type | Description |
---|---|---|
world | *World | A pointer to a World instance. |
s | ...System | Variadic 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
Parameter | Type | Description |
---|---|---|
T | type parameter | A component struct that implements the Name method. |
world | *World | A pointer to a World instance. |
Return Value
Type | Description |
---|---|
error | An 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
Parameter | Type | Description |
---|---|---|
world | *World | A pointer to a World instance. |
queries | ...AnyQueryType | Variadic parameter for IQuery instances to be registered. |
Return Value
Type | Description |
---|---|
error | An 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
Parameter | Type | Description |
---|---|---|
world | *World | A pointer to a World instance. |
msgs | ...AnyMessage | Variadic parameter for Message instances to be registered. |
Return Value
Type | Description |
---|---|
error | An 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
Parameter | Type | Description |
---|---|---|
worldCtx | WorldContext | A WorldContext object passed in to your System. |
num | int | The number of entities to create. |
components | ...metadata.Component | Variadic parameter for components to associate with the created entities. |
Return Values
Type | Description |
---|---|
[]EntityID | A slice of EntityID representing the IDs of the created entities. |
error | An 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
Parameter | Type | Description |
---|---|---|
worldCtx | WorldContext | A WorldContext object passed in to your System. |
components | ...metadata.Component | Variadic parameter for components to associate with the created entity. |
Return Values
Type | Description |
---|---|
EntityID | The ID of the created entity. |
error | An 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
Parameter | Type | Description |
---|---|---|
worldCtx | WorldContext | A WorldContext object passed in to your System. |
id | entity.ID | The entity ID to be removed from the world. |
Return Value
Type | Description |
---|---|
error | An 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
Type | Description |
---|---|
error | An error indicating any issues when starting the game. |