diff --git a/cardinal/go.mod b/cardinal/go.mod index 84c6ba0..bd0b8de 100644 --- a/cardinal/go.mod +++ b/cardinal/go.mod @@ -4,7 +4,7 @@ go 1.22.1 require ( github.com/rs/zerolog v1.32.0 - pkg.world.dev/world-engine/cardinal v1.2.6-beta + pkg.world.dev/world-engine/cardinal v1.3.2 ) require ( diff --git a/cardinal/go.sum b/cardinal/go.sum index a7b213d..8f203e5 100644 --- a/cardinal/go.sum +++ b/cardinal/go.sum @@ -373,6 +373,8 @@ pkg.world.dev/world-engine/assert v1.0.0 h1:vD6+QLT1pvQa86FPFi+wGcVA7PEwTGndXr+P pkg.world.dev/world-engine/assert v1.0.0/go.mod h1:bwA9YZ40+Tte6GUKibfqByxBLLt+54zjjFako8cpSuU= pkg.world.dev/world-engine/cardinal v1.2.6-beta h1:nbgfqpvq0hcni5dzpCTDwCEH3sO6p/J+yqfxhfKwtzU= pkg.world.dev/world-engine/cardinal v1.2.6-beta/go.mod h1:G5XveSFC1FNzybm+P6ONqhAHJLwQxLbp5vRcMGWuER4= +pkg.world.dev/world-engine/cardinal v1.3.2 h1:pzS33m8NwxMblyDoXnE6ChFkh02w0sof2NRzoX/dHsc= +pkg.world.dev/world-engine/cardinal v1.3.2/go.mod h1:G5XveSFC1FNzybm+P6ONqhAHJLwQxLbp5vRcMGWuER4= pkg.world.dev/world-engine/rift v1.1.0-beta.0.20240402214846-de1fc179818a h1:P9pf6itjPBlooxj8p0jTkIY7ozcjSgCYsuh/BkbL56o= pkg.world.dev/world-engine/rift v1.1.0-beta.0.20240402214846-de1fc179818a/go.mod h1:XAD40g4r3qOp3CTa66JBY+ACEUtjr01loyHiUZIheN8= pkg.world.dev/world-engine/sign v1.0.1-beta h1:ZwVeJYdf88t6qIHPurbdKJKVxUN0dfp0gSF7OCA9xt8= diff --git a/cardinal/init_test.go b/cardinal/init_test.go index 0adc81d..5f7cbef 100644 --- a/cardinal/init_test.go +++ b/cardinal/init_test.go @@ -25,21 +25,22 @@ func TestInitSystem_SpawnDefaultPlayersSystem_DefaultPlayersAreSpawned(t *testin wCtx := cardinal.NewReadOnlyWorldContext(tf.World) foundPlayers := map[string]bool{} - searchErr := cardinal.NewSearch(wCtx, filter.Contains(component.Health{})).Each(func(id types.EntityID) bool { - player, err := cardinal.GetComponent[component.Player](wCtx, id) - if err != nil { - t.Fatalf("failed to get player: %v", err) - } - health, err := cardinal.GetComponent[component.Health](wCtx, id) - if err != nil { - t.Fatalf("failed to get health: %v", err) - } - if health.HP < 100 { - t.Fatalf("new player should have at least 100 health; got %v", health.HP) - } - foundPlayers[player.Nickname] = true - return true - }) + searchErr := cardinal.NewSearch().Entity(filter.Contains(filter.Component[component.Health]())). + Each(wCtx, func(id types.EntityID) bool { + player, err := cardinal.GetComponent[component.Player](wCtx, id) + if err != nil { + t.Fatalf("failed to get player: %v", err) + } + health, err := cardinal.GetComponent[component.Health](wCtx, id) + if err != nil { + t.Fatalf("failed to get health: %v", err) + } + if health.HP < 100 { + t.Fatalf("new player should have at least 100 health; got %v", health.HP) + } + foundPlayers[player.Nickname] = true + return true + }) if searchErr != nil { t.Fatalf("failed to perform search: %v", searchErr) } diff --git a/cardinal/query/player_health.go b/cardinal/query/player_health.go index 6f190ef..117adb6 100644 --- a/cardinal/query/player_health.go +++ b/cardinal/query/player_health.go @@ -22,10 +22,9 @@ type PlayerHealthResponse struct { func PlayerHealth(world cardinal.WorldContext, req *PlayerHealthRequest) (*PlayerHealthResponse, error) { var playerHealth *comp.Health var err error - searchErr := cardinal.NewSearch( - world, - filter.Exact(comp.Player{}, comp.Health{})). - Each(func(id types.EntityID) bool { + searchErr := cardinal.NewSearch().Entity( + filter.Exact(filter.Component[comp.Player](), filter.Component[comp.Health]())). + Each(world, func(id types.EntityID) bool { var player *comp.Player player, err = cardinal.GetComponent[comp.Player](world, id) if err != nil { diff --git a/cardinal/system/regen.go b/cardinal/system/regen.go index 7003fef..767bd8f 100644 --- a/cardinal/system/regen.go +++ b/cardinal/system/regen.go @@ -11,15 +11,17 @@ import ( // RegenSystem replenishes the player's HP at every tick. // This provides an example of a system that doesn't rely on a transaction to update a component. func RegenSystem(world cardinal.WorldContext) error { - return cardinal.NewSearch(world, filter.Exact(comp.Player{}, comp.Health{})).Each(func(id types.EntityID) bool { - health, err := cardinal.GetComponent[comp.Health](world, id) - if err != nil { + return cardinal.NewSearch().Entity( + filter.Exact(filter.Component[comp.Player](), filter.Component[comp.Health]())). + Each(world, func(id types.EntityID) bool { + health, err := cardinal.GetComponent[comp.Health](world, id) + if err != nil { + return true + } + health.HP++ + if err := cardinal.SetComponent[comp.Health](world, id, health); err != nil { + return true + } return true - } - health.HP++ - if err := cardinal.SetComponent[comp.Health](world, id, health); err != nil { - return true - } - return true - }) + }) } diff --git a/cardinal/system/utils.go b/cardinal/system/utils.go index 0097515..40ed01c 100644 --- a/cardinal/system/utils.go +++ b/cardinal/system/utils.go @@ -15,7 +15,8 @@ func queryTargetPlayer(world cardinal.WorldContext, targetNickname string) (type var playerID types.EntityID var playerHealth *comp.Health var err error - searchErr := cardinal.NewSearch(world, filter.Exact(comp.Player{}, comp.Health{})).Each( + searchErr := cardinal.NewSearch().Entity( + filter.Exact(filter.Component[comp.Player](), filter.Component[comp.Health]())).Each(world, func(id types.EntityID) bool { var player *comp.Player player, err = cardinal.GetComponent[comp.Player](world, id) diff --git a/cardinal/system_test.go b/cardinal/system_test.go index b2b6192..85f4304 100644 --- a/cardinal/system_test.go +++ b/cardinal/system_test.go @@ -3,6 +3,8 @@ package main import ( "testing" + "gotest.tools/v3/assert" + "pkg.world.dev/world-engine/cardinal" "pkg.world.dev/world-engine/cardinal/receipt" "pkg.world.dev/world-engine/cardinal/search/filter" @@ -58,13 +60,21 @@ func TestSystem_PlayerSpawnerSystem_CanCreatePlayer(t *testing.T) { wCtx := cardinal.NewReadOnlyWorldContext(tf.World) // This search demonstrates the use of a "Where" clause, which limits the search results to only the entity IDs // that end up returning true from the anonymous function. In this case, we're looking for a specific nickname. - id := cardinal.NewSearch(wCtx, filter.All()).Where(func(id types.EntityID) bool { + acc := make([]types.EntityID, 0) + err := cardinal.NewSearch().Entity(filter.All()).Each(wCtx, func(id types.EntityID) bool { player, err := cardinal.GetComponent[component.Player](wCtx, id) if err != nil { t.Fatalf("failed to get player component: %v", err) } - return player.Nickname == nickname - }).MustFirst() + if player.Nickname == nickname { + acc = append(acc, id) + return false + } + return true + }) + assert.NilError(t, err) + assert.Equal(t, len(acc), 1) + id := acc[0] health, err := cardinal.GetComponent[component.Health](wCtx, id) if err != nil { @@ -106,7 +116,7 @@ func TestSystem_AttackSystem_AttackingTargetReducesTheirHealth(t *testing.T) { var found bool // This search demonstrates the "Each" pattern. Every entity ID is considered, and as long as the anonymous // function return true, the search will continue. - searchErr := cardinal.NewSearch(wCtx, filter.All()).Each(func(id types.EntityID) bool { + searchErr := cardinal.NewSearch().Entity(filter.All()).Each(wCtx, func(id types.EntityID) bool { player, err := cardinal.GetComponent[component.Player](wCtx, id) if err != nil { t.Fatalf("failed to get player component for %v", id)