Skip to content

Commit

Permalink
♻️ Add Entity change direction System
Browse files Browse the repository at this point in the history
  • Loading branch information
ImNotAVirus committed Sep 21, 2023
1 parent 9826907 commit ca217ac
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 37 deletions.
5 changes: 5 additions & 0 deletions apps/game_service/lib/game_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ defmodule GameService do
alias GameService.PlayerComponents.EndpointComponent

def entity_type(%PlayerBundle{}), do: :character
def entity_type(%Entity{id: {:player, _}}), do: :character

def entity_id(%PlayerBundle{id: id}), do: id
def entity_id(%Entity{id: {_, id}}), do: id

def entity_type_to_prefix(:character), do: :player

def load_bundle(%Entity{id: {:player, _}} = entity, components) do
PlayerBundle.load(entity, components)
Expand Down
11 changes: 9 additions & 2 deletions apps/game_service/lib/game_service/events/direction_changed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ defmodule GameService.Events.DirectionChanged do
@moduledoc """
Event triggered when an Entity change his direction.
"""
use ElvenGard.ECS.Event, fields: []

@type t :: %__MODULE__{}
use ElvenGard.ECS.Event, fields: [:entity_type, :entity_id, :value]

alias ElvenEnums.EntityEnums

@type t :: %__MODULE__{
entity_type: EntityEnums.entity_type_keys(),
entity_id: non_neg_integer(),
value: EntityEnums.direction_type_keys()
}
end
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule GameService.StaticMapPartition do
defp systems() do
[
GameService.EntityVisibilitySystem,
GameService.EntityMapActionSystem
GameService.EntityMapActionsSystem
]
end
end
34 changes: 0 additions & 34 deletions apps/game_service/lib/game_service/systems/entity_map_action.ex

This file was deleted.

71 changes: 71 additions & 0 deletions apps/game_service/lib/game_service/systems/entity_map_actions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
defmodule GameService.EntityMapActionsSystem do
@moduledoc """
TODO: Documentation for GameService.EntityMapActionsSystem
"""

use ElvenGard.ECS.System,
lock_components: [
GameService.EntityComponents.PositionComponent,
GameService.EntityComponents.DirectionComponent,
GameService.EntityComponents.LevelComponent,
GameService.PlayerComponents.HeroLevelComponent,
GameService.EntityComponents.CombatComponent,
# GameService.EntityComponents.BuffComponent,
GameService.EntityComponents.SpeedComponent,
GameService.EntityComponents.SittingComponent
],
event_subscriptions: [
GameService.Events.DirectionChanged,
GameService.Events.EntityInfoRequest,
GameService.Events.Movement,
GameService.Events.Sitting
]

require Logger

alias ElvenGard.ECS.{Command, Query}

alias GameService.EntityComponents, as: E

alias GameService.Events.{
DirectionChanged
# EntityInfoRequest,
# Movement,
# Sitting
}

# System behaviour

@impl true
def run(%DirectionChanged{} = event, _delta) do
%DirectionChanged{
entity_type: entity_type,
entity_id: entity_id,
value: value
} = event

ecs_type = GameService.entity_type_to_prefix(entity_type)
ecs_id = {ecs_type, entity_id}

# Check if the Entity exists
with {:ok, entity} <- Query.fetch_entity(ecs_id),
# Then update it's DirectionComponent
{:ok, _} <- Command.update_component(entity, E.DirectionComponent, value: value),
# Then get the current map
{:ok, position} <- Query.fetch_component(entity, E.PositionComponent) do
# Finally, notify all players on map
event = {:direction_changed, entity_type, entity_id, value}
GameService.System.map_event(event, position)
else
e ->
Logger.error(
"[#{inspect(__MODULE__)}] Can't set direction, " <>
"got #{inspect(e)} for #{inspect(event)}"
)
end
end

def run(event, _delta) do
Logger.warn("#{inspect(__MODULE__)} unhandled event #{inspect(event)}")
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule GameService.EntityMapActionsSystemTest do
use GameService.EntityCase, async: true

alias ElvenGard.ECS.Query

alias GameService.Events, as: Evt
alias GameService.EntityMapActionsSystem
alias GameService.EntityComponents, as: E
alias GameService.PlayerComponents, as: P

## Tests

test "system notify on Entity change direction" do
# Register our process to receive message
ref = make_ref()
position = %E.PositionComponent{map_ref: ref}
endpoint = %P.EndpointComponent{pid: self()}
_ = spawn_player(components: [endpoint, position])

# Create our fake Entity with a DirectionComponent
direction = %E.DirectionComponent{value: :south}
entity = spawn_player(components: [position, direction])

# Call our System with a DirectionChanged event
event = %Evt.DirectionChanged{
entity_type: :character,
entity_id: GameService.entity_id(entity),
value: :north
}

_ = EntityMapActionsSystem.run(event, 0)

# Check that the DirectionComponent was updated
{:ok, component} = Query.fetch_component(entity, E.DirectionComponent)
assert %E.DirectionComponent{value: :north} = component

# # We should receive an event
assert_receive {:direction_changed, entity_type, entity_id, value}
assert entity_type == event.entity_type
assert entity_id == event.entity_id
assert value == event.value
end
end

0 comments on commit ca217ac

Please sign in to comment.