diff --git a/games/pong_bot_e/ggs_network.erl b/games/pong_bot_e/ggs_network.erl index 038a77b..343465f 100644 --- a/games/pong_bot_e/ggs_network.erl +++ b/games/pong_bot_e/ggs_network.erl @@ -1,39 +1,57 @@ -module(ggs_network). -export([connect/0,append_key_value_strings_to_dict/2,key_value_string_to_list/1]). --export([read/1, send_command/2]). +-export([read/2, send_command/3]). connect() -> {ok,Socket} = gen_tcp:connect("localhost", 9000,[{active, false}]), Socket. - - -read(Message) -> - case Message of - {ok, M} -> - io:format("Message: ~n~n~s~n", [M]), - HeaderList = string:tokens(M, "\n"), - Headers = extract_headers(HeaderList), - Data = extract_data(HeaderList), - io:format("Data: ~s~n", [Data]), - received_command(Headers, Data) - end. -received_command(Headers, Data) -> +read(Socket, Ref) -> + Content = receive_content(Socket), + Headers = extract_headers(Content), + ContentSize = dict:fetch("Content-Size", Headers), + ContentSizeI = list_to_integer(lists:nth(1, ContentSize)), + Data = receive_data(Socket, ContentSizeI, ""), + %io:format("Headers: ~s~n", [Content]), + %io:format("Data: ~s~n", [Data]), + received_command(Headers, Data, Ref). + +receive_content(Socket) -> + receive_content_(0, "", Socket). + +receive_content_(Amount, Headers, Socket) -> + {ok, Char1} = gen_tcp:recv(Socket, 1), + case Char1 of + "\n" -> case Amount of + 1 -> Headers; + _ -> receive_content_(Amount + 1, + Headers ++ Char1, + Socket) + end; + _ -> receive_content_(0, Headers ++ Char1, Socket) + end. + +receive_data(_, 0, Headers) -> + Headers; +receive_data(Socket, ContentSize, Headers) -> + {ok, Char} = gen_tcp:recv(Socket, 1), + receive_data(Socket, ContentSize - 1, Headers ++ Char). + +received_command(Headers, Data, Ref) -> {ok, CommandList} = dict:find("Client-Command", Headers), Command = lists:nth(1, CommandList), case Command of "hello" -> - pong_bot:set_game_token(Data), - send_command("ready", ""); + pong_bot:set_game_token(Data, Ref), + send_command("ready", "", Ref); "defined" -> - io:format("Defined~n"), ok; Command -> - pong_bot:ggsNetworkReceivedCommandWithArgs(Command, Data) + pong_bot:ggsNetworkReceivedCommandWithArgs(Command, Data, Ref) end. -make_message(ServerOrGame, Command, Args) -> - GameToken = pong_bot:get_game_token(), +make_message(ServerOrGame, Command, Args, Ref) -> + GameToken = pong_bot:get_game_token(Ref), StrGameToken = string:concat("Token: ", GameToken), StrGameTokenln = string:concat(StrGameToken, "\n"), StrCommand = string:concat("-Command: ", Command), @@ -46,11 +64,11 @@ make_message(ServerOrGame, Command, Args) -> MessageWithArgs = string:concat(Message, list_concat(Args,[])), MessageWithArgs. -send_command(Command, Args) -> - write(make_message("Game", Command, Args)). +send_command(Command, Args, Ref) -> + write(make_message("Game", Command, Args, Ref), Ref). -write(Message) -> - Socket = gen_server:call({global, pong_bot}, socket), +write(Message, Ref) -> + Socket = gen_server:call({global, {pong_bot, Ref}}, socket), gen_tcp:send(Socket, Message). list_concat([],Ret) -> @@ -58,28 +76,13 @@ list_concat([],Ret) -> list_concat([E|ES],Ret) -> NewRet = string:concat(Ret,E), list_concat(ES,NewRet). - - %%%Packet parsing.%%% extract_headers(Source) -> - key_value_strings_to_dict(Source). - - -extract_data([]) -> - []; -extract_data([E|ES]) -> - io:format("~n~s~n", [E]), - KeyValueList = key_value_string_to_list(E), - case length(KeyValueList) of - 2 -> - extract_data(ES); - _ -> - E - end. - + HeaderList = string:tokens(Source, "\n"), + key_value_strings_to_dict(HeaderList). %%%Low-level internals.%%% diff --git a/games/pong_bot_e/pong_bot.erl b/games/pong_bot_e/pong_bot.erl index f5a81c4..585022c 100644 --- a/games/pong_bot_e/pong_bot.erl +++ b/games/pong_bot_e/pong_bot.erl @@ -1,25 +1,31 @@ -module(pong_bot). -behaviour(gen_server). --export([start_link/0]). +-export([start/1, start_link/0]). -export([init/1, handle_call/3, handle_cast/2]). --export([ggsNetworkReceivedCommandWithArgs/2,set_game_token/1,get_game_token/0]). --export([view/0, peek_socket/0]). +-export([ggsNetworkReceivedCommandWithArgs/3,set_game_token/2,get_game_token/1]). +-export([view/1, peek_socket/1]). +start(0) -> + ok; +start(N) -> + start_link(), + timer:sleep(50), + start(N - 1). start_link() -> - gen_server:start_link({global, pong_bot}, pong_bot, [], []), - Socket = peek_socket(), - spawn(fun() -> communication_loop(Socket) end), - spawn(fun() -> game_loop() end ). + Ref = make_ref(), + gen_server:start_link({global, {pong_bot, Ref}}, pong_bot, [], []), + Socket = peek_socket(Ref), + spawn(fun() -> communication_loop(Socket, Ref) end), + spawn(fun() -> game_loop(Ref) end ). -communication_loop(Socket) -> - A = gen_tcp:recv(Socket, 0), - ggs_network:read(A), - communication_loop(Socket). - - -peek_socket() -> - gen_server:call({global, pong_bot}, socket). +communication_loop(Socket, Ref) -> + ggs_network:read(Socket, Ref), + communication_loop(Socket, Ref). + + +peek_socket(Ref) -> + gen_server:call({global, {pong_bot, Ref}}, socket). init(_Args) -> @@ -42,118 +48,116 @@ new_pos() -> {0, 0}. -ggsNetworkReceivedCommandWithArgs(Command, Args) -> +ggsNetworkReceivedCommandWithArgs(Command, Args, Ref) -> case Command of "welcome" -> - welcome(Args); + welcome(Args, Ref); "ball" -> - ball(Args); + ball(Args, Ref); "player1_y" -> - player1_y(Args); + player1_y(Args, Ref); "player2_y" -> - player2_y(Args); + player2_y(Args, Ref); "game" -> - game(Args); + game(Args, Ref); "player1_points" -> - new_round(); + new_round(Ref); "player2_points" -> - new_round() - end. + new_round(Ref); + _ -> ok + end. -welcome(Who_am_I) -> - io:format("Welcome begin~n"), - io:format("I am player: ~s~n", [Who_am_I]), +welcome(Who_am_I, Ref) -> case Who_am_I of "1" -> - Me = gen_server:call({global, pong_bot}, player1), - gen_server:cast({global, pong_bot}, {me, Me}); + Me = gen_server:call({global, {pong_bot, Ref}}, player1), + gen_server:cast({global, {pong_bot, Ref}}, {me, Me}); "2" -> - Me = gen_server:call({global, pong_bot}, player2), - gen_server:cast({global, pong_bot}, {me, Me}) + Me = gen_server:call({global, {pong_bot, Ref}}, player2), + gen_server:cast({global, {pong_bot, Ref}}, {me, Me}) end. -game_loop() -> +game_loop(Ref) -> timer:sleep(300), - gameTick(), - game_loop(). + gameTick(Ref), + game_loop(Ref). -gameTick() -> - GamePaused = gen_server:call({global, pong_bot}, paused), - SendStart = gen_server:call({global, pong_bot}, start), +gameTick(Ref) -> + GamePaused = gen_server:call({global, {pong_bot, Ref}}, paused), + SendStart = gen_server:call({global, {pong_bot, Ref}}, start), case GamePaused of true -> case SendStart of false -> - ggs_network:send_command("start", ""), - gen_server:cast({global, pong_bot}, {start, true}); + ggs_network:send_command("start", "", Ref), + gen_server:cast({global, {pong_bot, Ref}}, {start, true}); true -> ok end; false -> - Ball = gen_server:call({global, pong_bot}, ball), + Ball = gen_server:call({global, {pong_bot, Ref}}, ball), {_, BallY} = Ball, - Me = gen_server:call({global, pong_bot}, me), + Me = gen_server:call({global, {pong_bot, Ref}}, me), {_, MeY} = Me, case BallY < (MeY - 5) of true -> - ggs_network:send_command("up", ""); - false -> - ggs_network:send_command("down", "") + ggs_network:send_command("up", "", Ref); + _ -> case BallY > ( MeY - 5) of + true -> + ggs_network:send_command("down", "", Ref); + _ -> ok + end end end. - - -ball(Pos_s) -> +ball(Pos_s, Ref) -> PosList = string:tokens(Pos_s, ","), XStr = lists:nth(1,PosList), - YStr = lists:nth(1,PosList), - X = string:to_integer(XStr), - Y = string:to_integer(YStr), + YStr = lists:nth(2,PosList), + X = list_to_integer(XStr), + Y = list_to_integer(YStr), Pos = {X, Y}, - gen_server:cast({global, pong_bot}, {ball, Pos}). + gen_server:cast({global, {pong_bot, Ref}}, {ball, Pos}). -player1_y(YStr) -> - Y = string:to_integer(YStr), - gen_server:cast({global, pong_bot}, {player1_y, Y}). +player1_y(YStr, Ref) -> + Y = list_to_integer(YStr), + gen_server:cast({global, {pong_bot, Ref}}, {player1_y, Y}). -player2_y(YStr) -> - Y = string:to_integer(YStr), - gen_server:cast({global, pong_bot}, {player2_y, Y}). +player2_y(YStr, Ref) -> + Y = list_to_integer(YStr), + gen_server:cast({global, {pong_bot, Ref}}, {player2_y, Y}). -game(WaitOrStart) -> +game(WaitOrStart, Ref) -> case WaitOrStart of "wait" -> ok; _ -> - gen_server:cast({global, pong_bot}, {paused, false}) + gen_server:cast({global, {pong_bot, Ref}}, {paused, false}) end. -new_round() -> +new_round(Ref) -> Paused = true, - SendStart = false, - gen_server:cast({global, pong_bot}, {new_round, Paused, SendStart}). + Start = false, + gen_server:cast({global, {pong_bot, Ref}}, {new_round, Paused, Start}). -set_game_token(GameToken) -> - gen_server:cast({global, pong_bot}, {game_token, GameToken}). +set_game_token(GameToken, Ref) -> + gen_server:cast({global, {pong_bot, Ref}}, {game_token, GameToken}). -get_game_token() -> - gen_server:call({global, pong_bot}, game_token). +get_game_token(Ref) -> + gen_server:call({global, {pong_bot, Ref}}, game_token). -view() -> - gen_server:call({global, pong_bot}, game_token). +view(Ref) -> + gen_server:call({global, {pong_bot, Ref}}, game_token). handle_call(player1, _From, State) -> - io:format("Player1 before~n"), Player1 = dict:fetch(player1, State), - io:format("Player1 after~n"), {reply, Player1, State}; handle_call(player2, _From, State) -> @@ -166,20 +170,25 @@ handle_call(player1_y, _From, State) -> handle_call(player2_y, _From, State) -> {_,Y} = dict:fetch(player2, State), - {reply, Y, State}; + {reply, Y, State}; + +handle_call(ball, _From, State) -> + Ball = dict:fetch(ball, State), + {reply, Ball, State}; + +handle_call(me, _From, State) -> + Me = dict:fetch(me, State), + {reply, Me, State}; handle_call(game_token, _From, State) -> GameToken = dict:fetch(game_token, State), {reply, GameToken, State}; handle_call(view, _From, State) -> - io:format("View the state.~n"), -% StateFromList = lists:nth(1, State) {reply, State, State}; handle_call(socket, _From, State) -> Socket = dict:fetch(socket, State), - %Socket = lists:nth(1, SocketInList), {reply, Socket, State}; handle_call(paused, _From, State) -> @@ -218,9 +227,9 @@ handle_cast({paused, Paused}, State) -> NewState = dict:store(paused, Paused, State), {noreply, NewState}; -handle_cast({new_rouned, Paused, SendStart}, State) -> +handle_cast({new_round, Paused, Start}, State) -> State1 = dict:store(paused, Paused, State), - NewState = dict:store(send_start, SendStart, State1), + NewState = dict:store(start, Start, State1), {noreply, NewState}; handle_cast({start, Start}, State) ->