Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added systems and msgs for movement component #3

Open
wants to merge 1 commit into
base: 11-11-sjamble_feature-query-msg
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cardinal/component/movement.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ var Directions = map[int]Direction{
}

type Location struct {
X float32
Y float32
X float64
Y float64
}

type Movement struct {
CurrentDirection Direction
Velocity float32
Velocity float64
CurrentLocation Location
}

Expand Down
4 changes: 4 additions & 0 deletions cardinal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ func MustInitWorld(w *cardinal.World) {
Must(
cardinal.RegisterComponent[component.Player](w),
cardinal.RegisterComponent[component.Health](w),
cardinal.RegisterComponent[component.Movement](w),
)

// Register messages (user action)
// NOTE: You must register your transactions here for it to be executed.
Must(
cardinal.RegisterMessage[msg.CreatePlayerMsg, msg.CreatePlayerResult](w, "create-player"),
cardinal.RegisterMessage[msg.AttackPlayerMsg, msg.AttackPlayerMsgReply](w, "attack-player"),
cardinal.RegisterMessage[msg.MovementPlayerMsg, msg.MovementPlayerMsgReply](w, "movement-player"),
)

// Register queries
Expand All @@ -63,6 +65,8 @@ func MustInitWorld(w *cardinal.World) {
system.AttackSystem,
system.RegenSystem,
system.PlayerSpawnerSystem,
system.MovementValidationSystem,
system.MovementSystem,
))

Must(cardinal.RegisterInitSystems(w,
Expand Down
14 changes: 14 additions & 0 deletions cardinal/msg/movement_player.go
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
package msg

type MovementPlayerMsg struct {
TargetNickname string `json:"target"`
Velocity int `json:"velocity"`
Direction int `json:"direction"`
LocationX float64 `json:"locationX"`
LocationY float64 `json:"locationY"`
}

type MovementPlayerMsgReply struct {
LocationX float64 `json:"locationX"`
LocationY float64 `json:"locationY"`
IsValid bool `json:"isValid"`
}
30 changes: 18 additions & 12 deletions cardinal/system/movement_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import (
"fmt"
"math"
"pkg.world.dev/world-engine/cardinal"
"pkg.world.dev/world-engine/cardinal/search/filter"
"pkg.world.dev/world-engine/cardinal/types"
Expand All @@ -20,8 +21,8 @@
}

// TODO: How to get delta time?
movement.CurrentLocation.X += movement.Velocity * float32(movement.CurrentDirection.X)
movement.CurrentLocation.Y += movement.Velocity * float32(movement.CurrentDirection.Y)
movement.CurrentLocation.X += movement.Velocity * float64(movement.CurrentDirection.X)
movement.CurrentLocation.Y += movement.Velocity * float64(movement.CurrentDirection.Y)

if err := cardinal.SetComponent[comp.Movement](world, id, movement); err != nil {
return true
Expand All @@ -31,19 +32,24 @@
}

func MovementValidationSystem(world cardinal.WorldContext) error {
return cardinal.EachMessage[msg.AttackPlayerMsg, msg.AttackPlayerMsgReply](
return cardinal.EachMessage[msg.MovementPlayerMsg, msg.MovementPlayerMsgReply](
world,
func(attack cardinal.TxData[msg.AttackPlayerMsg]) (msg.AttackPlayerMsgReply, error) {
playerID, playerHealth, err := queryTargetPlayer(world, attack.Msg.TargetNickname)
func(movement cardinal.TxData[msg.MovementPlayerMsg]) (msg.MovementPlayerMsgReply, error) {
playerID, playerMovementData, err := queryTargetPlayerMovementData(world, movement.Msg.TargetNickname)
if err != nil {
return msg.AttackPlayerMsgReply{}, fmt.Errorf("failed to inflict damage: %w", err)
return msg.MovementPlayerMsgReply{}, fmt.Errorf("failed to update movement: %w", err)
}

playerHealth.HP -= AttackDamage
if err := cardinal.SetComponent[comp.Health](world, playerID, playerHealth); err != nil {
return msg.AttackPlayerMsgReply{}, fmt.Errorf("failed to inflict damage: %w", err)
const errorTolerance float64 = 0.001
if math.Abs(playerMovementData.CurrentLocation.X-movement.Msg.LocationX) > errorTolerance ||
math.Abs(playerMovementData.CurrentLocation.Y-movement.Msg.LocationY) > errorTolerance {
return msg.MovementPlayerMsgReply{IsValid: false, LocationX: playerMovementData.CurrentLocation.X, LocationY: playerMovementData.CurrentLocation.Y}, nil

Check failure on line 45 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

line is 156 characters (lll)

Check failure on line 45 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

line is 156 characters (lll)
} else {

Check warning on line 46 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)

Check warning on line 46 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
playerMovementData.CurrentLocation.X = movement.Msg.LocationX
playerMovementData.CurrentLocation.Y = movement.Msg.LocationY
if err := cardinal.SetComponent[comp.Movement](world, playerID, playerMovementData); err != nil {
return msg.MovementPlayerMsgReply{IsValid: false, LocationX: playerMovementData.CurrentLocation.X, LocationY: playerMovementData.CurrentLocation.Y}, fmt.Errorf("failed to update movement: %w", err)

Check failure on line 50 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

line is 202 characters (lll)

Check failure on line 50 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

line is 202 characters (lll)
}
return msg.MovementPlayerMsgReply{IsValid: true, LocationX: playerMovementData.CurrentLocation.X, LocationY: playerMovementData.CurrentLocation.Y}, nil

Check failure on line 52 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

line is 155 characters (lll)

Check failure on line 52 in cardinal/system/movement_system.go

View workflow job for this annotation

GitHub Actions / Go

line is 155 characters (lll)
}

return msg.AttackPlayerMsgReply{Damage: AttackDamage}, nil
})
}
15 changes: 15 additions & 0 deletions cardinal/system/player_spawner.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ const (
InitialHP = 100
)

const (
InitialXLocation = 0
InitialYLocation = 0
InitialVelocity = 0
InitialDirection = 0
)

// PlayerSpawnerSystem spawns players based on `CreatePlayer` transactions.
// This provides an example of a system that creates a new entity.
func PlayerSpawnerSystem(world cardinal.WorldContext) error {
Expand All @@ -22,6 +29,14 @@ func PlayerSpawnerSystem(world cardinal.WorldContext) error {
id, err := cardinal.Create(world,
comp.Player{Nickname: create.Msg.Nickname},
comp.Health{HP: InitialHP},
comp.Movement{
CurrentLocation: comp.Location{X: InitialXLocation, Y: InitialYLocation},
Velocity: InitialVelocity,
CurrentDirection: comp.Direction{
comp.Directions[InitialDirection].X,
comp.Directions[InitialDirection].Y,
},
},
)
if err != nil {
return msg.CreatePlayerResult{}, fmt.Errorf("error creating player: %w", err)
Expand Down
39 changes: 39 additions & 0 deletions cardinal/system/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)

// queryTargetPlayer queries for the target player's entity ID and health component.
func queryTargetPlayer(world cardinal.WorldContext, targetNickname string) (types.EntityID, *comp.Health, error) {

Check failure on line 14 in cardinal/system/utils.go

View workflow job for this annotation

GitHub Actions / Go

14-51 lines are duplicate of `system/utils.go:53-90` (dupl)

Check failure on line 14 in cardinal/system/utils.go

View workflow job for this annotation

GitHub Actions / Go

14-51 lines are duplicate of `system/utils.go:53-90` (dupl)
var playerID types.EntityID
var playerHealth *comp.Health
var err error
Expand Down Expand Up @@ -49,3 +49,42 @@

return playerID, playerHealth, err
}

func queryTargetPlayerMovementData(world cardinal.WorldContext, targetNickname string) (types.EntityID, *comp.Movement, error) {

Check failure on line 53 in cardinal/system/utils.go

View workflow job for this annotation

GitHub Actions / Go

53-90 lines are duplicate of `system/utils.go:14-51` (dupl)

Check failure on line 53 in cardinal/system/utils.go

View workflow job for this annotation

GitHub Actions / Go

53-90 lines are duplicate of `system/utils.go:14-51` (dupl)
var playerID types.EntityID
var playerMovementComponent *comp.Movement
var err error
searchErr := cardinal.NewSearch().Entity(
filter.Exact(filter.Component[comp.Player](), filter.Component[comp.Movement]())).Each(world,
func(id types.EntityID) bool {
var player *comp.Player
player, err = cardinal.GetComponent[comp.Player](world, id)
if err != nil {
return false
}

// Terminates the search if the player is found
if player.Nickname == targetNickname {
playerID = id
playerMovementComponent, err = cardinal.GetComponent[comp.Movement](world, id)
if err != nil {
return false
}
return false
}

// Continue searching if the player is not the target player
return true
})
if searchErr != nil {
return 0, nil, err
}
if err != nil {
return 0, nil, err
}
if playerMovementComponent == nil {
return 0, nil, fmt.Errorf("player %q does not exist", targetNickname)
}

return playerID, playerMovementComponent, err
}
Loading