cardinal

package module
v1.5.1 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2024 License: LGPL-3.0 Imports: 61 Imported by: 0

Documentation

Index

Examples

Constants

View Source
const (
	DefaultCardinalNamespace         = "world-1"
	DefaultCardinalLogLevel          = "info"
	DefaultRedisAddress              = "localhost:6379"
	DefaultBaseShardSequencerAddress = "localhost:9601"
)
View Source
const (
	PersonaStatusUnknown   = "unknown"
	PersonaStatusAvailable = "available"
	PersonaStatusAssigned  = "assigned"
)
View Source
const (
	DefaultHistoricalTicksToStore = 10
	RedisDialTimeOut              = 150
)

Variables

View Source
var (
	ErrEntityMutationOnReadOnly          = errors.New("cannot modify state with read only context")
	ErrEntitiesCreatedBeforeReady        = errors.New("entities should not be created before world is ready")
	ErrEntityDoesNotExist                = gamestate.ErrEntityDoesNotExist
	ErrEntityMustHaveAtLeastOneComponent = gamestate.ErrEntityMustHaveAtLeastOneComponent
	ErrComponentNotOnEntity              = gamestate.ErrComponentNotOnEntity
	ErrComponentAlreadyOnEntity          = gamestate.ErrComponentAlreadyOnEntity
)
View Source
var DefaultQueryGroup = "game"
View Source
var (
	ErrEVMTypeNotSet = errors.New("EVM type is not set")
)

Functions

func AddComponentTo

func AddComponentTo[T types.Component](wCtx WorldContext, id types.EntityID) (err error)

func Create

func Create(wCtx WorldContext, components ...types.Component) (_ types.EntityID, err error)

Create creates a single entity in the world, and returns the id of the newly created entity. At least 1 component must be provided.

func CreateMany

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

CreateMany creates multiple entities in the world, and returns the slice of ids for the newly created entities. At least 1 component must be provided.

func EachMessage

func EachMessage[In any, Out any](wCtx WorldContext, fn func(TxData[In]) (Out, error)) error

func FilterFunction

func FilterFunction[T types.Component](f func(comp T) bool) func(ctx WorldContext, id types.EntityID) (bool, error)

func GetComponent

func GetComponent[T types.Component](wCtx WorldContext, id types.EntityID) (comp *T, err error)

GetComponent returns component data from the entity.

func MustRegisterComponent

func MustRegisterComponent[T types.Component](w *World)

func NewSearch

func NewSearch() searchBuilder

NewSearch is used to create a search object.

Usage:

cardinal.NewSearch().Entity(filter.Contains(filter.Component[EnergyComponent]()))

func RegisterComponent

func RegisterComponent[T types.Component](w *World) error

func RegisterInitSystems

func RegisterInitSystems(w *World, sys ...System) error

func RegisterMessage

func RegisterMessage[In any, Out any](world *World, name string, opts ...MessageOption[In, Out]) error

RegisterMessage registers a message to the world. Cardinal will automatically set up HTTP routes that map to each registered message. Message URLs are take the form of "group.name". A default group, "game", is used unless the WithCustomMessageGroup option is used. Example: game.throw-rock

func RegisterQuery

func RegisterQuery[Request any, Reply any](
	w *World,
	name string,
	handler func(wCtx WorldContext, req *Request) (*Reply, error),
	opts ...QueryOption[Request, Reply],
) (err error)

func RegisterSystems

func RegisterSystems(w *World, sys ...System) error

func RegisterTask

func RegisterTask[T Task](w *World) error

RegisterTask registers a Task definition with the World. A Task definition is a special type of component that has a Handle(WorldContext) method that is called when the task is triggered. The Handle method is responsible for executing the task and returning an error if any occurred.

func Remove

func Remove(wCtx WorldContext, id types.EntityID) (err error)

Remove removes the given Entity from the world.

func RemoveComponentFrom

func RemoveComponentFrom[T types.Component](wCtx WorldContext, id types.EntityID) (err error)

RemoveComponentFrom removes a component from an entity.

func SetComponent

func SetComponent[T types.Component](wCtx WorldContext, id types.EntityID, component *T) (err error)

SetComponent sets component data to the entity.

func UpdateComponent

func UpdateComponent[T types.Component](wCtx WorldContext, id types.EntityID, fn func(*T) *T) (err error)

Types

type AndSearch

type AndSearch struct {
	// contains filtered or unexported fields
}

func (*AndSearch) Collect

func (andSearch *AndSearch) Collect(wCtx WorldContext) ([]types.EntityID, error)

func (*AndSearch) Count

func (andSearch *AndSearch) Count(wCtx WorldContext) (int, error)

func (*AndSearch) Each

func (andSearch *AndSearch) Each(wCtx WorldContext, callback CallbackFn) error

func (*AndSearch) First

func (andSearch *AndSearch) First(wCtx WorldContext) (types.EntityID, error)

func (*AndSearch) MustFirst

func (andSearch *AndSearch) MustFirst(wCtx WorldContext) types.EntityID

type CallbackFn

type CallbackFn func(types.EntityID) bool

type EVMTxReceipt

type EVMTxReceipt struct {
	ABIResult []byte
	Errs      []error
	EVMTxHash string
}

type EntitySearch

type EntitySearch interface {
	Searchable
	Where(componentFilter FilterFn) EntitySearch
}

func NewLegacySearch

func NewLegacySearch(componentFilter filter.ComponentFilter) EntitySearch

TODO: should deprecate this in the future. NewLegacySearch allows users to create a Search object with a filter already provided as a property.

Example Usage:

cardinal.NewLegacySearch().Entity(filter.Exact(Alpha{}, Beta{})).Count()

type FilterFn

type FilterFn func(wCtx WorldContext, id types.EntityID) (bool, error)

func AndFilter

func AndFilter(fns ...FilterFn) FilterFn

func ComponentFilter

func ComponentFilter[T types.Component](f func(comp T) bool) FilterFn

func OrFilter

func OrFilter(fns ...FilterFn) FilterFn

type MessageManager

type MessageManager interface {
	RegisterMessage(msgType types.Message, msgReflectType reflect.Type) error
	GetRegisteredMessages() []types.Message
	GetMessageByID(id types.MessageID) types.Message
	GetMessageByFullName(fullName string) (types.Message, bool)
	GetMessageByType(mType reflect.Type) (types.Message, bool)
}

type MessageOption

type MessageOption[In, Out any] func(mt *MessageType[In, Out])

func WithCustomMessageGroup

func WithCustomMessageGroup[In, Out any](group string) MessageOption[In, Out]

WithCustomMessageGroup sets a custom group for the message. By default, messages are registered under the "game" group which maps it to the /tx/game/:txType route. This option allows you to set a custom group, which allow you to register the message under /tx/<custom_group>/:txType.

func WithMsgEVMSupport

func WithMsgEVMSupport[In, Out any]() MessageOption[In, Out]

type MessageType

type MessageType[In, Out any] struct {
	// contains filtered or unexported fields
}

MessageType manages a user defined state transition message struct.

Example
//nolint:testableexamples // can figure this out later.
package main

import (
	"errors"
	"fmt"

	"pkg.world.dev/world-engine/cardinal"
)

type MovePlayerMsg struct {
	DeltaX int
	DeltaY int
}

type MovePlayerResult struct {
	FinalX int
	FinalY int
}

func main() {
	world, err := cardinal.NewWorld(cardinal.WithMockRedis())
	if err != nil {
		panic(err)
	}

	err = cardinal.RegisterMessage[MovePlayerMsg, MovePlayerResult](world, "move-player")
	if err != nil {
		panic(err)
	}

	err = cardinal.RegisterSystems(world, func(wCtx cardinal.WorldContext) error {
		return cardinal.EachMessage[MovePlayerMsg, MovePlayerResult](wCtx,
			func(txData cardinal.TxData[MovePlayerMsg]) (MovePlayerResult, error) {
				// handle the transaction
				// ...

				if err := errors.New("some error from a function"); err != nil {
					// A returned non-nil error will be appended to this transaction's list of errors. Any existing
					// transaction result will not be modified.
					return MovePlayerResult{}, fmt.Errorf("problem processing transaction: %w", err)
				}

				// Returning a nil error implies this transaction handling was successful, so this transaction result
				// will be saved to the transaction receipt.
				return MovePlayerResult{
					FinalX: txData.Msg.DeltaX,
					FinalY: txData.Msg.DeltaY,
				}, nil
			})
	})
	if err != nil {
		panic(err)
	}
	// The above system will be called during each game tick.

	err = world.StartGame()
	if err != nil {
		panic(err)
	}
}
Output:

func NewMessageType

func NewMessageType[In, Out any](
	name string,
	opts ...MessageOption[In, Out],
) *MessageType[In, Out]

NewMessageType creates a new message type. It accepts two generic type parameters: the first for the message input, which defines the data needed to make a state transition, and the second for the message output, commonly used for the results of a state transition. By default, messages will be grouped under the "game" group, however an option may be passed in to change this.

func (*MessageType[In, Out]) ABIEncode

func (t *MessageType[In, Out]) ABIEncode(v any) ([]byte, error)

ABIEncode encodes the input to the message's matching evm type. If the input is not either of the message's evm types, an error is returned.

func (*MessageType[In, Out]) AddError

func (t *MessageType[In, Out]) AddError(wCtx WorldContext, hash types.TxHash, err error)

func (*MessageType[In, Out]) Decode

func (t *MessageType[In, Out]) Decode(bytes []byte) (any, error)

func (*MessageType[In, Out]) DecodeEVMBytes

func (t *MessageType[In, Out]) DecodeEVMBytes(bz []byte) (any, error)

DecodeEVMBytes decodes abi encoded solidity structs into the message's "In" type.

func (*MessageType[In, Out]) Each

func (t *MessageType[In, Out]) Each(wCtx WorldContext, fn func(TxData[In]) (Out, error))

func (*MessageType[In, Out]) Encode

func (t *MessageType[In, Out]) Encode(a any) ([]byte, error)

func (*MessageType[In, Out]) FullName

func (t *MessageType[In, Out]) FullName() string

func (*MessageType[In, Out]) GetInFieldInformation

func (t *MessageType[In, Out]) GetInFieldInformation() map[string]any

GetInFieldInformation returns a map of the fields of the message's "In" type and it's field types.

func (*MessageType[In, Out]) GetReceipt

func (t *MessageType[In, Out]) GetReceipt(wCtx WorldContext, hash types.TxHash) (
	v Out, errs []error, ok bool,
)

func (*MessageType[In, Out]) Group

func (t *MessageType[In, Out]) Group() string

func (*MessageType[In, Out]) ID

func (t *MessageType[In, Out]) ID() types.MessageID

func (*MessageType[In, Out]) In

func (t *MessageType[In, Out]) In(wCtx WorldContext) []TxData[In]

In extracts all the TxData in the tx pool that match this MessageType's ID.

func (*MessageType[In, Out]) IsEVMCompatible

func (t *MessageType[In, Out]) IsEVMCompatible() bool

func (*MessageType[In, Out]) Name

func (t *MessageType[In, Out]) Name() string

func (*MessageType[In, Out]) SetID

func (t *MessageType[In, Out]) SetID(id types.MessageID) error

func (*MessageType[In, Out]) SetResult

func (t *MessageType[In, Out]) SetResult(wCtx WorldContext, hash types.TxHash, result Out)

type Namespace

type Namespace string

Namespace is a unique identifier for a world used for posting to the data availability layer and to prevent signature replay attacks across multiple worlds.

func (Namespace) String

func (n Namespace) String() string

func (Namespace) Validate

func (n Namespace) Validate() error

Validate validates that the namespace is alphanumeric or - (hyphen).

type NotSearch

type NotSearch struct {
	// contains filtered or unexported fields
}

func (*NotSearch) Collect

func (notSearch *NotSearch) Collect(wCtx WorldContext) ([]types.EntityID, error)

func (*NotSearch) Count

func (notSearch *NotSearch) Count(wCtx WorldContext) (int, error)

func (*NotSearch) Each

func (notSearch *NotSearch) Each(wCtx WorldContext, callback CallbackFn) error

func (*NotSearch) First

func (notSearch *NotSearch) First(wCtx WorldContext) (types.EntityID, error)

func (*NotSearch) MustFirst

func (notSearch *NotSearch) MustFirst(wCtx WorldContext) types.EntityID

type Option

type Option func(*World)

type OrSearch

type OrSearch struct {
	// contains filtered or unexported fields
}

func (*OrSearch) Collect

func (orSearch *OrSearch) Collect(wCtx WorldContext) ([]types.EntityID, error)

func (*OrSearch) Count

func (orSearch *OrSearch) Count(wCtx WorldContext) (int, error)

func (*OrSearch) Each

func (orSearch *OrSearch) Each(wCtx WorldContext, callback CallbackFn) error

func (*OrSearch) First

func (orSearch *OrSearch) First(wCtx WorldContext) (types.EntityID, error)

func (*OrSearch) MustFirst

func (orSearch *OrSearch) MustFirst(wCtx WorldContext) types.EntityID

type PersonaSignerQueryRequest

type PersonaSignerQueryRequest struct {
	PersonaTag string `json:"personaTag"`
	Tick       uint64 `json:"tick"`
}

PersonaSignerQueryRequest is the desired request body for the query-persona-signer endpoint.

type PersonaSignerQueryResponse

type PersonaSignerQueryResponse struct {
	Status        string `json:"status"`
	SignerAddress string `json:"signerAddress"`
}

PersonaSignerQueryResponse is used as the response body for the query-persona-signer endpoint. Status can be: "assigned": The requested persona tag has been assigned the returned SignerAddress "unknown": The game tick has not advanced far enough to know what the signer address. SignerAddress will be empty. "available": The game tick has advanced, and no signer address has been assigned. SignerAddress will be empty.

type Plugin

type Plugin interface {
	Register(world *World) error
}

type QueryManager

type QueryManager interface {
	RegisterQuery(queryInput query) error
	GetRegisteredQueries() []query
	HandleQuery(group string, name string, bz []byte) ([]byte, error)
	HandleQueryEVM(group string, name string, abiRequest []byte) ([]byte, error)

	BuildQueryFields() []types.FieldDetail
	// contains filtered or unexported methods
}

type QueryOption

type QueryOption[Request, Reply any] func(qt *queryType[Request, Reply])

func WithCustomQueryGroup

func WithCustomQueryGroup[Request, Reply any](group string) QueryOption[Request, Reply]

WithCustomQueryGroup sets a custom group for the query. By default, queries are registered under the "game" group which maps it to the /query/game/:queryType route. This option allows you to set a custom group, which allow you to register the query under /query/<custom_group>/:queryType.

func WithQueryEVMSupport

func WithQueryEVMSupport[Request, Reply any]() QueryOption[Request, Reply]
type Search struct {
	// contains filtered or unexported fields
}

Search represents a search for entities. It is used to filter entities based on their components. It receives arbitrary filters that are used to filter entities. It contains a cache that is used to avoid re-evaluating the search. So it is not recommended to create a new search every time you want to filter entities with the same search.

func (*Search) Collect

func (s *Search) Collect(wCtx WorldContext) ([]types.EntityID, error)

func (*Search) Count

func (s *Search) Count(wCtx WorldContext) (ret int, err error)

Count returns the number of entities that match the search.

func (*Search) Each

func (s *Search) Each(wCtx WorldContext, callback CallbackFn) (err error)

Each iterates over all entities that match the search. If you would like to stop the iteration, return false to the callback. To continue iterating, return true.

func (*Search) Entity

func (s *Search) Entity(componentFilter filter.ComponentFilter) EntitySearch

func (*Search) First

func (s *Search) First(wCtx WorldContext) (id types.EntityID, err error)

First returns the first entity that matches the search.

func (*Search) MustFirst

func (s *Search) MustFirst(wCtx WorldContext) types.EntityID

func (*Search) Where

func (s *Search) Where(componentFilter FilterFn) EntitySearch

Once the where clause method is activated the search will ONLY return results if a where clause returns true and no error.

type Searchable

type Searchable interface {
	Each(wCtx WorldContext, callback CallbackFn) error
	First(wCtx WorldContext) (types.EntityID, error)
	MustFirst(wCtx WorldContext) types.EntityID
	Count(wCtx WorldContext) (int, error)
	Collect(wCtx WorldContext) ([]types.EntityID, error)
	// contains filtered or unexported methods
}

func And

func And(searches ...Searchable) Searchable

func Not

func Not(search Searchable) Searchable

func Or

func Or(searches ...Searchable) Searchable

type System

type System func(ctx WorldContext) error

System is a user-defined function that is executed at every tick.

type SystemManager

type SystemManager interface {
	// GetRegisteredSystems returns a slice of all registered systems' name.
	GetRegisteredSystems() []string

	// GetCurrentSystem returns the name of the currently running system.
	// If no system is currently running, it returns an empty string.
	GetCurrentSystem() string
	// contains filtered or unexported methods
}

type Task

type Task interface {
	types.Component
	Handle(WorldContext) error
}

Task is a user-facing special component interface that is used to define a task that can be scheduled to be executed. It implements the types.Component interface along with a Handle method that is called when the task is triggered. This method is not to be confused with taskMetadata, which is an internal component type used to store the trigger condition for a task.

type TaskPlugin

type TaskPlugin struct{}

TaskPlugin defines a plugin that handles task scheduling and execution.

func (*TaskPlugin) Register

func (*TaskPlugin) Register(w *World) error

type TestFixture

type TestFixture struct {
	testing.TB

	// Base url is something like "localhost:5050". You must attach http:// or ws:// as well as a resource path
	BaseURL string
	World   *World
	Redis   *miniredis.Miniredis

	StartTickCh chan time.Time
	DoneTickCh  chan uint64
	// contains filtered or unexported fields
}

TestFixture is a helper struct that manages a cardinal.World instance. It will automatically clean up its resources at the end of the test.

func NewTestFixture

func NewTestFixture(t testing.TB, redis *miniredis.Miniredis, opts ...WorldOption) *TestFixture

NewTestFixture creates a test fixture with user defined port for Cardinal integration tests.

func (*TestFixture) AddTransaction

func (t *TestFixture) AddTransaction(txID types.MessageID, tx any, sigs ...*sign.Transaction) types.TxHash

func (*TestFixture) CreatePersona

func (t *TestFixture) CreatePersona(personaTag, signerAddr string)

func (*TestFixture) DoTick

func (t *TestFixture) DoTick()

DoTick executes one game tick and blocks until the tick is complete. StartWorld is automatically called if it was not called before the first tick.

func (*TestFixture) Get

func (t *TestFixture) Get(path string) *http.Response

Get executes a http GET request to this TestFixture's cardinal server.

func (*TestFixture) Post

func (t *TestFixture) Post(path string, payload any) *http.Response

Post executes a http POST request to this TextFixture's cardinal server.

func (*TestFixture) StartWorld

func (t *TestFixture) StartWorld()

StartWorld starts the game world and registers a cleanup function that will shut down the cardinal World at the end of the test. Components/Systems/Queries, etc should be registered before calling this function.

type TickResults

type TickResults struct {
	Tick     uint64
	Receipts []receipt.Receipt
	Events   [][]byte
}

func NewTickResults

func NewTickResults(initialTick uint64) *TickResults

func (*TickResults) AddEvent

func (tr *TickResults) AddEvent(event any) error

func (*TickResults) AddStringEvent

func (tr *TickResults) AddStringEvent(e string) error

func (*TickResults) Clear

func (tr *TickResults) Clear()

func (*TickResults) SetReceipts

func (tr *TickResults) SetReceipts(newReceipts []receipt.Receipt)

func (*TickResults) SetTick

func (tr *TickResults) SetTick(tick uint64)

type TxData

type TxData[In any] struct {
	Hash types.TxHash
	Msg  In
	Tx   *sign.Transaction
}

type World

type World struct {
	SystemManager
	MessageManager
	QueryManager
	component.ComponentManager
	// contains filtered or unexported fields
}

func NewWorld

func NewWorld(opts ...WorldOption) (*World, error)

NewWorld creates a new World object using Redis as the storage layer

func (*World) AddEVMTransaction

func (w *World) AddEVMTransaction(
	id types.MessageID,
	v any,
	sig *sign.Transaction,
	evmTxHash string,
) (
	tick uint64, txHash types.TxHash,
)

func (*World) AddTransaction

func (w *World) AddTransaction(id types.MessageID, v any, sig *sign.Transaction) (
	tick uint64, txHash types.TxHash,
)

AddTransaction adds a transaction to the transaction pool. This should not be used directly. Instead, use a MessageType.addTransaction to ensure type consistency. Returns the tick this transaction will be executed in.

func (*World) ConsumeEVMMsgResult

func (w *World) ConsumeEVMMsgResult(evmTxHash string) ([]byte, []error, string, bool)

ConsumeEVMMsgResult consumes a tx result from an EVM originated Cardinal message. It will fetch the receipt from the map, and then delete ('consume') it from the map.

func (*World) CurrentTick

func (w *World) CurrentTick() uint64

func (*World) EvaluateCQL

func (w *World) EvaluateCQL(cqlString string) ([]types.EntityStateElement, error)

func (*World) GameStateManager

func (w *World) GameStateManager() gamestate.Manager

func (*World) GetDebugState

func (w *World) GetDebugState() ([]types.DebugStateElement, error)

func (*World) GetEVMMsgReceipt

func (w *World) GetEVMMsgReceipt(evmTxHash string) (EVMTxReceipt, bool)

func (*World) GetMessageByID

func (w *World) GetMessageByID(id types.MessageID) (types.Message, bool)

func (*World) GetReadOnlyCtx

func (w *World) GetReadOnlyCtx() WorldContext

func (*World) GetRegisteredComponents

func (w *World) GetRegisteredComponents() []types.ComponentMetadata

func (*World) GetSignerComponentForPersona

func (w *World) GetSignerComponentForPersona(personaTag string) (*component.SignerComponent, error)

func (*World) GetSignerForPersonaTag

func (w *World) GetSignerForPersonaTag(personaTag string, tick uint64) (addr string, err error)

GetSignerForPersonaTag returns the signer address that has been registered for the given persona tag after the given tick. If the engine's tick is less than or equal to the given tick, ErrorCreatePersonaTXsNotProcessed is returned. If the given personaTag has no signer address, ErrPersonaTagHasNoSigner is returned.

func (*World) GetTransactionReceiptsForTick

func (w *World) GetTransactionReceiptsForTick(tick uint64) ([]receipt.Receipt, error)

func (*World) IsGameRunning

func (w *World) IsGameRunning() bool

func (*World) Namespace

func (w *World) Namespace() string

func (*World) ReceiptHistorySize

func (w *World) ReceiptHistorySize() uint64

func (*World) RegisterPlugin

func (w *World) RegisterPlugin(plugin Plugin)

func (*World) Search

func (w *World) Search(filter filter.ComponentFilter) EntitySearch

func (*World) Shutdown

func (w *World) Shutdown()

Shutdown will trigger a graceful shutdown of the World.

func (*World) StartGame

func (w *World) StartGame() error

StartGame starts running the world game loop. Each time a message arrives on the tickChannel, a world tick is attempted. In addition, an HTTP server (listening on the given port) is created so that game messages can be sent to this world. After StartGame is called, RegisterComponent, registerMessagesByName, RegisterQueries, and RegisterSystems may not be called. If StartGame doesn't encounter any errors, it will block forever, running the server and ticking the game in the background.

func (*World) StoreReader

func (w *World) StoreReader() gamestate.Reader

func (*World) UseNonce

func (w *World) UseNonce(signerAddress string, nonce uint64) error

func (*World) WaitForNextTick

func (w *World) WaitForNextTick() (success bool)

WaitForNextTick blocks until at least one game tick has completed. It returns true if it successfully waited for a tick. False may be returned if the engine was shut down while waiting for the next tick to complete.

type WorldConfig

type WorldConfig struct {
	// CardinalNamespace The shard namespace for Cardinal. This needs to be unique to prevent signature replay attacks.
	CardinalNamespace string `mapstructure:"CARDINAL_NAMESPACE"`

	// CardinalRollupEnabled When true, Cardinal will sequence and recover to/from base shard.
	CardinalRollupEnabled bool `mapstructure:"CARDINAL_ROLLUP_ENABLED"`

	// CardinalLogLevel Determines the log level for Cardinal.
	CardinalLogLevel string `mapstructure:"CARDINAL_LOG_LEVEL"`

	// CardinalLogPretty Pretty logging, disable by default due to performance impact.
	CardinalLogPretty bool `mapstructure:"CARDINAL_LOG_PRETTY"`

	// RedisAddress The address of the redis server, supports unix sockets.
	RedisAddress string `mapstructure:"REDIS_ADDRESS"`

	// RedisPassword The password for the redis server. Make sure to use a password in production.
	RedisPassword string `mapstructure:"REDIS_PASSWORD"`

	// BaseShardSequencerAddress This is the address that Cardinal will use to sequence and recover to/from base shard.
	BaseShardSequencerAddress string `mapstructure:"BASE_SHARD_SEQUENCER_ADDRESS"`

	// BaseShardRouterKey is a token used to secure communications between the game shard and the base shard.
	BaseShardRouterKey string `mapstructure:"BASE_SHARD_ROUTER_KEY"`

	// TelemetryTraceEnabled When true, Cardinal will collect OpenTelemetry traces
	TelemetryTraceEnabled bool `mapstructure:"TELEMETRY_TRACE_ENABLED"`

	// TelemetryProfilerEnabled When true, Cardinal will run Datadog continuous profiling
	TelemetryProfilerEnabled bool `mapstructure:"TELEMETRY_PROFILER_ENABLED"`
}

func (*WorldConfig) Validate

func (w *WorldConfig) Validate() error

Validate validates the config values. If CARDINAL_ROLLUP=true, the BASE_SHARD_SEQUENCER_ADDRESS and BASE_SHARD_ROUTER_KEY are required.

type WorldContext

type WorldContext interface {
	// Timestamp returns the UNIX timestamp of the tick in milliseconds.
	// Millisecond is used to provide precision when working with subsecond tick intervals.
	Timestamp() uint64

	// CurrentTick returns the current tick.
	CurrentTick() uint64

	// Logger returns the logger that can be used to log messages from within system or query.
	Logger() *zerolog.Logger

	// EmitEvent emits an event that will be broadcast to all websocket subscribers.
	EmitEvent(map[string]any) error

	// EmitStringEvent emits a string event that will be broadcast to all websocket subscribers.
	// This method is provided for backwards compatability. EmitEvent should be used for most cases.
	EmitStringEvent(string) error

	// Namespace returns the namespace of the world.
	Namespace() string

	// Rand returns a random number generator that is seeded specifically for a current tick.
	Rand() *rand.Rand

	// ScheduleTickTask schedules a task to be executed after the specified tickDelay.
	// The given Task must have been registered using RegisterTask.
	ScheduleTickTask(uint64, Task) error

	// ScheduleTimeTask schedules a task to be executed after the specified duration (in wall clock time).
	// The given Task must have been registered using RegisterTask.
	ScheduleTimeTask(time.Duration, Task) error
	// contains filtered or unexported methods
}

func NewReadOnlyWorldContext

func NewReadOnlyWorldContext(world *World) WorldContext

func NewWorldContext

func NewWorldContext(world *World) WorldContext

type WorldOption

type WorldOption struct {
	// contains filtered or unexported fields
}

WorldOption represents an option that can be used to augment how the cardinal.World will be run.

func WithCustomLogger

func WithCustomLogger(logger zerolog.Logger) WorldOption

func WithCustomRouter

func WithCustomRouter(rtr router.Router) WorldOption

func WithDisableSignatureVerification

func WithDisableSignatureVerification() WorldOption

WithDisableSignatureVerification disables signature verification for the HTTP server. This should only be used for local development.

func WithMockJobQueue

func WithMockJobQueue() WorldOption

WithMockJobQueue runs the router with an in-memory job queue instead of a persistent one that writes to disk.

func WithMockRedis

func WithMockRedis() WorldOption

WithMockRedis runs the World with an embedded miniredis instance on port 6379.

func WithPort

func WithPort(port string) WorldOption

WithPort sets the port that the HTTP server will run on.

func WithPrettyLog

func WithPrettyLog() WorldOption

func WithReceiptHistorySize

func WithReceiptHistorySize(size int) WorldOption

WithReceiptHistorySize specifies how many ticks worth of transaction receipts should be kept in memory. The default is 10. A smaller number uses less memory, but limits the amount of historical receipts available.

func WithStoreManager

func WithStoreManager(s gamestate.Manager) WorldOption

func WithTickChannel

func WithTickChannel(ch <-chan time.Time) WorldOption

WithTickChannel sets the channel that will be used to decide when world.doTick is executed. If unset, a loop interval of 1 second will be set. To set some other time, use: WithTickChannel(time.Tick(<some-duration>)). Tests can pass in a channel controlled by the test for fine-grained control over when ticks are executed.

func WithTickDoneChannel

func WithTickDoneChannel(ch chan<- uint64) WorldOption

WithTickDoneChannel sets a channel that will be notified each time a tick completes. The completed tick will be pushed to the channel. This option is useful in tests when assertions need to be performed at the end of a tick.

Directories

Path Synopsis
Package gamestate allows for buffering of state changes to the ECS dbStorage layer, and either committing those changes in an atomic Redis transaction, or discarding the changes.
Package gamestate allows for buffering of state changes to the ECS dbStorage layer, and either committing those changes in an atomic Redis transaction, or discarding the changes.
msg
Package receipt keeps track of transaction receipts for a number of ticks.
Package receipt keeps track of transaction receipts for a number of ticks.
iterator/mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
docs
Package docs Code generated by swaggo/swag.
Package docs Code generated by swaggo/swag.

Jump to

Keyboard shortcuts

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