ecs

package
v1.0.3-beta Latest Latest
Warning

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

Go to latest
Published: Dec 6, 2023 License: LGPL-3.0 Imports: 40 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrPersonaTagHasNoSigner        = errors.New("persona tag does not have a signer")
	ErrCreatePersonaTxsNotProcessed = errors.New("create persona txs have not been processed for the given tick")
)
View Source
var (
	ErrEntitiesCreatedBeforeLoadingGameState = errors.New("cannot create entities before loading game state")
	ErrMessageRegistrationMustHappenOnce     = errors.New(
		"message registration must happen exactly 1 time",
	)
	ErrStoreStateInvalid    = errors.New("saved world state is not valid")
	ErrDuplicateMessageName = errors.New("message names must be unique")
	ErrDuplicateQueryName   = errors.New("query names must be unique")
)
View Source
var AuthorizePersonaAddressMsg = NewMessageType[AuthorizePersonaAddress, AuthorizePersonaAddressResult](
	"authorize-persona-address",
)

CreatePersonaMsg is a message that facilitates the creation of a persona tag.

View Source
var (
	ErrCannotModifyStateWithReadOnlyContext = errors.New("cannot modify state with read only context")
)
View Source
var (
	ErrEVMTypeNotSet = errors.New("EVM type is not set")
)

Functions

func AddComponentTo

func AddComponentTo[T component.Component](wCtx WorldContext, id entity.ID) error

func AuthorizePersonaAddressSystem

func AuthorizePersonaAddressSystem(wCtx WorldContext) 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 WorldContext, components ...component.Component) (entity.ID, error)

func CreateMany

func CreateMany(wCtx WorldContext, num int, components ...component.Component) ([]entity.ID, error)

func GetComponent

func GetComponent[T component.Component](wCtx WorldContext, id entity.ID) (comp *T, err error)

GetComponent returns component data from the entity.

func MustRegisterComponent

func MustRegisterComponent[T component.Component](world *World)

func RegisterComponent

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

func RegisterPersonaSystem

func RegisterPersonaSystem(wCtx WorldContext) error

RegisterPersonaSystem is an ecs.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](
	world *World,
	name string,
	handler func(wCtx WorldContext, req *Request) (*Reply, error),
	opts ...func() func(queryType *QueryType[Request, Reply]),
) error

func RemoveComponentFrom

func RemoveComponentFrom[T component.Component](wCtx WorldContext, id entity.ID) error

RemoveComponentFrom removes a component from an entity.

func SetComponent

func SetComponent[T component.Component](wCtx WorldContext, id entity.ID, component *T) error

SetComponent sets component data to the entity.

func UpdateComponent

func UpdateComponent[T component.Component](wCtx WorldContext, id entity.ID, fn func(*T) *T) error

func WithMsgEVMSupport

func WithMsgEVMSupport[In, Out any]() func(messageType *MessageType[In, Out])

func WithQueryEVMSupport

func WithQueryEVMSupport[Request, Reply any]() func(transactionType *QueryType[Request, Reply])

Types

type AuthorizePersonaAddress

type AuthorizePersonaAddress struct {
	Address string `json:"address"`
}

type AuthorizePersonaAddressResult

type AuthorizePersonaAddressResult struct {
	Success bool `json:"success"`
}

type CreatePersona

type CreatePersona struct {
	PersonaTag    string `json:"personaTag"`
	SignerAddress string `json:"signerAddress"`
}

CreatePersona allows for the associating of a persona tag with a signer address.

type CreatePersonaResult

type CreatePersonaResult struct {
	Success bool `json:"success"`
}

type EVMTxReceipt

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

type Filterable

type Filterable interface {
	ConvertToComponentFilter(world *World) (filter.ComponentFilter, error)
}

func All

func All() Filterable

func And

func And(filters ...Filterable) Filterable

func Contains

func Contains(components ...component.Component) Filterable

func Exact

func Exact(components ...component.Component) Filterable

func Not

func Not(filter Filterable) Filterable

func Or

func Or(filters ...Filterable) Filterable

type MessageType

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

MessageType manages a user defined state transition message struct.

func NewMessageType

func NewMessageType[In, Out any](
	name string,
	opts ...func() func(*MessageType[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.

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 message.TxHash, err error)

func (*MessageType[In, Out]) AddToQueue

func (t *MessageType[In, Out]) AddToQueue(world *World, data In, sigs ...*sign.Transaction) message.TxHash

AddToQueue adds a message with the given data to the world. The message will be executed at the next game tick. An optional sign.Transaction can be associated with this message.

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]) GetReceipt

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

func (*MessageType[In, Out]) ID

func (t *MessageType[In, Out]) ID() message.TypeID

func (*MessageType[In, Out]) In

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

In extracts all the TxData in the tx queue 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 message.TypeID) error

func (*MessageType[In, Out]) SetResult

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

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(w *World)

func WithAdapter

func WithAdapter(adapter shard.Adapter) Option

func WithEventHub

func WithEventHub(eventHub events.EventHub) Option

func WithLoggingEventHub

func WithLoggingEventHub(logger *ecslog.Logger) Option

func WithPrettyLog

func WithPrettyLog() Option

func WithReceiptHistorySize

func WithReceiptHistorySize(size int) Option

func WithStoreManager

func WithStoreManager(s store.IManager) Option

type Query

type Query interface {
	// Name returns the name of the query.
	Name() string
	// HandleQuery handles queries with concrete types, rather than encoded bytes.
	HandleQuery(WorldContext, any) (any, error)
	// HandleQueryRaw is given a reference to the world, json encoded bytes that represent a query request
	// and is expected to return a json encoded response struct.
	HandleQueryRaw(WorldContext, []byte) ([]byte, error)
	// Schema returns the json schema of the query request.
	Schema() (request, reply *jsonschema.Schema)
	// DecodeEVMRequest decodes bytes originating from the evm into the request type, which will be ABI encoded.
	DecodeEVMRequest([]byte) (any, error)
	// EncodeEVMReply encodes the reply as an abi encoded struct.
	EncodeEVMReply(any) ([]byte, error)
	// DecodeEVMReply decodes EVM reply bytes, into the concrete go reply type.
	DecodeEVMReply([]byte) (any, error)
	// EncodeAsABI encodes a go struct in abi format. This is mostly used for testing.
	EncodeAsABI(any) ([]byte, error)
	// IsEVMCompatible reports if the query is able to be sent from the EVM.
	IsEVMCompatible() bool
}

func NewQueryType

func NewQueryType[Request any, Reply any](
	name string,
	handler func(wCtx WorldContext, req *Request) (*Reply, error),
	opts ...func() func(queryType *QueryType[Request, Reply]),
) (Query, error)

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]) HandleQuery

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

func (*QueryType[req, rep]) HandleQueryRaw

func (r *QueryType[req, rep]) HandleQueryRaw(wCtx WorldContext, 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

func (*QueryType[req, rep]) Schema

func (r *QueryType[req, rep]) Schema() (request, reply *jsonschema.Schema)
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(filter filter.ComponentFilter) *Search

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

func (*Search) Count

func (q *Search) Count(wCtx WorldContext) (int, error)

Count returns the number of entities that match the search.

func (*Search) Each

func (q *Search) Each(wCtx WorldContext, callback SearchCallBackFn) 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

func (q *Search) First(wCtx WorldContext) (id entity.ID, err error)

First returns the first entity that matches the search.

func (*Search) MustFirst

func (q *Search) MustFirst(wCtx WorldContext) entity.ID

type SearchCallBackFn

type SearchCallBackFn func(entity.ID) bool

type SignerComponent

type SignerComponent struct {
	PersonaTag          string
	SignerAddress       string
	AuthorizedAddresses []string
}

func (SignerComponent) Name

func (SignerComponent) Name() string

type System

type System func(WorldContext) error

type TxData

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

type World

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

func NewWorld

func NewWorld(
	storage *storage.Storage,
	entityStore store.IManager,
	namespace Namespace,
	opts ...Option,
) (*World, error)

NewWorld creates a new world.

func (*World) AddEVMTransaction

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

func (*World) AddInitSystem

func (w *World) AddInitSystem(system System)

func (*World) AddMessageError

func (w *World) AddMessageError(id message.TxHash, err error)

func (*World) AddTransaction

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

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

func (*World) ConsumeEVMMsgResult

func (w *World) ConsumeEVMMsgResult(evmTxHash string) (EVMTxReceipt, 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) DoesWorldHaveAnEventHub

func (w *World) DoesWorldHaveAnEventHub() bool

func (*World) EmitEvent

func (w *World) EmitEvent(event *events.Event)

func (*World) FlushEvents

func (w *World) FlushEvents()

func (*World) GetComponentByName

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

func (*World) GetComponents

func (w *World) GetComponents() []component.ComponentMetadata

func (*World) GetEventHub

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

func (*World) GetNonce

func (w *World) GetNonce(signerAddress string) (uint64, error)

func (*World) GetQueryByName

func (w *World) GetQueryByName(name string) (Query, 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 world'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) GetSystemNames

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

func (*World) GetTransactionReceipt

func (w *World) GetTransactionReceipt(id message.TxHash) (any, []error, bool)

func (*World) GetTransactionReceiptsForTick

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

func (*World) GetTxQueueAmount

func (w *World) GetTxQueueAmount() int

func (*World) InjectLogger

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

func (*World) IsEntitiesCreated

func (w *World) IsEntitiesCreated() bool

func (*World) IsGameLoopRunning

func (w *World) IsGameLoopRunning() bool

func (*World) IsRecovering

func (w *World) IsRecovering() bool

func (*World) ListMessages

func (w *World) ListMessages() ([]message.Message, error)

func (*World) ListQueries

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

func (*World) LoadGameState

func (w *World) LoadGameState() error

func (*World) Namespace

func (w *World) Namespace() Namespace

func (*World) NewSearch

func (w *World) NewSearch(filter Filterable) (*Search, error)

func (*World) ReceiptHistorySize

func (w *World) ReceiptHistorySize() uint64

func (*World) RecoverFromChain

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

RecoverFromChain will attempt to recover the state of the world based on historical transaction data. The function puts the world in a recovery state, and then queries 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) RegisterMessages

func (w *World) RegisterMessages(txs ...message.Message) error

func (*World) RegisterSystem

func (w *World) RegisterSystem(s System)

func (*World) RegisterSystemWithName

func (w *World) RegisterSystemWithName(system System, functionName string)

func (*World) RegisterSystems

func (w *World) RegisterSystems(systems ...System)

func (*World) Remove

func (w *World) Remove(id entity.ID) error

Remove removes the given Entity from the world.

func (*World) SetEntitiesCreated

func (w *World) SetEntitiesCreated(value bool)

func (*World) SetEventHub

func (w *World) SetEventHub(eventHub events.EventHub)

func (*World) SetMessageResult

func (w *World) SetMessageResult(id message.TxHash, a any)

func (*World) SetNonce

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

func (*World) Shutdown

func (w *World) Shutdown()

func (*World) StartGameLoop

func (w *World) StartGameLoop(
	ctx context.Context,
	tickStart <-chan time.Time,
	tickDone chan<- uint64,
)

func (*World) StoreManager

func (w *World) StoreManager() store.IManager

func (*World) Tick

func (w *World) Tick(_ context.Context) 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) TickStore

func (w *World) TickStore() store.TickStorage

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 world was shut down while waiting for the next tick to complete.

type WorldContext

type WorldContext interface {
	CurrentTick() uint64
	Logger() *zerolog.Logger
	NewSearch(filter Filterable) (*Search, error)

	// For internal use.
	GetWorld() *World
	StoreReader() store.Reader
	StoreManager() store.IManager
	GetTxQueue() *txpool.TxQueue
	IsReadOnly() bool
}

func NewReadOnlyWorldContext

func NewReadOnlyWorldContext(world *World) WorldContext

func NewWorldContext

func NewWorldContext(world *World) WorldContext

func NewWorldContextForTick

func NewWorldContextForTick(world *World, queue *txpool.TxQueue, logger *ecslog.Logger) WorldContext

Directories

Path Synopsis
Package ecb allows for buffering of state changes to the ECS storage 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 storage layer, and either committing those changes in an atomic Redis transaction, or discarding the changes.
internal
Package receipt keeps track of transaction receipts for a number of ticks.
Package receipt keeps track of transaction receipts for a number of ticks.

Jump to

Keyboard shortcuts

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