We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Okay so this will be a series of posts about my work to build a Multiplayer Poke Site.
For this first one we will look at GenServer for the Room context and the Struct for the Player context.
For this we need to have a room GenServer that will allow use to keep track of Players and the state of the room that we are currently in.
defmodule GameSite.MultiPoker.Room do
use GenServer
alias GameSite.MultiPoker.Player
defstruct players: %{},
room_id: nil,
room_status: :waiting,
host_id: nil,
full: false
def new(%Player{} = host, opts \\ []) do
host_id = host.player_id
room_id = Keyword.get(opts, :room_id)
room_status = Keyword.get(opts, :room_status, :waiting)
full = Keyword.get(opts, :full, false)
%__MODULE__{
players: %{host_id => host},
room_id: room_id,
room_status: room_status,
host_id: host_id,
full: full
}
end
def add_player(pid, %Player{} = player) do
GenServer.cast(pid, {:add_player, player})
end
def remove_player(pid, %Player{} = player) do
GenServer.cast(pid, {:remove_player, player})
end
def update_status(pid, status) do
GenServer.cast(pid, {:update_status, status})
end
def get_state(pid) do
GenServer.call(pid, :get_room_state)
end
def start_link(host, opts \\ []) do
GenServer.start_link(__MODULE__, {host, opts})
end
@impl true
def init({host, opts}) do
initial_state = new(host, opts)
{:ok, initial_state}
end
@impl true
def handle_cast({:add_player, %Player{} = player}, %__MODULE__{players: players} = state) do
new_players = Map.put(players, player.player_id, player)
{:noreply, %__MODULE__{state | players: new_players}}
end
@impl true
def handle_cast({:update_status, status}, state) do
{:noreply, %__MODULE__{state | room_status: status}}
end
@impl true
def handle_cast({:remove_player, %Player{} = player}, %__MODULE__{players: players} = state) do
new_players = Map.delete(players, player.player_id)
{:noreply, %__MODULE__{state | players: new_players}}
end
@impl true
def handle_cast({:full_room}, state) do
{:noreply, %__MODULE__{state | full: true}}
end
@impl true
def handle_cast({:has_room}, state) do
{:noreply, %__MODULE__{state | full: false}}
end
end
Next we need to build the Player context that will allow us to update a Player. This will keep track of things like :current_bet, :chips:, :folded, and more.
defmodule GameSite.MultiPoker.Player do
defstruct player_id: nil,
ready?: false,
chips: 1000,
current_bet: 0,
folded?: false,
seat_position: nil,
hand: [],
connected?: true
def new(id, opts \\ []) do
ready = Keyword.get(opts, :ready?, false)
chips = Keyword.get(opts, :chips, 1000)
current_bet = Keyword.get(opts, :current_bet, 0)
folded = Keyword.get(opts, :folded?, false)
seat_position = Keyword.get(opts, :seat_position, nil)
hand = Keyword.get(opts, :hand, [])
connected = Keyword.get(opts, :connected?, true)
%__MODULE__{
player_id: id,
ready?: ready,
chips: chips,
current_bet: current_bet,
folded?: folded,
seat_position: seat_position,
hand: hand,
connected?: connected
}
end
def change(%__MODULE__{} = player, opts \\ []) do
updates = Enum.into(opts, %{})
struct(player, updates)
end
def set_ready(%__MODULE__{} = player, ready) do
%__MODULE__{player | ready?: ready}
end
end
This will be enough to get us started I will add in the _Supervisor Tree on the next post.