Add GameCoordinator logic for finding or creating games
All checks were successful
Build & Test / nix-build (push) Successful in 1m14s
All checks were successful
Build & Test / nix-build (push) Successful in 1m14s
This commit is contained in:
parent
99af42f42c
commit
11db275db2
@ -26,7 +26,8 @@ defmodule Amethyst.Application do
|
||||
children = [
|
||||
{Task.Supervisor, name: Amethyst.ConnectionSupervisor},
|
||||
{Amethyst.Keys, 1024},
|
||||
{Amethyst.GameRegistry, []}
|
||||
{Amethyst.GameRegistry, []},
|
||||
{Amethyst.GameCoordinator, []}
|
||||
]
|
||||
|
||||
children = case Application.fetch_env!(:amethyst, :port) do
|
||||
|
@ -12,18 +12,18 @@ defmodule Amethyst.API.Game do
|
||||
def child_spec(state) do
|
||||
%{
|
||||
id: __MODULE__,
|
||||
start: {__MODULE__, :start_link, []}
|
||||
start: {__MODULE__, :register_self, []}
|
||||
}
|
||||
end
|
||||
def start_link() do
|
||||
register_self()
|
||||
_loop()
|
||||
end
|
||||
defp _loop() do
|
||||
_loop()
|
||||
end
|
||||
def register_self() do
|
||||
Amethyst.GameRegistry.register(__MODULE__, unquote(meta))
|
||||
Process.sleep(:infinity)
|
||||
end
|
||||
def start(state) do
|
||||
loop(state)
|
||||
end
|
||||
defp loop(state) do
|
||||
loop(state)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,31 +6,62 @@ defmodule Amethyst.GameCoordinator do
|
||||
instances of each game and can create new ones on demand.
|
||||
"""
|
||||
|
||||
def start_link(initial) when is_list(initial) do
|
||||
GenServer.start_link(__MODULE__, initial, name: {:global, __MODULE__})
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(initial) do
|
||||
{:ok, initial}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call({:get, type}, _from, state) do
|
||||
{:reply, find_or_create(type, state), state}
|
||||
def handle_call({:find, type}, _from, state) do
|
||||
{pid, state} = _find(type, state)
|
||||
{:reply, pid, state}
|
||||
end
|
||||
|
||||
defp create(mod) do
|
||||
state = mod.initialize()
|
||||
spawn(mod, :listen, [state])
|
||||
@impl true
|
||||
def handle_call({:create, type}, _from, state) do
|
||||
{pid, state} = _create(type, state)
|
||||
{:reply, pid, state}
|
||||
end
|
||||
|
||||
defp find(type, games) do
|
||||
existing = games |> Enum.filter(fn {mod, _pid, _opts} -> mod == type end)
|
||||
[{_mod, pid, _} | _] = existing
|
||||
pid
|
||||
end
|
||||
|
||||
defp find_or_create(type, games) do
|
||||
case find(type, games) do
|
||||
nil -> create(type)
|
||||
some -> some
|
||||
@impl true
|
||||
def handle_call({:find_or_create, type}, from, state) do
|
||||
{pid, state} = _find(type, state)
|
||||
case pid do
|
||||
nil -> handle_call({:create, type}, from, state)
|
||||
some -> {:reply, some, state}
|
||||
end
|
||||
end
|
||||
|
||||
defp _create(type, games) do
|
||||
state = type.instantiate()
|
||||
pid = spawn(type, :start, [state])
|
||||
games = [{type, pid, []} | games]
|
||||
{pid, games}
|
||||
end
|
||||
|
||||
defp _find(type, games) do
|
||||
alive_games = games |> Enum.filter(fn {_mod, pid, _opts} -> Process.alive?(pid) end)
|
||||
# TODO: Here we should have some additional filtering for specifically joinable games
|
||||
existing = alive_games |> Enum.filter(fn {mod, _pid, _opts} -> mod == type end)
|
||||
if length(existing) > 0 do
|
||||
[{_mod, pid, _} | _] = existing
|
||||
{pid, alive_games}
|
||||
else
|
||||
{nil, alive_games}
|
||||
end
|
||||
end
|
||||
|
||||
def create(type) do
|
||||
GenServer.call({:global, __MODULE__}, {:create, type})
|
||||
end
|
||||
def find(type) do
|
||||
GenServer.call({:global, __MODULE__}, {:find, type})
|
||||
end
|
||||
def find_or_create(type) do
|
||||
GenServer.call({:global, __MODULE__}, {:find_or_create, type})
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user