Skip to content

Commit

Permalink
Feat/buildings relocate (#15)
Browse files Browse the repository at this point in the history
* Added CreateEffectSystem; Added TileID to Building;

* Added Effects spawner

* Fixed effects spawning procedure; Removed template systems;

* Reverted major farming speed to 50

* Reverted time durations counting procedure

* Added buildings relocate
  • Loading branch information
k-karuna authored Jul 8, 2024
1 parent 12a2553 commit c1f4e8d
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 57 deletions.
2 changes: 2 additions & 0 deletions cardinal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func MustInitWorld(w *cardinal.World) {
cardinal.RegisterMessage[msg.CreateBuildingMsg, msg.CreateBuildingResult](w, "create-building"),
cardinal.RegisterMessage[msg.DeleteBuildingMsg, msg.DeleteBuildingResult](w, "delete-building"),
cardinal.RegisterMessage[msg.CreateEffectMsg, msg.CreateEffectResult](w, "create-effect"),
cardinal.RegisterMessage[msg.RelocateBuildingMsg, msg.RelocateBuildingResult](w, "relocate-building"),
)

// Register queries
Expand Down Expand Up @@ -80,6 +81,7 @@ func MustInitWorld(w *cardinal.World) {
system.DeleteBuildingSystem,
system.CreateEffectSystem,
system.EffectsSpawnerSystem,
system.RelocateBuildingSystem,
))
}

Expand Down
10 changes: 10 additions & 0 deletions cardinal/msg/relocate_building.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package msg

type RelocateBuildingMsg struct {
TileIndexFrom int `json:"tileIndexFrom"`
TileIndexTo int `json:"tileIndexTo"`
}

type RelocateBuildingResult struct {
Success bool `json:"success"`
}
47 changes: 0 additions & 47 deletions cardinal/system/create_building.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package system

import (
"errors"
"fmt"

"pkg.world.dev/world-engine/cardinal"
Expand Down Expand Up @@ -77,49 +76,3 @@ func CreateBuildingSystem(world cardinal.WorldContext) error {
return msg.CreateBuildingResult{Success: true}, nil
})
}

func SubtractResources(world cardinal.WorldContext, resources []comp.Resource, personaTag string) error {
playerResourcesEntityID, playerResources, _ := QueryComponent[comp.PlayerResources](
world,
personaTag,
filter.Component[comp.Player](),
filter.Component[comp.PlayerResources](),
)

for _, resource := range resources {
var playerResource *comp.Resource
var err error
if playerResource, err = GetResourceByType(playerResources, resource.Type); err != nil {
return fmt.Errorf("can't get player resource %s: %w", resource.Type, err)
}
if playerResource.Amount < resource.Amount {
return fmt.Errorf("not enough resource %s", resource.Type)
}

playerResource.Amount -= resource.Amount
SetResourceByType(playerResources, *playerResource)

if err := cardinal.SetComponent(world, playerResourcesEntityID, playerResources); err != nil {
return fmt.Errorf("failed to update player resource: %w", err)
}
}

return nil
}

func GetResourceByType(playerResources *comp.PlayerResources, resourceType comp.ResourceType) (*comp.Resource, error) {
for i := range playerResources.Resources {
if playerResources.Resources[i].Type == resourceType {
return &playerResources.Resources[i], nil
}
}
return nil, errors.New("resource not found")
}

func SetResourceByType(playerResources *comp.PlayerResources, newResource comp.Resource) {
for i := range playerResources.Resources {
if playerResources.Resources[i].Type == newResource.Type {
playerResources.Resources[i] = newResource
}
}
}
10 changes: 0 additions & 10 deletions cardinal/system/create_effect.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package system

import (
"errors"
"fmt"

"pkg.world.dev/world-engine/cardinal"
Expand Down Expand Up @@ -78,12 +77,3 @@ func CreateEffectSystem(world cardinal.WorldContext) error {
return msg.CreateEffectResult{Success: true}, nil
})
}

func FindBuildingByTileID(buildings []*comp.Building, tileID int) (*comp.Building, int, error) {
for index, building := range buildings {
if building.TileID == tileID {
return building, index, nil
}
}
return nil, -1, errors.New("building with given tileID not found")
}
88 changes: 88 additions & 0 deletions cardinal/system/relocate_building.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package system

import (
"fmt"

"pkg.world.dev/world-engine/cardinal"
"pkg.world.dev/world-engine/cardinal/search/filter"

comp "oceanus-shard/component"
"oceanus-shard/msg"
)

// RelocateBuildingSystem relocates buildings.
func RelocateBuildingSystem(world cardinal.WorldContext) error {
return cardinal.EachMessage[msg.RelocateBuildingMsg, msg.RelocateBuildingResult](
world,
func(request cardinal.TxData[msg.RelocateBuildingMsg]) (msg.RelocateBuildingResult, error) {
mapEntityID, playerMap, _ := QueryComponent[comp.TileMap](
world,
request.Tx.PersonaTag,
filter.Component[comp.Player](),
filter.Component[comp.TileMap](),
)

playerBuildingsEntityIDs, playerBuildings, _ := QueryAllComponents[comp.Building](
world,
request.Tx.PersonaTag,
filter.Component[comp.Player](),
filter.Component[comp.Building](),
)

if playerMap == nil {
return msg.RelocateBuildingResult{Success: false},
fmt.Errorf("failed to relocate building, this player did not have tilemap")
}

player, _ := cardinal.GetComponent[comp.Player](world, mapEntityID)
if player.Nickname != request.Tx.PersonaTag {
return msg.RelocateBuildingResult{Success: false}, fmt.Errorf("can't relocate another player building")
}

tiles := *playerMap.Tiles

if request.Msg.TileIndexFrom < 0 || request.Msg.TileIndexFrom >= len(tiles) ||
request.Msg.TileIndexTo < 0 || request.Msg.TileIndexTo >= len(tiles) {
return msg.RelocateBuildingResult{Success: false}, fmt.Errorf("index of tiles out of range")
}

tileFrom := &(*playerMap.Tiles)[request.Msg.TileIndexFrom]
if tileFrom.Building == nil {
return msg.RelocateBuildingResult{Success: false},
fmt.Errorf("failed to relocate building, source tile didn't have buildings")
}

tileTo := &(*playerMap.Tiles)[request.Msg.TileIndexTo]
if tileTo.Building != nil {
return msg.RelocateBuildingResult{Success: false},
fmt.Errorf("failed to relocate building, target tile already have buildings")
}

if tileTo.Tile != comp.BuildingConfigs[tileFrom.Building.Type].TileType {
return msg.RelocateBuildingResult{Success: false},
fmt.Errorf("failed to relocate building, target tile type and building tiletype mismatch")
}

fromBuilding, fromBuildingIndex, err := FindBuildingByTileID(playerBuildings, tileFrom.Building.TileID)
if err != nil {
return msg.RelocateBuildingResult{Success: false}, err
}

fromBuilding.TileID = request.Msg.TileIndexTo
tileFrom.Building = nil
tileTo.Building = fromBuilding

if err := cardinal.SetComponent(
world,
playerBuildingsEntityIDs[fromBuildingIndex],
fromBuilding); err != nil {
return msg.RelocateBuildingResult{Success: false}, err
}

if err := cardinal.SetComponent(world, mapEntityID, playerMap); err != nil {
return msg.RelocateBuildingResult{Success: false}, err
}

return msg.RelocateBuildingResult{Success: true}, nil
})
}
56 changes: 56 additions & 0 deletions cardinal/system/query_utils.go → cardinal/system/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package system

import (
"errors"
"fmt"
comp "oceanus-shard/component"
"reflect"
Expand Down Expand Up @@ -87,3 +88,58 @@ func QueryAllComponents[T types.Component](
}
return entityIDs, targetComponents, err
}

func FindBuildingByTileID(buildings []*comp.Building, tileID int) (*comp.Building, int, error) {
for index, building := range buildings {
if building.TileID == tileID {
return building, index, nil
}
}
return nil, -1, errors.New("building with given tileID not found")
}

func SubtractResources(world cardinal.WorldContext, resources []comp.Resource, personaTag string) error {
playerResourcesEntityID, playerResources, _ := QueryComponent[comp.PlayerResources](
world,
personaTag,
filter.Component[comp.Player](),
filter.Component[comp.PlayerResources](),
)

for _, resource := range resources {
var playerResource *comp.Resource
var err error
if playerResource, err = GetResourceByType(playerResources, resource.Type); err != nil {
return fmt.Errorf("can't get player resource %s: %w", resource.Type, err)
}
if playerResource.Amount < resource.Amount {
return fmt.Errorf("not enough resource %s", resource.Type)
}

playerResource.Amount -= resource.Amount
SetResourceByType(playerResources, *playerResource)

if err := cardinal.SetComponent(world, playerResourcesEntityID, playerResources); err != nil {
return fmt.Errorf("failed to update player resource: %w", err)
}
}

return nil
}

func GetResourceByType(playerResources *comp.PlayerResources, resourceType comp.ResourceType) (*comp.Resource, error) {
for i := range playerResources.Resources {
if playerResources.Resources[i].Type == resourceType {
return &playerResources.Resources[i], nil
}
}
return nil, errors.New("resource not found")
}

func SetResourceByType(playerResources *comp.PlayerResources, newResource comp.Resource) {
for i := range playerResources.Resources {
if playerResources.Resources[i].Type == newResource.Type {
playerResources.Resources[i] = newResource
}
}
}

0 comments on commit c1f4e8d

Please sign in to comment.