cardinal

package module
v1.1.0-beta Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2024 License: LGPL-3.0 Imports: 48 Imported by: 6

Documentation

Index

Constants

View Source
const (
	DefaultRunMode       = RunModeDev
	DefaultNamespace     = "world-1"
	DefaultRedisAddress  = "localhost:6379"
	DefaultLogLevel      = "info"
	DefaultStatsdAddress = "localhost:8125"
)

Default configuration values.

View Source
const (
	DefaultHistoricalTicksToStore = 10
)

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                = iterators.ErrEntityDoesNotExist
	ErrEntityMustHaveAtLeastOneComponent = iterators.ErrEntityMustHaveAtLeastOneComponent
	ErrComponentNotOnEntity              = iterators.ErrComponentNotOnEntity
	ErrComponentAlreadyOnEntity          = iterators.ErrComponentAlreadyOnEntity
)

Functions

func AddComponentTo

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

func AuthorizePersonaAddressSystem

func AuthorizePersonaAddressSystem(wCtx engine.Context) error

AuthorizePersonaAddressSystem enables users to authorize an address to a persona tag. This is mostly used so that users who want to interact with the game via smart contract can link their EVM address to their persona tag, enabling them to mutate their owned state from the context of the EVM.

func Create

func Create(wCtx engine.Context, 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 engine.Context, 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 engine.Context, fn func(message.TxData[In]) (Out, error)) error

func GetComponent

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

GetComponent returns component data from the entity.

func GetMessage

func GetMessage[In any, Out any](wCtx engine.Context) (*message.MessageType[In, Out], error)

func GetMessageFromWorld

func GetMessageFromWorld[In any, Out any](world *World) (*message.MessageType[In, Out], error)

func MustRegisterComponent

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

func NewQueryType

func NewQueryType[Request any, Reply any](
	name string,
	handler func(wCtx engine.Context, req *Request) (*Reply, error),
	opts ...QueryOption[Request, Reply],
) (engine.Query, error)

func NewReadOnlyWorldContext

func NewReadOnlyWorldContext(world *World) engine.Context

func NewWorldContext

func NewWorldContext(world *World) engine.Context

func RegisterComponent

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

func RegisterInitSystems

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

func RegisterMessage

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

func RegisterPersonaSystem

func RegisterPersonaSystem(wCtx engine.Context) error

RegisterPersonaSystem is an system that will associate persona tags with signature addresses. Each persona tag may have at most 1 signer, so additional attempts to register a signer with a persona tag will be ignored.

func RegisterQuery

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

func RegisterSystems

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

func Remove

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

Remove removes the given Entity from the engine.

func RemoveComponentFrom

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

RemoveComponentFrom removes a component from an entity.

func SetComponent

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

SetComponent sets component data to the entity.

func UpdateComponent

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

Types

type CQLQueryRequest

type CQLQueryRequest struct {
	CQL string
}

type CQLQueryResponse

type CQLQueryResponse struct {
	Results []cqlData `json:"results"`
}

type CallbackFn added in v1.3.3

type CallbackFn func(types.EntityID) bool

type DebugStateRequest

type DebugStateRequest struct{}

type DebugStateResponse

type DebugStateResponse []*debugStateElement

type EVMTxReceipt

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

type ListTxReceiptsRequest

type ListTxReceiptsRequest struct {
	StartTick uint64 `json:"startTick" mapstructure:"startTick"`
}

type ListTxReceiptsResponse

type ListTxReceiptsResponse struct {
	StartTick uint64         `json:"startTick"`
	EndTick   uint64         `json:"endTick"`
	Receipts  []ReceiptEntry `json:"receipts"`
}

ListTxReceiptsResponse returns the transaction receipts for the given range of ticks. The interval is closed on StartTick and open on EndTick: i.e. [StartTick, EndTick) Meaning StartTick is included and EndTick is not. To iterate over all ticks in the future, use the returned EndTick as the StartTick in the next request. If StartTick == EndTick, the receipts list will be empty.

type Namespace

type Namespace string

Namespace is a unique identifier for a world.

func (Namespace) String

func (n Namespace) String() string

type Option

type Option func(*World)

type Plugin

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

type QueryOption added in v1.3.3

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

func WithCustomQueryGroup added in v1.3.3

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 added in v1.3.3

func WithQueryEVMSupport[Request, Reply any]() QueryOption[Request, Reply]

type QueryType

type QueryType[Request any, Reply any] struct {
	// contains filtered or unexported fields
}

func (*QueryType[req, rep]) DecodeEVMReply

func (r *QueryType[req, rep]) DecodeEVMReply(bz []byte) (any, error)

func (*QueryType[req, rep]) DecodeEVMRequest

func (r *QueryType[req, rep]) DecodeEVMRequest(bz []byte) (any, error)

func (*QueryType[Request, Reply]) EncodeAsABI

func (r *QueryType[Request, Reply]) EncodeAsABI(input any) ([]byte, error)

func (*QueryType[req, rep]) EncodeEVMReply

func (r *QueryType[req, rep]) EncodeEVMReply(a any) ([]byte, error)

func (*QueryType[req, rep]) Group

func (r *QueryType[req, rep]) Group() string

func (*QueryType[req, rep]) HandleQuery

func (r *QueryType[req, rep]) HandleQuery(wCtx engine.Context, a any) (any, error)

func (*QueryType[req, rep]) HandleQueryRaw

func (r *QueryType[req, rep]) HandleQueryRaw(wCtx engine.Context, bz []byte) ([]byte, error)

func (*QueryType[Request, Reply]) IsEVMCompatible

func (r *QueryType[Request, Reply]) IsEVMCompatible() bool

func (*QueryType[req, rep]) Name

func (r *QueryType[req, rep]) Name() string

type ReceiptEntry

type ReceiptEntry struct {
	TxHash string  `json:"txHash"`
	Tick   uint64  `json:"tick"`
	Result any     `json:"result"`
	Errors []error `json:"errors"`
}

ReceiptEntry represents a single transaction receipt. It contains an ID, a result, and a list of errors.

type RunMode

type RunMode string
const (
	RunModeProd RunMode = "production"
	RunModeDev  RunMode = "development"
)
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 NewSearch

func NewSearch(wCtx engine.Context, filter filter.ComponentFilter) *Search

NewSearch creates a new search. It receives arbitrary filters that are used to filter entities.

func (*Search) Count added in v1.3.3

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

Count returns the number of entities that match the search.

func (*Search) Each added in v1.3.3

func (s *Search) Each(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) First added in v1.3.3

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

First returns the first entity that matches the search.

func (*Search) MustFirst added in v1.3.3

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

type System

type System = system.System

type World

type World struct {
	Logger *zerolog.Logger
	// contains filtered or unexported fields
}

func NewMockWorld

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

NewMockWorld creates a World object that uses miniredis as the storage layer suitable for local development. If you are creating a World for unit tests, use NewTestWorld.

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) GameStateManager

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

func (*World) GetComponentByName

func (w *World) GetComponentByName(name string) (types.ComponentMetadata, error)

func (*World) GetEVMMsgReceipt

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

func (*World) GetEventHub

func (w *World) GetEventHub() *events.EventHub

func (*World) GetMessageByID

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

func (*World) GetMessageByName

func (w *World) GetMessageByName(name string) (types.Message, bool)

func (*World) GetMessageManager

func (w *World) GetMessageManager() *message.Manager

func (*World) GetPersonaForEVMAddress

func (w *World) GetPersonaForEVMAddress(addr string) (string, error)

func (*World) GetQueryByName

func (w *World) GetQueryByName(name string) (engine.Query, error)

func (*World) GetRegisteredComponents

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

func (*World) GetRegisteredSystemNames

func (w *World) GetRegisteredSystemNames() []string

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) HandleEVMQuery

func (w *World) HandleEVMQuery(name string, abiRequest []byte) ([]byte, error)

func (*World) InjectLogger

func (w *World) InjectLogger(logger *zerolog.Logger)

func (*World) IsGameRunning

func (w *World) IsGameRunning() bool

func (*World) ListMessages

func (w *World) ListMessages() []types.Message

func (*World) ListQueries

func (w *World) ListQueries() []engine.Query

func (*World) Namespace

func (w *World) Namespace() Namespace

func (*World) RecoverFromChain

func (w *World) RecoverFromChain(ctx context.Context) error

RecoverFromChain will attempt to recover the state of the engine based on historical transaction data. The function puts the World in a recovery state, and will then query all transaction batches under the World's namespace. The function will continuously ask the EVM base shard for batches, and run ticks for each batch returned.

func (*World) RegisterPlugin

func (w *World) RegisterPlugin(plugin Plugin)

func (*World) SetRouter

func (w *World) SetRouter(rtr router.Router)

func (*World) Shutdown

func (w *World) Shutdown() error

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) Tick

func (w *World) Tick(ctx context.Context, timestamp uint64) error

Tick performs one game tick. This consists of taking a snapshot of all pending transactions, then calling each System in turn with the snapshot of transactions.

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 {
	RedisAddress              string  `config:"REDIS_ADDRESS"`
	RedisPassword             string  `config:"REDIS_PASSWORD"`
	CardinalNamespace         string  `config:"CARDINAL_NAMESPACE"`
	CardinalMode              RunMode `config:"CARDINAL_MODE"`
	BaseShardSequencerAddress string  `config:"BASE_SHARD_SEQUENCER_ADDRESS"`
	BaseShardQueryAddress     string  `config:"BASE_SHARD_QUERY_ADDRESS"`
	CardinalLogLevel          string  `config:"CARDINAL_LOG_LEVEL"`
	StatsdAddress             string  `config:"STATSD_ADDRESS"`
	TraceAddress              string  `config:"TRACE_ADDRESS"`
}

func (WorldConfig) Validate

func (w WorldConfig) Validate() error

type WorldContext

type WorldContext = engine.Context

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 WithCustomMockRedis

func WithCustomMockRedis(miniRedis *miniredis.Miniredis) WorldOption

func WithDisableSignatureVerification

func WithDisableSignatureVerification() WorldOption

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

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.Tick 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 ecb 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 ecb 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.
Package statsd is a helper package that wraps some common statsd methods.
Package statsd is a helper package that wraps some common statsd methods.

Jump to

Keyboard shortcuts

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