Add GameCoordinator logic for finding or creating games
All checks were successful
Build & Test / nix-build (push) Successful in 1m14s

This commit is contained in:
Kodi Craft 2024-08-18 13:02:48 +02:00
parent 99af42f42c
commit 11db275db2
Signed by: kodi
GPG Key ID: 69D9EED60B242822
3 changed files with 56 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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)
@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
{pid, alive_games}
else
{nil, alive_games}
end
end
defp find_or_create(type, games) do
case find(type, games) do
nil -> create(type)
some -> some
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