Skip to content

Commit

Permalink
♻️ Small refacto
Browse files Browse the repository at this point in the history
  • Loading branch information
ImNotAVirus committed Sep 21, 2023
1 parent 765bbeb commit 9826907
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 25 deletions.
24 changes: 24 additions & 0 deletions apps/game_service/lib/game_service/system.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule GameService.System do
@moduledoc """
TODO: Documentation for GameService.System
"""

alias ElvenGard.ECS.Query

alias GameService.EntityComponents.PositionComponent
alias GameService.PlayerComponents.EndpointComponent

@spec map_event(any(), PositionComponent.t()) :: any()
def map_event(event, %PositionComponent{map_ref: map_ref}) do
# Get all endpoints on the current map
endpoints =
Query.select(
EndpointComponent,
with: [{PositionComponent, [{:==, :map_ref, map_ref}]}]
)
|> Query.all()

# Broadcast the entity spawn to players
GameService.broadcast_to(event, endpoints)
end
end
22 changes: 6 additions & 16 deletions apps/game_service/lib/game_service/systems/entity_visibility.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,31 @@ defmodule GameService.EntityVisibilitySystem do
GameService.Events.EntityDespawned
]

alias ElvenGard.ECS.Query
alias GameService.Events.{EntitySpawned, EntityDespawned}
alias GameService.PlayerComponents.EndpointComponent
alias GameService.EntityComponents.PositionComponent
alias GameService.EntityComponents, as: E

# System behaviour

@impl true
def run(%EntitySpawned{entity: entity, components: components}, _delta) do
components
|> Enum.find(&match?(%PositionComponent{}, &1))
|> Enum.find(&match?(%E.PositionComponent{}, &1))
|> then(&broadcast_event(:entity_spawn, entity, components, &1))
end

def run(%EntityDespawned{entity: entity, components: components}, _delta) do
components
|> Enum.find(&match?(%PositionComponent{}, &1))
|> Enum.find(&match?(%E.PositionComponent{}, &1))
|> then(&broadcast_event(:entity_despawn, entity, components, &1))
end

## Helpers

defp broadcast_event(event, entity, components, %PositionComponent{map_ref: map_ref}) do
# Get all endpoints on the current map
endpoints =
Query.select(
EndpointComponent,
with: [{PositionComponent, [{:==, :map_ref, map_ref}]}]
)
|> Query.all()

defp broadcast_event(event_name, entity, components, %E.PositionComponent{} = position) do
# Transform the entity + components to a bundle
bundle = GameService.preload_bundle(entity, components)

# Broadcast the entity spawn to players
GameService.broadcast_to({event, bundle}, endpoints)
# Send Events
GameService.System.map_event({event_name, bundle}, position)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ defmodule GameService.EntityVisibilitySystemTest do
use GameService.EntityCase, async: true

alias GameService.PlayerBundle
alias GameService.Events.{EntitySpawned, EntityDespawned}
alias GameService.PlayerComponents.EndpointComponent
alias GameService.EntityComponents.PositionComponent
alias GameService.EntityVisibilitySystem
alias GameService.Events, as: Evt
alias GameService.EntityComponents, as: E
alias GameService.PlayerComponents, as: P

## Tests

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

# Call our System with a EntitySpawned event
entity = spawn_player(components: [position])
event = %EntitySpawned{entity: entity, components: [position]}
event = %Evt.EntitySpawned{entity: entity, components: [position]}
_ = EntityVisibilitySystem.run(event, 0)

# We should receive an event
Expand All @@ -30,13 +30,13 @@ defmodule GameService.EntityVisibilitySystemTest do
test "system notify on Entity despawn" do
# Register our process to receive message
ref = make_ref()
position = %PositionComponent{map_ref: ref}
endpoint = %EndpointComponent{pid: self()}
position = %E.PositionComponent{map_ref: ref}
endpoint = %P.EndpointComponent{pid: self()}
_ = spawn_player(components: [endpoint, position])

# Call our System with a EntitySpawned event
entity = spawn_player(components: [position])
event = %EntityDespawned{entity: entity, components: [position]}
event = %Evt.EntityDespawned{entity: entity, components: [position]}
_ = EntityVisibilitySystem.run(event, 0)

# We should receive an event
Expand Down

0 comments on commit 9826907

Please sign in to comment.