| -module(game).
-author(neFormal).
-behaviour(gen_server).
-export([start_link/1, join/3, leave/2, send/3, move/5, list/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(player, {id, name, team=false, pid=false, object=null}).
-record(object, {id, type, x, y, z}).
-record(state, {players=[], objects=[], last_id=1}).
-include("cmd_macros.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% interface
start_link(Id) ->
gen_server:start_link({local, Id}, ?MODULE, [], []).
join(Pid, Client, Name) ->
gen_server:call(Pid, {join, Client, Name}).
leave(Pid, Client) ->
gen_server:cast(Pid, {leave, Client}).
send(Pid, Client, Text) ->
gen_server:cast(Pid, {send, Client, Text}).
move(Pid, Client, Id, Key, Value) ->
gen_server:cast(Pid, {move, Client, Id, Key, Value}).
list(Pid) ->
gen_server:call(Pid, list).
%%%% backend
init([]) -> {ok, #state{players=[], objects=[], last_id=1}}.
handle_call({join, Client, Name}, _From, S=#state{players=Players, objects=Objects, last_id=LastId}) ->
Obj = create_object(0, LastId+1),
Player = create_player(LastId+1, Name, Client, Obj),
Joins = [?JOIN, LastId+1, Name, [Obj#object.id, Obj#object.x, Obj#object.y, Obj#object.z]],
io:format("foreach ~p~n", [Joins]),
gen_server:cast(Player#player.pid, {send, Joins}),
lists:foreach(fun(P) ->
gen_server:cast(P#player.pid, {send, Joins}),
[#object{id=Id, type=T, x=X, y=Y, z=Z}] = [X || X <- Objects, X#object.id == P#player.id],
J = [?JOIN, P#player.id, P#player.name, [Id, X, Y, Z]],
gen_server:cast(Player#player.pid, {send, J})
end, Players),
{reply, {self(), LastId+1}, S#state{players=[Player|Players], objects=[Obj|Objects], last_id=LastId+1}};
handle_call(list, _From, S) ->
{reply, S}.
handle_cast({move, _C, Id, Key, Value}, S) ->
Players = S#state.players,
io:format("handle_cast({move: ~p~n", [Players]),
Moves = [?MOVE, Id, Key, Value],
lists:foreach(fun(Player) ->
io:format("foreach ~p~n", [Moves]),
gen_server:cast(Player#player.pid, {send, Moves})
end, Players),
{noreply, S};
handle_cast({leave, Player}, S=#state{players=Players}) ->
{noreply, S#state{players=lists:delete(Player, Players)}};
handle_cast({send, Client, Text}, S=#state{players=Players}) ->
lists:foreach(fun({Player, _}) ->
client:send_text(Player#player.pid, Text)
end, Players),
{noreply, S}.
handle_info(Msg, S=#state{}) ->
io:format("Unexpected message: ~p~n", [Msg]),
{noreply, S}.
terminate(normal, _S) ->
ok.
code_change(_Old, S, _Extra) ->
{ok, S}.
create_player(Id, Name, Pid, Obj) ->
#player{id=Id, name=Name, pid=Pid, object=Obj}.
create_object(Type, Id) ->
#object{id=Id, type=0, x=-107.575, y=26.6066, z=-0.490075}.
|