簡單Elixir遊戲服設計- 豐富桌子進程

輪處處理桌子進程了。桌子進程拋開消息發送,基本上就是table的轉調用。api

無謂測試驅動先仍是寫代碼先,反正怎麼順就怎麼搞。ide

defmodule TableServer do
    use GenServer, restart: :temporary, start: {__MODULE__, :start_link, []}

    def start_link(table) do
        GenServer.start_link(__MODULE__, table, name: register_name(table))
      end

    def init(table) do
        {:ok, table}
    end

    def register_name(%{} = table), do: register_name(table |> SimpleTable.get_id)
    def register_name(id), do: {:via, Registry, {LocalRegistry, {Table, id}}}

    def exist?(table) do
        key = {Table, table |> SimpleTable.get_id}
        case Registry.lookup(LocalRegistry, key) do
            [{_pid, _}] -> true
            [] -> false
        end
    end

    def create(player) do
        table = SimpleTable.init 
                |> SimpleTable.set_id(player |> Player.get_id)
                |> SimpleTable.set_creator(player)
                |> SimpleTable.add_seat(player)
        TableSupervisor.start_table(table)
    end

    def join(table, player), do: GenServer.cast(table, {:join, player: player})

    def quit(table, player), do: GenServer.cast(table, {:quit, player: player})

    def dismiss(table, player), do: GenServer.cast(table, {:dismiss, player: player})

    def start(table, player), do: GenServer.cast(table, {:start, player: player})

    def open(table, player), do: GenServer.cast(table, {:open, player: player})

    def makeup(table, player), do: GenServer.cast(table, {:makeup, player: player})

    def handle_cast(request, table) do
        {:ok, table} = inner_handle_cast(request, table) 
        {:noreply, table}
    end



    def send_error(_player, _error) do
    
    end

  

    def inner_handle_cast({:join, player: player}, table) do 
        with {:ok, table}  <- table |> SimpleTable.join(player)
        do
            seat = SimpleTable.find_seat(table, player)
            broadcast_join(table, seat)
        else
            {:error, error} ->
                send_error(player, error)
        end
        {:ok, table}
    end

    def inner_handle_cast({:quit, player: player}, table) do
        with {:ok, table} <- table |> SimpleTable.quit(player)
        do
            broadcast_quit(table, player)
        else
            {:error, error} ->
                send_error(player, error)
        end
        {:ok, table}
       end

    def inner_handle_cast({:dismiss, player: player}, table) do
        with {:ok, table} <- table |> SimpleTable.dismiss(player)
        do
            broadcast_dismiss(table)
        else
            {:error, error} ->
                send_error(player, error)
        end
        {:ok, table}
    end

    def inner_handle_cast({:start, player: player}, table) do
        with {:ok, table} <-    table |> SimpleTable.start(player)
        do
            broadcast_start(table)
        else
            {:error, error} ->
                send_error(player, error)
        end
        {:ok, table}
    end

    def inner_handle_cast({:open, player: player}, table) do
        with {:ok, table} <- table |> SimpleTable.open(player)
        do
            send_open(table, player)
        else
            {:error, error} ->
                send_error(player, error)
        end
        {:ok, table}
    end

    def inner_handle_cast({:makeup, player: player}, table) do
        with {:ok, table} <- table |> SimpleTable.make_up(player)
        do
            send_makeup(table, player)
        else
            {:error, error} ->
                send_error(player, error)
        end
        {:ok, table}
    end

    def broadcast_join(_table, _seat) do
        
    end

    def broadcast_quit(_table, _player) do
        
    end

    def broadcast_dismiss(_table) do
        
    end

    def broadcast_start(_table) do
        
    end

    def send_open(_table, _player) do
        
    end

    def send_makeup(_table, _player) do
        
    end

end
table_server.ex

雖然table_server 很簡單,但我仍是花了點時間在上面。函數

主要在考慮下面的問題:測試

1. 要不要用exactor 庫簡化api接口ui

  後來沒有用, exactor 仍是適合於速錯模式用, 而遊戲咱們一般要try catch,若是要用,須要包裝exactor的宏,麻煩。spa

       固然若是把table存到ets裏, 就能夠比較方便的崩潰恢復, 也許這比較適合用exactor。rest

2. inner_handle_cast  應該是怎麼樣的接口才方便修改code

      想來想去,用  {cmd, keyword_list} 比較方便, 直觀且容易修改server

3. 消息發送怎麼樣才方便以及直觀blog

  一開始是嘗試 broadcast_table, 誘惑是凡是發消息就調用該接口。

      但明顯感受有2個缺陷

      一個是粒度太大(結果是該函數裏好比要有不一樣分支)

      一個沒法直觀每一個操做的具體影響

     因此最後改爲,須要發送什麼,就搞個api發送什麼, 這就有broadcast_join broadcast_quit 等等,

    感受就清晰不少,天然不少,而且粒度小了發送的信息也少了。

下回增長相關的測試和代碼吧

相關文章
相關標籤/搜索