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 = [
|
children = [
|
||||||
{Task.Supervisor, name: Amethyst.ConnectionSupervisor},
|
{Task.Supervisor, name: Amethyst.ConnectionSupervisor},
|
||||||
{Amethyst.Keys, 1024},
|
{Amethyst.Keys, 1024},
|
||||||
{Amethyst.GameRegistry, []}
|
{Amethyst.GameRegistry, []},
|
||||||
|
{Amethyst.GameCoordinator, []}
|
||||||
]
|
]
|
||||||
|
|
||||||
children = case Application.fetch_env!(:amethyst, :port) do
|
children = case Application.fetch_env!(:amethyst, :port) do
|
||||||
|
@ -12,18 +12,18 @@ defmodule Amethyst.API.Game do
|
|||||||
def child_spec(state) do
|
def child_spec(state) do
|
||||||
%{
|
%{
|
||||||
id: __MODULE__,
|
id: __MODULE__,
|
||||||
start: {__MODULE__, :start_link, []}
|
start: {__MODULE__, :register_self, []}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
def start_link() do
|
|
||||||
register_self()
|
|
||||||
_loop()
|
|
||||||
end
|
|
||||||
defp _loop() do
|
|
||||||
_loop()
|
|
||||||
end
|
|
||||||
def register_self() do
|
def register_self() do
|
||||||
Amethyst.GameRegistry.register(__MODULE__, unquote(meta))
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,31 +6,62 @@ defmodule Amethyst.GameCoordinator do
|
|||||||
instances of each game and can create new ones on demand.
|
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
|
@impl true
|
||||||
def init(initial) do
|
def init(initial) do
|
||||||
{:ok, initial}
|
{:ok, initial}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_call({:get, type}, _from, state) do
|
def handle_call({:find, type}, _from, state) do
|
||||||
{:reply, find_or_create(type, state), state}
|
{pid, state} = _find(type, state)
|
||||||
|
{:reply, pid, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp create(mod) do
|
@impl true
|
||||||
state = mod.initialize()
|
def handle_call({:create, type}, _from, state) do
|
||||||
spawn(mod, :listen, [state])
|
{pid, state} = _create(type, state)
|
||||||
|
{:reply, pid, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp find(type, games) do
|
@impl true
|
||||||
existing = games |> Enum.filter(fn {mod, _pid, _opts} -> mod == type end)
|
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
|
[{_mod, pid, _} | _] = existing
|
||||||
pid
|
{pid, alive_games}
|
||||||
|
else
|
||||||
|
{nil, alive_games}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp find_or_create(type, games) do
|
def create(type) do
|
||||||
case find(type, games) do
|
GenServer.call({:global, __MODULE__}, {:create, type})
|
||||||
nil -> create(type)
|
end
|
||||||
some -> some
|
def find(type) do
|
||||||
end
|
GenServer.call({:global, __MODULE__}, {:find, type})
|
||||||
|
end
|
||||||
|
def find_or_create(type) do
|
||||||
|
GenServer.call({:global, __MODULE__}, {:find_or_create, type})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user