Skip to content

Commit

Permalink
feat(starter-game-template): update to use a new version of cardinal … (
Browse files Browse the repository at this point in the history
#4)

* feat(starter-game-template): update to use a new version of cardinal that returns tx_hash

* bump cardinal version again and add logger to system functions
  • Loading branch information
jerargus authored Aug 25, 2023
1 parent a4337bc commit dc30649
Show file tree
Hide file tree
Showing 22 changed files with 270 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .jsclient/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cardinal/component/health.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package component

import "github.com/argus-labs/world-engine/cardinal/ecs"
import "pkg.world.dev/world-engine/cardinal/ecs"

type HealthComponent struct {
HP int
Expand Down
2 changes: 1 addition & 1 deletion cardinal/component/player.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package component

import "github.com/argus-labs/world-engine/cardinal/ecs"
import "pkg.world.dev/world-engine/cardinal/ecs"

type PlayerComponent struct {
Nickname string
Expand Down
5 changes: 3 additions & 2 deletions cardinal/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package main

import (
"github.com/argus-labs/starter-game-template/cardinal/utils"
"github.com/argus-labs/world-engine/cardinal/ecs"
"os"

"github.com/argus-labs/starter-game-template/cardinal/utils"
"pkg.world.dev/world-engine/cardinal/ecs"
)

type Config struct {
Expand Down
2 changes: 1 addition & 1 deletion cardinal/game/archetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package game

import (
"github.com/argus-labs/starter-game-template/cardinal/component"
"github.com/argus-labs/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs"
)

type IArchetype struct {
Expand Down
14 changes: 6 additions & 8 deletions cardinal/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/argus-labs/starter-game-template/cardinal

go 1.20
go 1.21

replace (
github.com/cometbft/cometbft => github.com/rollkit/cometbft v0.0.0-20230614163111-d6a8d2c98cc0
Expand All @@ -10,10 +10,7 @@ replace (
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
)

require (
github.com/argus-labs/world-engine/cardinal v0.1.22-alpha
github.com/rs/zerolog v1.29.1
)
require github.com/rs/zerolog v1.29.1

require (
buf.build/gen/go/argus-labs/world-engine/grpc/go v1.3.0-20230808004839-11a21a99bf62.1 // indirect
Expand All @@ -29,9 +26,7 @@ require (
cosmossdk.io/x/tx v0.9.1 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/alicebob/miniredis/v2 v2.30.2 // indirect
github.com/argus-labs/world-engine/chain v0.1.1-alpha // indirect
github.com/argus-labs/world-engine/sign v0.1.4-alpha // indirect
github.com/alicebob/miniredis/v2 v2.30.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
Expand Down Expand Up @@ -116,5 +111,8 @@ require (
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
pkg.world.dev/world-engine/cardinal v0.1.27-alpha
pkg.world.dev/world-engine/chain v0.1.11-alpha // indirect
pkg.world.dev/world-engine/sign v0.1.6-alpha // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
191 changes: 183 additions & 8 deletions cardinal/go.sum

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions cardinal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"github.com/argus-labs/starter-game-template/cardinal/read"
"github.com/argus-labs/starter-game-template/cardinal/system"
"github.com/argus-labs/starter-game-template/cardinal/tx"
"github.com/argus-labs/world-engine/cardinal/server"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"pkg.world.dev/world-engine/cardinal/server"
)

func main() {
Expand Down Expand Up @@ -73,9 +73,9 @@ func main() {
world.StartGameLoop(context.Background(), time.Second)

// TODO: When launching to production, you should enable signature verification.
h, err := server.NewHandler(world, server.DisableSignatureVerification())
h, err := server.NewHandler(world, server.WithPort(cfg.CardinalPort))
if err != nil {
panic(err)
}
h.Serve("", cfg.CardinalPort)
h.Serve()
}
8 changes: 4 additions & 4 deletions cardinal/read/read_archetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package read
import (
"errors"
"fmt"
"github.com/argus-labs/starter-game-template/cardinal/game"
"reflect"

"github.com/argus-labs/world-engine/cardinal/ecs"
"github.com/argus-labs/world-engine/cardinal/ecs/filter"
"github.com/argus-labs/world-engine/cardinal/ecs/storage"
"github.com/argus-labs/starter-game-template/cardinal/game"
"pkg.world.dev/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs/filter"
"pkg.world.dev/world-engine/cardinal/ecs/storage"
)

type ArchetypeRequest struct {
Expand Down
3 changes: 2 additions & 1 deletion cardinal/read/read_constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package read

import (
"errors"

"github.com/argus-labs/starter-game-template/cardinal/game"
"github.com/argus-labs/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs"
)

type ConstantRequest struct {
Expand Down
14 changes: 7 additions & 7 deletions cardinal/system/system_attack.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import (

comp "github.com/argus-labs/starter-game-template/cardinal/component"
"github.com/argus-labs/starter-game-template/cardinal/tx"
"github.com/argus-labs/world-engine/cardinal/ecs"
"github.com/argus-labs/world-engine/cardinal/ecs/filter"
"github.com/argus-labs/world-engine/cardinal/ecs/storage"
"pkg.world.dev/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs/filter"
"pkg.world.dev/world-engine/cardinal/ecs/storage"
)

// AttackSystem is a system that inflict damage to player's HP based on `AttackPlayer` transactions.
// This provides a simple example of how to create a system that modifies the component of an entity.
func AttackSystem(world *ecs.World, tq *ecs.TransactionQueue) error {
func AttackSystem(world *ecs.World, tq *ecs.TransactionQueue, _ *ecs.Logger) error {
// Get all the transactions that are of type CreatePlayer from the tx queue
attackTxs := tx.AttackPlayer.In(tq)

Expand All @@ -37,23 +37,23 @@ func AttackSystem(world *ecs.World, tq *ecs.TransactionQueue) error {
targetPlayerID, ok := playerTagToID[target]
// If the target player doesn't exist, skip this transaction
if !ok {
tx.AttackPlayer.AddError(world, attack.ID,
tx.AttackPlayer.AddError(world, attack.TxHash,
fmt.Errorf("target %q does not exist", target))
continue
}

// Get the health component for the target player
health, err := comp.Health.Get(world, targetPlayerID)
if err != nil {
tx.AttackPlayer.AddError(world, attack.ID,
tx.AttackPlayer.AddError(world, attack.TxHash,
fmt.Errorf("can't get health for %q: %w", target, err))
continue
}

// Inflict damage and update the component
health.HP -= 10
if err := comp.Health.Set(world, targetPlayerID, health); err != nil {
tx.AttackPlayer.AddError(world, attack.ID,
tx.AttackPlayer.AddError(world, attack.TxHash,
fmt.Errorf("failed to set health on %q: %w", target, err))
continue
}
Expand Down
12 changes: 6 additions & 6 deletions cardinal/system/system_player_spawner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import (

comp "github.com/argus-labs/starter-game-template/cardinal/component"
"github.com/argus-labs/starter-game-template/cardinal/tx"
"github.com/argus-labs/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs"
)

// PlayerSpawnerSystem is a system that spawns players based on `CreatePlayer` transactions.
// This provides a simple example of how to create a system that creates a new entity.
func PlayerSpawnerSystem(world *ecs.World, tq *ecs.TransactionQueue) error {
func PlayerSpawnerSystem(world *ecs.World, tq *ecs.TransactionQueue, _ *ecs.Logger) error {
// Get all the transactions that are of type CreatePlayer from the tx queue
createTxs := tx.CreatePlayer.In(tq)

Expand All @@ -21,25 +21,25 @@ func PlayerSpawnerSystem(world *ecs.World, tq *ecs.TransactionQueue) error {
for _, create := range createTxs {
id, err := world.Create(comp.Player, comp.Health)
if err != nil {
tx.CreatePlayer.AddError(world, create.ID,
tx.CreatePlayer.AddError(world, create.TxHash,
fmt.Errorf("error creating player: %w", err))
continue
}

err = comp.Player.Set(world, id, comp.PlayerComponent{Nickname: create.Value.Nickname})
if err != nil {
tx.CreatePlayer.AddError(world, create.ID,
tx.CreatePlayer.AddError(world, create.TxHash,
fmt.Errorf("error setting player nickname: %w", err))
continue
}

err = comp.Health.Set(world, id, comp.HealthComponent{HP: 100})
if err != nil {
tx.CreatePlayer.AddError(world, create.ID,
tx.CreatePlayer.AddError(world, create.TxHash,
fmt.Errorf("error setting player health: %w", err))
continue
}
tx.CreatePlayer.SetResult(world, create.ID, tx.CreatePlayerMsgReply{true})
tx.CreatePlayer.SetResult(world, create.TxHash, tx.CreatePlayerMsgReply{true})
}

return nil
Expand Down
8 changes: 4 additions & 4 deletions cardinal/system/system_regen.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package system

import (
comp "github.com/argus-labs/starter-game-template/cardinal/component"
"github.com/argus-labs/world-engine/cardinal/ecs"
"github.com/argus-labs/world-engine/cardinal/ecs/filter"
"github.com/argus-labs/world-engine/cardinal/ecs/storage"
"pkg.world.dev/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs/filter"
"pkg.world.dev/world-engine/cardinal/ecs/storage"
)

// RegenSystem is a system that replenishes the player's HP at every tick.
// This provides a simple example of how to create a system that doesn't rely on a transaction to update a component.
func RegenSystem(world *ecs.World, _ *ecs.TransactionQueue) error {
func RegenSystem(world *ecs.World, _ *ecs.TransactionQueue, _ *ecs.Logger) error {
ecs.NewQuery(filter.Exact(comp.Player, comp.Health)).Each(world, func(id storage.EntityID) bool {
// Get the health component for the player
health, err := comp.Health.Get(world, id)
Expand Down
2 changes: 1 addition & 1 deletion cardinal/tx/tx_attack_player.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package tx

import (
"github.com/argus-labs/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs"
)

type AttackPlayerMsg struct {
Expand Down
2 changes: 1 addition & 1 deletion cardinal/tx/tx_create_player.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package tx

import (
"github.com/argus-labs/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs"
)

type CreatePlayerMsg struct {
Expand Down
6 changes: 3 additions & 3 deletions cardinal/utils/world.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package utils

import (
"github.com/argus-labs/world-engine/cardinal/ecs"
"github.com/argus-labs/world-engine/cardinal/ecs/inmem"
"github.com/argus-labs/world-engine/cardinal/ecs/storage"
"github.com/rs/zerolog/log"
"pkg.world.dev/world-engine/cardinal/ecs"
"pkg.world.dev/world-engine/cardinal/ecs/inmem"
"pkg.world.dev/world-engine/cardinal/ecs/storage"
)

// NewWorld is the recommended way to run the game
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ services:
- cardinal
environment:
- CARDINAL_ADDR=${CARDINAL_ADDR:-http://cardinal:3333}
- CARDINAL_NAMESPACE=0
- CARDINAL_NAMESPACE=world
entrypoint:
- "/bin/sh"
- "-ecx"
Expand Down
40 changes: 24 additions & 16 deletions nakama/cardinal.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"net/http"
"os"

"github.com/argus-labs/world-engine/sign"
"github.com/heroiclabs/nakama-common/runtime"
"pkg.world.dev/world-engine/sign"
)

var (
Expand All @@ -33,6 +33,11 @@ var (
ErrorPersonaSignerUnknown = errors.New("persona signer is unknown.")
)

type txResponse struct {
TxHash string `json:"tx_hash"`
Tick uint64 `json:"tick"`
}

func initCardinalAddress() error {
globalCardinalAddress = os.Getenv(EnvCardinalAddr)
if globalCardinalAddress == "" {
Expand Down Expand Up @@ -90,7 +95,7 @@ func doRequest(req *http.Request) (*http.Response, error) {
return resp, nil
}

func cardinalCreatePersona(ctx context.Context, nk runtime.NakamaModule, personaTag string) (tick uint64, err error) {
func cardinalCreatePersona(ctx context.Context, nk runtime.NakamaModule, personaTag string) (txHash string, tick uint64, err error) {
signerAddress := getSignerAddress()
createPersonaTx := struct {
PersonaTag string
Expand All @@ -102,39 +107,42 @@ func cardinalCreatePersona(ctx context.Context, nk runtime.NakamaModule, persona

key, nonce, err := getPrivateKeyAndANonce(ctx, nk)
if err != nil {
return 0, fmt.Errorf("unable to get the private key or a nonce: %w", err)
return "", 0, fmt.Errorf("unable to get the private key or a nonce: %w", err)
}

signedPayload, err := sign.NewSignedPayload(key, personaTag, globalNamespace, nonce, createPersonaTx)
signedPayload, err := sign.NewSystemSignedPayload(key, globalNamespace, nonce, createPersonaTx)
if err != nil {
return 0, fmt.Errorf("unable to create signed payload: %w", err)
return "", 0, fmt.Errorf("unable to create signed payload: %w", err)
}

buf, err := signedPayload.Marshal()
if err != nil {
return 0, fmt.Errorf("unable to marshal signed payload: %w", err)
return "", 0, fmt.Errorf("unable to marshal signed payload: %w", err)
}

req, err := http.NewRequestWithContext(ctx, "POST", makeURL(createPersonaEndpoint), bytes.NewReader(buf))
if err != nil {
return 0, fmt.Errorf("unable to make request to %q: %w", createPersonaEndpoint, err)
return "", 0, fmt.Errorf("unable to make request to %q: %w", createPersonaEndpoint, err)
}

resp, err := doRequest(req)
if err != nil {
return 0, err
return "", 0, err
}
if code := resp.StatusCode; code != 200 {
buf, err := io.ReadAll(resp.Body)
return "", 0, fmt.Errorf("create persona response is not 200. code %v, body: %v, err: %v", code, string(buf), err)

}
createPersonaResponse := struct {
Status string
Tick uint64
}{}
var createPersonaResponse txResponse

if err := json.NewDecoder(resp.Body).Decode(&createPersonaResponse); err != nil {
return 0, fmt.Errorf("unable to decode response: %w", err)
return "", 0, fmt.Errorf("unable to decode response: %w", err)
}
if s := createPersonaResponse.Status; s != "ok" {
return 0, fmt.Errorf("create persona failed with status %q", s)
if createPersonaResponse.TxHash == "" {
return "", 0, fmt.Errorf("tx response does not have a tx hash")
}
return createPersonaResponse.Tick, nil
return createPersonaResponse.TxHash, createPersonaResponse.Tick, nil
}

func cardinalQueryPersonaSigner(ctx context.Context, personaTag string, tick uint64) (signerAddress string, err error) {
Expand Down
7 changes: 1 addition & 6 deletions nakama/dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,11 @@ type TransactionReceiptsReply struct {
}

type Receipt struct {
ID TxID `json:"id"`
TxHash string `json:"tx_hash"`
Result map[string]any `json:"result"`
Errors []string `json:"errors"`
}

type TxID struct {
PersonaTag string
Index uint64
}

// receiptsDispatcher continually polls Cardinal for transaction receipts and dispatches them to any subscribed
// channels. The subscribed channels are stored in the sync.Map.
type receiptsDispatcher struct {
Expand Down
Loading

0 comments on commit dc30649

Please sign in to comment.