简单Elixir游戏服设计- 丰富桌子进程

轮到处理桌子进程了。桌子进程抛开消息发送,基本上就是table的转调用。

无谓测试驱动先还是写代码先,反正怎么顺就怎么搞。

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接口

  后来没有用, exactor 还是适合于速错模式用, 而游戏我们通常要try catch,如果要用,需要包装exactor的宏,麻烦。

       当然如果把table存到ets里, 就可以比较方便的崩溃恢复, 也许这比较适合用exactor。

2. inner_handle_cast  应该是怎么样的接口才方便修改

      想来想去,用  {cmd, keyword_list} 比较方便, 直观且容易修改

3. 消息发送怎么样才方便以及直观

  一开始是尝试 broadcast_table, 诱惑是凡是发消息就调用该接口。

      但明显感觉有2个缺陷

      一个是粒度太大(结果是该函数里比如要有不同分支)

      一个无法直观每个操作的具体影响

     所以最后改成,需要发送什么,就搞个api发送什么, 这就有broadcast_join broadcast_quit 等等,

    感觉就清晰很多,自然很多,并且粒度小了发送的信息也少了。

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

转载于:https://www.cnblogs.com/rubyist/p/7677049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值