简单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 等等,

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

下回增长相关的测试和代码吧

相关文章
相关标签/搜索