added stash
This commit is contained in:
parent
0718031e22
commit
da67b0a977
5 changed files with 192 additions and 73 deletions
|
@ -1,48 +1,66 @@
|
|||
-module(ggs_player).
|
||||
-export([start_link/1, notify/3, get_token/1, stop/2]).
|
||||
-record(pl_state,
|
||||
{token, % Player's token
|
||||
socket, % Player's socket
|
||||
table}). % Player's table
|
||||
|
||||
%% @doc This module handles communication between a player and GGS. This module is
|
||||
%%responsible for:
|
||||
%% * The storage of the player socket, player token and a table token.
|
||||
%% * Ability to fetch a player token.
|
||||
%% * Forwarding messages from players to the game
|
||||
%% * Remove a player from GGS
|
||||
%% responsible for:
|
||||
%% * The storage of the player socket, player token and a table token.
|
||||
%% * Ability to fetch a player token.
|
||||
%% * Forwarding messages from players to the game
|
||||
%% * Remove a player from GGS
|
||||
|
||||
-module(ggs_player).
|
||||
-behaviour(gen_server).
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-export([start/1, notify/3, notify_game/2, get_token/1, stop/1]).
|
||||
|
||||
-vsn(1.0).
|
||||
|
||||
-record(state, {
|
||||
token,
|
||||
socket,
|
||||
table,
|
||||
protocol }).
|
||||
|
||||
%% @doc Spawns a process representing the player in GGS. Takes the player socket as
|
||||
%% an argument for storage and later usage. Creates a unique player token
|
||||
%% identifying the player.
|
||||
%% @spec start_link(Socket::socket()) -> {ok, Pid} | {error, Reason}
|
||||
start_link(Socket) ->
|
||||
% The socket is in 'active' mode, and that means we are pushed any data
|
||||
% that arrives on it, we do not need to recv() manually. Since the socket
|
||||
% was opened in our parent process, we need to change the owner of it to
|
||||
% us, otherwise these messages end up in our parent.
|
||||
erlang:port_connect(Socket, self()),
|
||||
start(Socket) ->
|
||||
erlang:display("start_link"),
|
||||
gen_server:start(?MODULE, [Socket], []).
|
||||
|
||||
init([Socket]) ->
|
||||
{ok, Protocol} = ggs_protocol:start_link(Socket, self()),
|
||||
{ok, Token} = ggs_coordinator:join_lobby(),
|
||||
TableStatus = ggs_coordinator:join_table("1337"),
|
||||
case TableStatus of
|
||||
{ok, Table} ->
|
||||
notify(self(), self(), {"hello", Token}),
|
||||
loop(#pl_state{socket = Socket, token = Token, table = Table});
|
||||
|
||||
case ggs_coordinator:join_table("1337") of
|
||||
{ok, T} ->
|
||||
Table = T;
|
||||
{error, no_such_table} ->
|
||||
ggs_coordinator:create_table({force, "1337"}),
|
||||
{ok, Table} = ggs_coordinator:join_table("1337"),
|
||||
notify(self(), self(), {"hello", Token}),
|
||||
loop(#pl_state{socket = Socket, token = Token, table = Table})
|
||||
end.
|
||||
{ok, T} = ggs_coordinator:join_table("1337"),
|
||||
Table = T
|
||||
end,
|
||||
|
||||
State = #state{
|
||||
token = Token,
|
||||
socket = Socket,
|
||||
table = Table,
|
||||
protocol = Protocol
|
||||
},
|
||||
erlang:display(State),
|
||||
{ok, State}.
|
||||
|
||||
%% @doc Handles incoming messages from the GGS and forwards them through the player
|
||||
%% socket to the player.
|
||||
%% @spec notify(Player::Pid(), From::Pid(),
|
||||
%% {Command::String(), Message::string()}) -> ok
|
||||
notify(Player, From, Message) ->
|
||||
{Cmd, Data} = Message,
|
||||
Parsed = ggs_protocol:create_message(Cmd, "text","text", Data),
|
||||
Player ! {notify, From, Parsed}.
|
||||
notify(Player, _From, Message) ->
|
||||
gen_server:cast(Player, {notify, Message}).
|
||||
|
||||
%% @doc Handles incomming messages form a client and forwards them
|
||||
%% through to the game_vm
|
||||
notify_game(Player, Message) ->
|
||||
gen_server:cast(Player, Message).
|
||||
|
||||
%% @doc Get the player token uniquely representing the player.
|
||||
%% @spec get_token() -> string()
|
||||
|
@ -53,32 +71,33 @@ get_token(_Player) ->
|
|||
%% together with the table token. It should also close the player socket and the
|
||||
%% process should return in the end.
|
||||
%% @spec stop(Table::pid()) -> Reason::string()
|
||||
stop(_Player,_Table) ->
|
||||
ggs_logger:not_implemented().
|
||||
stop(Player) ->
|
||||
gen_server:cast(Player, stop).
|
||||
|
||||
%% Internals
|
||||
|
||||
loop(#pl_state{token = _Token, socket = Socket, table = Table} = State) ->
|
||||
receive
|
||||
{tcp, Socket, Data} -> % Just echo for now..
|
||||
Parsed = ggs_protocol:parse(Data),
|
||||
self() ! Parsed,
|
||||
loop(State);
|
||||
{notify, _From, Message} ->
|
||||
gen_tcp:send(Socket, Message),
|
||||
loop(State);
|
||||
% Below are messages generated by the parser
|
||||
{game_cmd,Cmd, _Headers, Data} ->
|
||||
ggs_table:notify(Table, self(), {game, Cmd, Data}),
|
||||
loop(State);
|
||||
{srv_cmd,"define", _Headers, Data} ->
|
||||
ggs_table:notify(Table, self(), {server, define, Data}),
|
||||
loop(State);
|
||||
{tcp_closed, _Socket} ->
|
||||
io:format("Client disconnected, but THIS IS NOT SUPPORTED YET!~n"),
|
||||
loop(State);
|
||||
Other ->
|
||||
io:format("Got UNKNOWN message: "),
|
||||
erlang:display(Other),
|
||||
io:format("~n")
|
||||
end.
|
||||
handle_call({notify, Message}, _From, #state { protocol = Protocol } = State) ->
|
||||
ggs_protocol:send_command(Protocol, Message),
|
||||
{noreplay, State};
|
||||
|
||||
handle_call({game_cmd, Command, _Headers, Data}, _From, #state { table = Table } = State) ->
|
||||
ggs_table:notify(Table, self(), {game, Command, Data}),
|
||||
{noreplay, State};
|
||||
|
||||
handle_call({srv_cmd, "define", _Headers, Data}, _From, #state { table = Table } = State) ->
|
||||
ggs_table:notify(Table, self(), {server, define, Data}),
|
||||
{noreplay, State};
|
||||
|
||||
handle_call(_Request, _From, St) -> {stop, unimplemented, St}.
|
||||
handle_cast(_Request, St) -> {stop, unimplemented, St}.
|
||||
|
||||
handle_info(_Info, St) -> {stop, unimplemented, St}.
|
||||
|
||||
terminate(_Reason, State) ->
|
||||
ggs_protocol:stop(State#state.protocol),
|
||||
ggs_table:remove_player(State#state.table, self()),
|
||||
% ggs_coordinator:remove_player(self(), self()), % not implemented yet
|
||||
% TODO: release Socket
|
||||
ok.
|
||||
|
||||
code_change(_OldVsn, St, _Extra) -> {ok, St}.
|
||||
|
|
Reference in a new issue