From 0361558f4bd4be9c907959d2c4fbc0c4c4d88ff2 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Sun, 6 Feb 2011 19:25:36 +0100 Subject: [PATCH 01/67] added js_helper module --- src/js_helper.erl | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/js_helper.erl diff --git a/src/js_helper.erl b/src/js_helper.erl new file mode 100644 index 0000000..efb38f4 --- /dev/null +++ b/src/js_helper.erl @@ -0,0 +1,8 @@ +-module(js_helper). +-export([test/0, echo/1]). + +test() -> + {ok, test}. + +echo(String) -> + {ok, String}. \ No newline at end of file From 76148b39d0b783c58f5fddf32190c0b2935dc7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 15:08:37 +0100 Subject: [PATCH 02/67] Started new structure --- src/ggs_coordinator.erl | 0 src/ggs_dispatcher.erl | 0 src/ggs_gamevm.erl | 0 src/ggs_player.erl | 0 src/ggs_table.erl | 0 src/{ => old}/ggs_app.erl | 0 src/{ => old}/ggs_backup.erl | 0 src/{ => old}/ggs_mnesia_controller_server.erl | 0 src/{ => old}/ggs_protocol.erl | 0 src/{ => old}/ggs_server.erl | 0 src/{ => old}/ggs_server_sup.erl | 0 src/{ => old}/ggs_sup.erl | 0 src/{ => old}/js_runner.erl | 0 src/{ => old}/start_ggs.erl | 0 14 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/ggs_coordinator.erl create mode 100644 src/ggs_dispatcher.erl create mode 100644 src/ggs_gamevm.erl create mode 100644 src/ggs_player.erl create mode 100644 src/ggs_table.erl rename src/{ => old}/ggs_app.erl (100%) rename src/{ => old}/ggs_backup.erl (100%) rename src/{ => old}/ggs_mnesia_controller_server.erl (100%) rename src/{ => old}/ggs_protocol.erl (100%) rename src/{ => old}/ggs_server.erl (100%) rename src/{ => old}/ggs_server_sup.erl (100%) rename src/{ => old}/ggs_sup.erl (100%) rename src/{ => old}/js_runner.erl (100%) rename src/{ => old}/start_ggs.erl (100%) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_player.erl b/src/ggs_player.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_table.erl b/src/ggs_table.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_app.erl b/src/old/ggs_app.erl similarity index 100% rename from src/ggs_app.erl rename to src/old/ggs_app.erl diff --git a/src/ggs_backup.erl b/src/old/ggs_backup.erl similarity index 100% rename from src/ggs_backup.erl rename to src/old/ggs_backup.erl diff --git a/src/ggs_mnesia_controller_server.erl b/src/old/ggs_mnesia_controller_server.erl similarity index 100% rename from src/ggs_mnesia_controller_server.erl rename to src/old/ggs_mnesia_controller_server.erl diff --git a/src/ggs_protocol.erl b/src/old/ggs_protocol.erl similarity index 100% rename from src/ggs_protocol.erl rename to src/old/ggs_protocol.erl diff --git a/src/ggs_server.erl b/src/old/ggs_server.erl similarity index 100% rename from src/ggs_server.erl rename to src/old/ggs_server.erl diff --git a/src/ggs_server_sup.erl b/src/old/ggs_server_sup.erl similarity index 100% rename from src/ggs_server_sup.erl rename to src/old/ggs_server_sup.erl diff --git a/src/ggs_sup.erl b/src/old/ggs_sup.erl similarity index 100% rename from src/ggs_sup.erl rename to src/old/ggs_sup.erl diff --git a/src/js_runner.erl b/src/old/js_runner.erl similarity index 100% rename from src/js_runner.erl rename to src/old/js_runner.erl diff --git a/src/start_ggs.erl b/src/old/start_ggs.erl similarity index 100% rename from src/start_ggs.erl rename to src/old/start_ggs.erl From ac63eb124bfd255d7d85a420e5247228417f4148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 15:48:55 +0100 Subject: [PATCH 03/67] Added specification and documentation for the dispatcher --- src/ggs_dispatcher.erl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index e69de29..8f89ceb 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -0,0 +1,21 @@ +-module(ggs_dispatcher). +-export([start_link/1, stop/1]). + +%% @doc This module is the entry-point for clients connecting to GGS. This is +%% the module responsible for: +%% * Greeting a connecting client, and associating a socket for it +%% * Spawning a ggs_player for the connecting client, passing the socket + +%% @doc Starts a new dispatcher with the specified port. Registers this +%% dispatcher under the name "ggs_dispatcher". The pid of the dispatcher +%% is returned. +%% @spec start_link(Port) -> Pid +%% Port = Integer +%% Pid = # +start_link(Port) -> + not_implemented. + +%% @doc Stops the dispatcher with the specified reason. +%% @spec stop(Reason) -> ok. +%% Reason = String +stop(Reason) -> not_implemented. From e4bdc05bc816f4b314544f0a8a0baea9631e4cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 16:05:48 +0100 Subject: [PATCH 04/67] Added documentation for ggs_gamevm.erl --- src/ggs_gamevm.erl | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index e69de29..8116a96 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -0,0 +1,50 @@ +-module(ggs_vm_runner). +-export([start_link/0, define/2, user_command/4]). +%% @doc This module is responsible for running the game VM:s. You can issue +%% commands to a vm using this module. + +%% @doc Create a new VM process. The process ID is returned and can be used +%% with for example the define method of this module. +start_link() -> + erlang_js:start(), %% @TODO: should only be done once + PortPid = spawn_link( fun() -> + process_flag(trap_exit, true), + {ok, Port} = js_driver:new(), + js:define(Port, <<"function userCommand(user, command, args){return 'Hello world';}">>), + loop(Port) + end ), + PortPid. + +%% @doc Define some new code on the specified VM, returns the atom ok. +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}, + ok. + +%% @doc Execute a user command on the specified VM. This function is +%% asynchronous, and returns ok. +%% @spec user_command(GameVM, User, Command, Args) -> ok +%% GameVM = process IS of VM +%% Player = the player running the command +%% Command = a game command to run +%% Args = arguments for the Command parameter +user_command(GameVM, Player, Command, Args) -> + Ref = make_ref(), + GameVM ! {user_command, Player, Command, Args, self(), Ref}, + ok. + +%% Helper functions + +loop(Port) -> + receive + {define, SourceCode} -> + ok = js:define(Port, list_to_binary(SourceCode)), + loop(Port); + {user_command, User, Command, Args, From, Ref} -> + {ok, Ret} = js:call(Port, <<"userCommand">>, + [ list_to_binary(User), + list_to_binary(Command), + list_to_binary(Args) + ]), + From ! {Ref, Ret}, + loop(Port) + end. From ae1856e1f2a96381f77425ee03a6545bd314e93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 16:50:57 +0100 Subject: [PATCH 05/67] Added supervisor structure --- src/ggs_app.erl | 14 ++++++++++++++ src/ggs_sup.erl | 41 +++++++++++++++++++++++++++++++++++++++++ src/start_ggs.erl | 7 +++++++ 3 files changed, 62 insertions(+) create mode 100644 src/ggs_app.erl create mode 100644 src/ggs_sup.erl create mode 100644 src/start_ggs.erl diff --git a/src/ggs_app.erl b/src/ggs_app.erl new file mode 100644 index 0000000..d8b2e60 --- /dev/null +++ b/src/ggs_app.erl @@ -0,0 +1,14 @@ +-module(ggs_app). +-behaviour(application). +-export([start/2, stop/1]). + +start(_StartType, _StartArgs) -> + case ggs_sup:start_link(9000) of + {ok, Pid} -> + {ok, Pid}; + Other -> + {error, Other} + end. + +stop(_State) -> + ok. diff --git a/src/ggs_sup.erl b/src/ggs_sup.erl new file mode 100644 index 0000000..bfb2617 --- /dev/null +++ b/src/ggs_sup.erl @@ -0,0 +1,41 @@ +-module(ggs_sup). +-behaviour(supervisor). + +%% API +-export([start/1, start_link/1]). + +%% Supervisor callbacks +-export([init/1]). +-define(SERVER, ?MODULE). + +start(Port) -> + [FirstArg] = Port, + {IntPort, _} = string:to_integer(FirstArg), + start_link(IntPort). + +start_link(Port) -> + supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). + +init([Port]) -> + Dispatcher = {ggs_dispatcher, + {ggs_dispatcher, start_link, [Port]}, + permanent, + 2000, + worker, + [ggs_dispatcher] + }, + Coordinator = {ggs_coordinator, + {ggs_coordinator, start_link, []}, + permanent, + 2000, + worker, + [ggs_dispatcher] + }, + Children = [Dispatcher, Coordinator], + + RestartStrategy = { one_for_one, % Restart only crashing child + 10, % Allow ten crashes per.. + 1 % 1 second, then crash supervisor. + }, + {ok, {RestartStrategy, Children}}. + diff --git a/src/start_ggs.erl b/src/start_ggs.erl new file mode 100644 index 0000000..3955715 --- /dev/null +++ b/src/start_ggs.erl @@ -0,0 +1,7 @@ +-module(start_ggs). +-export([start/0]). + +start() -> + application:start(inets), + application:start(erlang_js), + application:start(ggs). From 3b94f5da2447f14119f4004a0fd15f590822cac9 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 17:11:27 +0100 Subject: [PATCH 06/67] Added edoc to player. --- src/ggs_player.erl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index e69de29..bdfcf7d 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -0,0 +1,22 @@ + + + +%% @spec start_link(GameToken::string()) -> socket() +%% @doc Spawn a new player process. +start_link(Socket) -> end. + + +%% @spec notify(Player::Pid(), From::Pid(), +%% {Command::String(), Message::string()}) -> ok +%% @doc send a message to a player. +notify(Player, From, Message) -> end. + + +%% @spec get_token() -> string() +%% @doc Get the player token. +get_token() -> end. + + +%% @spec stop(Table::pid()) -> Reason::string() +%% @doc Properly terminates the process. +stop(Table) -> end. From e09b3cbd143facecb87714029fb31c6972c4b453 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 17:28:55 +0100 Subject: [PATCH 07/67] Refined ggs_player. --- src/ggs_player.erl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index bdfcf7d..4a24ef4 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,22 +1,26 @@ +-module(ggs_player). +-export([start_link/1, notify/3, get_token/1, stop/1]). +%% @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. - -%% @spec start_link(GameToken::string()) -> socket() -%% @doc Spawn a new player process. -start_link(Socket) -> end. +%% @doc Spawns a new player process. +%% @spec start_link(Socket::socket()) -> ok +start_link(Socket) -> not_implemented. %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok %% @doc send a message to a player. -notify(Player, From, Message) -> end. +notify(Player, From, Message) -> not_implemented. %% @spec get_token() -> string() %% @doc Get the player token. -get_token() -> end. +get_token() -> not_implemented. %% @spec stop(Table::pid()) -> Reason::string() %% @doc Properly terminates the process. -stop(Table) -> end. +stop(Table) -> not_implemented. From c42bd46c44c211eee59a325a7d9bcf798bd324c0 Mon Sep 17 00:00:00 2001 From: niklas Date: Wed, 16 Feb 2011 16:56:06 +0100 Subject: [PATCH 08/67] Initial interface --- src/ggs_coordinator.erl | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index e69de29..ed9c4e3 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -0,0 +1,38 @@ +-module(ggs_coordinator). +-export(). + +%% @doc This module act as "the man in the middle". +%% Creates the starting connection between table and players. + +%% @doc Starts the coordinator process. +start_link() -> + not_implemented. + +%% @doc Terminates the coordinator process. +stop() -> + not_implemented. + +%% @doc Creates a unique token for the table. +join_table() -> + not_implemented. + +%% @doc +create_table() -> + not_implemented. + +%% @doc This is the first function run by a newly created players. +%% Generates a unique token that we use to identify the player. +join_lobby() -> + not_implemented. + +%% @doc Act as a supervisor to player and respawns player when it gets bad data. +respawn_player(Player, Socket) -> + not_implemented. + +%% @doc Act as a supervisor to table and respawns table when it gets bad data. +respawn_table() -> + not_implemented. + +%% @doc Removes a player from coordinator. +remove_player(From, Player) -> + not_implemented. From c23e79de240b0c20d85f6a30188f96a4793c147f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 17:05:22 +0100 Subject: [PATCH 09/67] Updated ggs_dispatcher with gen_server functionality --- src/ggs_dispatcher.erl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 8f89ceb..bc3327a 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -1,6 +1,13 @@ -module(ggs_dispatcher). + +%% API Exports -export([start_link/1, stop/1]). +%% gen_server callback exports +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). + + %% @doc This module is the entry-point for clients connecting to GGS. This is %% the module responsible for: %% * Greeting a connecting client, and associating a socket for it @@ -19,3 +26,22 @@ start_link(Port) -> %% @spec stop(Reason) -> ok. %% Reason = String stop(Reason) -> not_implemented. + + +%% gen_server callbacks + +%% @doc Initiate the dispatcher. This is called from gen_server +init([Port]) -> + {ok, ok}. + +handle_call(_Message, _From, State) -> + {noreply, State}. + +handle_cast(_Message, State) -> + {noreply, State}. + +terminate(normal, _State) -> + ok. + +code_change(_OldVsn, State, Extra) -> + {ok, State}. From 702a887117cf9c1992b2d4b6997ee1e28a2d6065 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 18:03:48 +0100 Subject: [PATCH 10/67] Completed edoc of player. --- src/ggs_player.erl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 4a24ef4..b5815af 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -3,24 +3,30 @@ %% @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. +%% * 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 -%% @doc Spawns a new player process. +%% @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 start_link(Socket) -> not_implemented. +%% @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 -%% @doc send a message to a player. notify(Player, From, Message) -> not_implemented. - +%% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -%% @doc Get the player token. get_token() -> not_implemented. +%% @doc Properly terminates the player process. The player token will be destroyed. +%% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() -%% @doc Properly terminates the process. stop(Table) -> not_implemented. From a801008cd9438971db21a54d1b5b910e34716733 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:11:51 +0100 Subject: [PATCH 11/67] Initial interface --- src/ggs_network.erl | 170 ------------------------------------------ src/ggs_table.erl | 36 +++++++++ src/ggs_vm_runner.erl | 28 ------- 3 files changed, 36 insertions(+), 198 deletions(-) delete mode 100644 src/ggs_network.erl delete mode 100644 src/ggs_vm_runner.erl diff --git a/src/ggs_network.erl b/src/ggs_network.erl deleted file mode 100644 index be1b9d1..0000000 --- a/src/ggs_network.erl +++ /dev/null @@ -1,170 +0,0 @@ -%%%---------------------------------------------------- -%%% @author Jonatan Pålsson -%%% @copyright 2010 Jonatan Pålsson -%%% @doc RPC over TCP server -%%% @end -%%%---------------------------------------------------- -%%% @author Mattias Pettersson -%%% @doc Socket module for GGS -%%% @end -%%%---------------------------------------------------- - - --module(ggs_network). - --behaviour(gen_server). - -%define --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - - -% export --export([start_link/0,start_link/1]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -%-export([get_count/1,crash/0,vms/0,hello/0,echo/0]). --export([get_count/1]). --export([send/3, send/4]). --export([stop/0]). - -%% gen_server callbacks --export([terminate/2, code_change/3]). - -%state --record(state, {port, lsock, client_vm_map = []}). - - -%%----------------------------------------------------- -%% @doc Starts gen_server -%% @end -%%----------------------------------------------------- -start_link() -> - start_link(?DEFAULT_PORT). - -start_link(Port) -> - process_flag(trap_exit, true), - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). - -%%----------------------------------------------------- -%% Creation -%%----------------------------------------------------- -init([Port]) -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}. - -%%----------------------------------------------------- -%% @doc Fetches the number of requests made to this server -%% @spec get_count() -> {ok, Count} -%% where -%% Count = integer() -%% @end -%%----------------------------------------------------- -get_count(get_count) -> - gen_server:call(?SERVER, get_count). - -%crash() -> gen_server:call(?SERVER, crash). -%vms() -> gen_server:call(?SERVER, vms). -%hello() -> gen_server:call(?SERVER, hello). -%echo() -> gen_server:call(?SERVER, {echo, RefID, _, MSG}). - - - - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% Handlers -%%----------------------------------------------------- -handle_call(get_count, _From, State) -> - {reply, {ok, State#state.client_vm_map}, State}. - -handle_cast(stop, State) -> - {stop, normal, State}. - -handle_info({tcp, Socket, RawData}, State) -> %parameters coming from gen_server - NewState = do_JSCall(Socket, RawData, State), %TODO - OldMap = State#state.client_vm_map, - io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), - {noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}. - - -%%----------------------------------------------------- -%% TCP Calls -%%----------------------------------------------------- -send(Socket, RefID, String) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [RefID,String])). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [RefID, String1, String2])). - - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -do_JSCall(Socket, Data, State) -> - JSVM = js_runner:boot(), - js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), - Parsed = ggs_protocol:parse(Data), - NewState = case Parsed of - {cmd, Command, Parameter} -> - % Set the new state to [] - Ret = js_runner:call(JSVM, "userCommand", - [list_to_binary(Command), - list_to_binary(Parameter)]), - send(Socket, "RefID", "JS says: ", Ret), - []; - % Set the new state to the reference generated, and JSVM associated - {hello} -> - Client = getRef(), - send(Socket, Client, "__ok_hello"), - {Client, JSVM}; - {echo, RefID, _, MSG} -> - send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), - []; - {crash, Zero} -> - 10/Zero; - {vms} -> - send(Socket, "RefID", State); - % Set the new state to [] - Other -> - send(Socket, "RefID", "__error"), - [] - end, - % Return the new state - NewState. - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - {A1,A2,A3} = now(), - random:seed(A1, A2, A3), - random:uniform(1000). - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. diff --git a/src/ggs_table.erl b/src/ggs_table.erl index e69de29..87a623a 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -0,0 +1,36 @@ +%% @doc This module represents a Player with a Socket and a Token + +-module(ggs_table). +-export([ + start_link/1, + add_player/2, + remove_player/2, + stop/2, + notify/3 +]). + +% @doc returns a new table +start_link(Token) -> + not_implemented(). + +% @doc adds a player to a table +add_player(Table, Player) -> + not_implemented(). + +% @doc removes player form a table +remove_player(Table, Player) -> + not_implemented(). + +% @doc stops the table process +stop(Table) -> + not_implemented(). + +% @doc notifies the table with a message from a player +notify(Table, Player, Message) -> + not_implemented(). + + +% loop + + +% private helpers \ No newline at end of file diff --git a/src/ggs_vm_runner.erl b/src/ggs_vm_runner.erl deleted file mode 100644 index cf633f0..0000000 --- a/src/ggs_vm_runner.erl +++ /dev/null @@ -1,28 +0,0 @@ --module(ggs_vm_runner). --export([start_link/0, define/2, user_command/4]). - -%Mattias -start_link() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - js:define(Port, <<"function userCommand(user, command, args){}">>), - PortPid = spawn_link(fun() -> loop(Port) end ), - PortPid. - - -loop(Port) -> -receive - {define, SourceCode} -> - ok = js:define(Port, list_to_binary(SourceCode)), - loop(Port); - {user_command, User, Command, Args} -> - {ok, Ret} = js:call(Port, <<"userCommand">>, list_to_binary([User,Command,Args])), - loop(Port) -end. - - -define(GameVM, SourceCode) -> - GameVM ! {define,SourceCode}. - -user_command(GameVM, User, Command, Args) -> - GameVM ! {user_command, User, Command, Args}. From 4927d47065cac9d6fa19c2c5b8f99f2699c79a92 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:17:03 +0100 Subject: [PATCH 12/67] renamed test to unit_tests --- {tests => unit_tests}/ggs_protocol_test.erl | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {tests => unit_tests}/ggs_protocol_test.erl (100%) diff --git a/tests/ggs_protocol_test.erl b/unit_tests/ggs_protocol_test.erl similarity index 100% rename from tests/ggs_protocol_test.erl rename to unit_tests/ggs_protocol_test.erl From db7c99adb17d4af875b8f96d27648748e5c33bc6 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:17:56 +0100 Subject: [PATCH 13/67] removed unnecessary files --- unit_tests/ggs_protocol_test.erl | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 unit_tests/ggs_protocol_test.erl diff --git a/unit_tests/ggs_protocol_test.erl b/unit_tests/ggs_protocol_test.erl deleted file mode 100644 index 2230cbf..0000000 --- a/unit_tests/ggs_protocol_test.erl +++ /dev/null @@ -1,6 +0,0 @@ --module(ggs_protocol_test). --export([test_parse/0]). - -test_parse() -> - Ret = ggs_protocol:parse("<> __define JavaScript"), - io:format("~p~n", [Ret]). From 5d71202a00b70664616ee6650a51f790473ffa9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 17:19:00 +0100 Subject: [PATCH 14/67] Added OTP structure to ggs_coordinator --- src/ggs_coordinator.erl | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index ed9c4e3..4f38c6a 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,5 +1,11 @@ -module(ggs_coordinator). --export(). + +%% API Exports +-export([start_link/1, stop/1]). + +%% gen_server callback exports +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. @@ -9,15 +15,15 @@ start_link() -> not_implemented. %% @doc Terminates the coordinator process. -stop() -> +stop(_Reason) -> not_implemented. -%% @doc Creates a unique token for the table. -join_table() -> +%% @doc Joins table with specified token +join_table(_Token) -> not_implemented. -%% @doc -create_table() -> +%% @doc Create a new table +create_table(_Params) -> not_implemented. %% @doc This is the first function run by a newly created players. @@ -26,13 +32,30 @@ join_lobby() -> not_implemented. %% @doc Act as a supervisor to player and respawns player when it gets bad data. -respawn_player(Player, Socket) -> +respawn_player(_Player, _Socket) -> not_implemented. %% @doc Act as a supervisor to table and respawns table when it gets bad data. -respawn_table() -> +respawn_table(_Token) -> not_implemented. %% @doc Removes a player from coordinator. remove_player(From, Player) -> not_implemented. + +%% gen_server callbacks + +init([Port]) -> + {ok, ok}. + +handle_call(_Message, _From, State) -> + {noreply, State}. + +handle_cast(_Message, State) -> + {noreply, State}. + +terminate(normal, _State) -> + ok. + +code_change(_OldVsn, State, Extra) -> + {ok, State}. From 62be1f04cc570c9fab2f6cdfa4bb5982b64bb050 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:23:58 +0100 Subject: [PATCH 15/67] changed not_implemented to a function --- src/ggs_coordinator.erl | 16 ++++++++-------- src/ggs_dispatcher.erl | 4 ++-- src/ggs_player.erl | 12 ++++++++---- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4f38c6a..1081077 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -12,36 +12,36 @@ %% @doc Starts the coordinator process. start_link() -> - not_implemented. + not_implemented(). %% @doc Terminates the coordinator process. stop(_Reason) -> - not_implemented. + not_implemented(). %% @doc Joins table with specified token join_table(_Token) -> - not_implemented. + not_implemented(). %% @doc Create a new table create_table(_Params) -> - not_implemented. + not_implemented(). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - not_implemented. + not_implemented(). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> - not_implemented. + not_implemented(). %% @doc Act as a supervisor to table and respawns table when it gets bad data. respawn_table(_Token) -> - not_implemented. + not_implemented(). %% @doc Removes a player from coordinator. remove_player(From, Player) -> - not_implemented. + not_implemented(). %% gen_server callbacks diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index bc3327a..69d5481 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -20,12 +20,12 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented. + not_implemented(). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented. +stop(Reason) -> not_implemented(). %% gen_server callbacks diff --git a/src/ggs_player.erl b/src/ggs_player.erl index b5815af..6eb31c9 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -12,21 +12,25 @@ %% an argument for storage and later usage. Creates a unique player token %% identifying the player. %% @spec start_link(Socket::socket()) -> ok -start_link(Socket) -> not_implemented. +start_link(Socket) -> + not_implemented(). %% @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) -> not_implemented. +notify(Player, From, Message) -> + not_implemented(). %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -get_token() -> not_implemented. +get_token() -> + not_implemented(). %% @doc Properly terminates the player process. The player token will be destroyed. %% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(Table) -> not_implemented. +stop(Table) -> + not_implemented(). From 70a6beb8b9c7752afb018ec62e7febc9d3d9b146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 19:49:43 +0100 Subject: [PATCH 16/67] Added some basic echo functionality --- ebin/ggs.app | 3 +- src/ggs_coordinator.erl | 14 ++- src/ggs_dispatcher.erl | 30 ++++- src/ggs_gamevm.erl | 2 +- src/ggs_player.erl | 19 ++- src/ggs_sup.erl | 9 +- src/ggs_table.erl | 22 ++-- src/helpers.erl | 4 + src/old/ggs_app.erl | 14 --- src/old/ggs_backup.erl | 41 ------- src/old/ggs_mnesia_controller_server.erl | 68 ----------- src/old/ggs_protocol.erl | 49 -------- src/old/ggs_server.erl | 141 ----------------------- src/old/ggs_server_sup.erl | 48 -------- src/old/ggs_sup.erl | 34 ------ src/old/js_runner.erl | 13 --- src/old/start_ggs.erl | 7 -- 17 files changed, 70 insertions(+), 448 deletions(-) create mode 100644 src/helpers.erl delete mode 100644 src/old/ggs_app.erl delete mode 100644 src/old/ggs_backup.erl delete mode 100644 src/old/ggs_mnesia_controller_server.erl delete mode 100644 src/old/ggs_protocol.erl delete mode 100644 src/old/ggs_server.erl delete mode 100644 src/old/ggs_server_sup.erl delete mode 100644 src/old/ggs_sup.erl delete mode 100644 src/old/js_runner.erl delete mode 100644 src/old/start_ggs.erl diff --git a/ebin/ggs.app b/ebin/ggs.app index 3315864..b3ea744 100644 --- a/ebin/ggs.app +++ b/ebin/ggs.app @@ -3,7 +3,8 @@ {vsn, "0.1.0"}, {modules, [ ggs_app, - ggs_sup + ggs_sup, + ggs_dispatcher ]}, {registered, [ggs_sup]}, {applications, [kernel, stdlib]}, diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4f38c6a..9acffe4 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,18 +1,19 @@ -module(ggs_coordinator). %% API Exports --export([start_link/1, stop/1]). +-export([start_link/0, stop/1]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. %% @doc Starts the coordinator process. start_link() -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @doc Terminates the coordinator process. stop(_Reason) -> @@ -40,12 +41,12 @@ respawn_table(_Token) -> not_implemented. %% @doc Removes a player from coordinator. -remove_player(From, Player) -> +remove_player(_From, _Player) -> not_implemented. %% gen_server callbacks -init([Port]) -> +init([]) -> {ok, ok}. handle_call(_Message, _From, State) -> @@ -54,8 +55,11 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info(_Message, State) -> + {noreply, State}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index bc3327a..4b47ba3 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -1,5 +1,7 @@ -module(ggs_dispatcher). +-behaviour(gen_server). + %% API Exports -export([start_link/1, stop/1]). @@ -7,6 +9,8 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). + %% @doc This module is the entry-point for clients connecting to GGS. This is %% the module responsible for: @@ -20,19 +24,21 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented. +stop(_Reason) -> not_implemented. %% gen_server callbacks %% @doc Initiate the dispatcher. This is called from gen_server init([Port]) -> - {ok, ok}. + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, LSock, 0}. handle_call(_Message, _From, State) -> {noreply, State}. @@ -40,8 +46,24 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info({tcp, _Socket, RawData}, State) -> + io:format("Got connect request!~n"), + {noreply, State}; + +handle_info({tcp_closed, Socket}, State) -> + gen_tcp:close(Socket), + {stop, "Client closed socket", State}; + +%% @doc This is our function for accepting connections. When a client connects, +%% it will immediately time out due to timing settings set in init and here, +%% and when it does, we accept the connection. +handle_info(timeout, LSock) -> + {ok, Sock} = gen_tcp:accept(LSock), + spawn(ggs_player, start_link, [Sock]), + {noreply, LSock, 0}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 8116a96..1a8f547 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -1,4 +1,4 @@ --module(ggs_vm_runner). +-module(ggs_gamevm). -export([start_link/0, define/2, user_command/4]). %% @doc This module is responsible for running the game VM:s. You can issue %% commands to a vm using this module. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index b5815af..87c003c 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -12,21 +12,32 @@ %% an argument for storage and later usage. Creates a unique player token %% identifying the player. %% @spec start_link(Socket::socket()) -> ok -start_link(Socket) -> not_implemented. +start_link(Socket) -> + loop(Socket). %% @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) -> not_implemented. +notify(_Player, _From, _Message) -> not_implemented. %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -get_token() -> not_implemented. +get_token(_Player) -> not_implemented. %% @doc Properly terminates the player process. The player token will be destroyed. %% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(Table) -> not_implemented. +stop(_Table) -> not_implemented. + + +%% Internals + +loop(Socket) -> + receive {tcp, Socket, Data} -> % Just echo for now.. + gen_tcp:send(Socket,Data), + loop(Socket) + end. + diff --git a/src/ggs_sup.erl b/src/ggs_sup.erl index bfb2617..05fab65 100644 --- a/src/ggs_sup.erl +++ b/src/ggs_sup.erl @@ -2,17 +2,12 @@ -behaviour(supervisor). %% API --export([start/1, start_link/1]). +-export([start_link/1]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - start_link(Port) -> supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). @@ -29,7 +24,7 @@ init([Port]) -> permanent, 2000, worker, - [ggs_dispatcher] + [ggs_coordinator] }, Children = [Dispatcher, Coordinator], diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 87a623a..e00b840 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -10,27 +10,27 @@ ]). % @doc returns a new table -start_link(Token) -> - not_implemented(). +start_link(_Token) -> + helpers:not_implemented(). % @doc adds a player to a table -add_player(Table, Player) -> - not_implemented(). +add_player(_Table, _Player) -> + helpers:not_implemented(). % @doc removes player form a table -remove_player(Table, Player) -> - not_implemented(). +remove_player(_Table, _Player) -> + helpers:not_implemented(). % @doc stops the table process -stop(Table) -> - not_implemented(). +stop(_Table, _Msg) -> + helpers:not_implemented(). % @doc notifies the table with a message from a player -notify(Table, Player, Message) -> - not_implemented(). +notify(_Table, _Player, _Message) -> + helpers:not_implemented(). % loop -% private helpers \ No newline at end of file +% private helpers diff --git a/src/helpers.erl b/src/helpers.erl new file mode 100644 index 0000000..1bf7825 --- /dev/null +++ b/src/helpers.erl @@ -0,0 +1,4 @@ +-module(helpers). + +not_implemented() -> + exit("Not implemented"). diff --git a/src/old/ggs_app.erl b/src/old/ggs_app.erl deleted file mode 100644 index d8b2e60..0000000 --- a/src/old/ggs_app.erl +++ /dev/null @@ -1,14 +0,0 @@ --module(ggs_app). --behaviour(application). --export([start/2, stop/1]). - -start(_StartType, _StartArgs) -> - case ggs_sup:start_link(9000) of - {ok, Pid} -> - {ok, Pid}; - Other -> - {error, Other} - end. - -stop(_State) -> - ok. diff --git a/src/old/ggs_backup.erl b/src/old/ggs_backup.erl deleted file mode 100644 index 30c80a2..0000000 --- a/src/old/ggs_backup.erl +++ /dev/null @@ -1,41 +0,0 @@ --module(ggs_backup). --behaviour(gen_server). - -%% API --export([start_link/0 ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). - --record(state, {port, lsock, client_vm_map = []}). - -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -init([]) -> - {ok, #state{port = -1, lsock = -1, client_vm_map = -1}, 0}. - -handle_call(get_backup, _From, State) -> - BackedUpState = case State of - #state{port = -1, lsock = -1, client_vm_map = -1} -> - not_initialized; - Other -> - Other - end, - {reply, {backup_state, BackedUpState}, State}. - -handle_cast({set_backup, NewState}, _State) -> - {noreply, NewState}. - -handle_info(_Msg, State) -> - {noreply, State}. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -terminate(_Reason, _State) -> - ok. diff --git a/src/old/ggs_mnesia_controller_server.erl b/src/old/ggs_mnesia_controller_server.erl deleted file mode 100644 index c1f8a10..0000000 --- a/src/old/ggs_mnesia_controller_server.erl +++ /dev/null @@ -1,68 +0,0 @@ --module(ggs_mnesia_controller_server). --behaviour(gen_server). - -%% API --export([start_link/0, - stop/0 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). - --record(state, {}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([]) -> - mnesia:create_schema([node()]), - mnesia:start(), - {ok, {}, 0}. - -handle_cast(a, State) -> - {noreply, State}. - -% Request a value from the Mnesia database -handle_call({getValue, _Key},_From,State) -> - {reply,value_of_key_requested_goes_here, State}; - -% Set a value in the Mnesia database -handle_call({setValue, _Key, Value},_From,State) -> - {reply,value_set_or_updated, State}. - -handle_info(timeout, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- diff --git a/src/old/ggs_protocol.erl b/src/old/ggs_protocol.erl deleted file mode 100644 index 46c1ba1..0000000 --- a/src/old/ggs_protocol.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(ggs_protocol). --export([parse/1]). - -parse(Data) -> - Parsed = do_parse(Data, []), - prettify(Parsed). - -do_parse(Data, ParsedMessage) -> - NewLinePos = string:chr(Data, $\n), - Line = string:substr(Data, 1, NewLinePos-1), - Tokens = re:split(Line, ": ", [{return, list}]), - case handle(Tokens) of - {Command, more} -> - do_parse(string:substr(Data, NewLinePos+1), ParsedMessage ++ [Command]); - {separator, data_next} -> - {_, Value} = lists:keyfind(content_len, 1, ParsedMessage), - {ContentLength, []} = string:to_integer(Value), - {ParsedMessage, handle_data(string:substr(Data, NewLinePos+1), ContentLength)} - end. - -handle([[]]) -> - {separator, data_next}; -handle(["Server-Command", Param]) -> - {{srv_cmd, Param}, more}; -handle(["Content-Length", Param]) -> - {{content_len, Param}, more}; -handle(["Token", Param]) -> - {{token, Param}, more}; -handle(["Content-Type", Param]) -> - {{content_type, Param}, more}. - -handle_data(Data, Length) -> - {data, string:substr(Data,1,Length)}. - - -%% Helpers -prettify({Args, Data}) -> - case lists:keyfind(srv_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {srv_cmd, Value, Args, Data}); - _Other -> - case lists:keyfind(game_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {game_cmd, Value, Args, Data}); - _ -> - ok - end - end. - diff --git a/src/old/ggs_server.erl b/src/old/ggs_server.erl deleted file mode 100644 index 34d297f..0000000 --- a/src/old/ggs_server.erl +++ /dev/null @@ -1,141 +0,0 @@ -%%%---------------------------------------------------- -%%% @author Jonatan PÃ¥lsson -%%% @copyright 2010 Jonatan PÃ¥lsson -%%% @doc RPC over TCP server -%%% @end -%%%---------------------------------------------------- - --module(ggs_server). --behaviour(gen_server). - -%% API --export([start_link/1, - start_link/0, - stop/0 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - --record(state, {port, lsock, client_vm_map = []}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link(Port) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). - -start_link() -> - start_link(?DEFAULT_PORT). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([Port]) -> - case gen_server:call(ggs_backup, get_backup) of - {backup_state, not_initialized} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}; - {backup_state, State} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, State#state{lsock = LSock}, 0} - end. - -handle_call({backup_state, OldState}, _From, State) -> - io:format("Received old state from backup~n"), - {noreply, OldState}. - - -handle_info({tcp, Socket, RawData}, State) -> - ggs_protocol:parse(RawData), - {noreply, State#state{lsock = Socket}}; - -handle_info({tcp_closed, Socket}, State) -> - gen_tcp:close(Socket), - {stop, "Client closed socket", State}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}; - -handle_info(Other, State) -> - erlang:display(Other). - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -handle_cast(stop, State) -> - {stop, normal, State}; - -% Handle javascript defines -handle_cast({define, Token, SourceCode}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:define(GameVM, SourceCode), - send(State#state.lsock, Token, "Okay, defined that for you!"), - {noreply, State}; - -% Handle javascript calls -handle_cast({call, Token, Command}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:user_command(GameVM, "User", Command, []), - %send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), Unessecary - {noreply, State}; - -% Set the new state to the reference generated, and JSVM associated -handle_cast({hello, _, _}, State) -> - GameVM = ggs_vm_runner:start_link(), - Client = getRef(), - send(State#state.lsock, Client, "This is your refID"), - OldMap = State#state.client_vm_map, - NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - %{A1,A2,A3} = now(), - %#random:seed(A1, A2, A3), - %random:uniform(1000). - string:strip(os:cmd("uuidgen"), right, $\n ). - -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - erlang:display(RefID), - erlang:display(VMs), - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. - -send(Socket, RefID, String) -> - gen_tcp:send(Socket, string:join([RefID,String,"\n"], " ")). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, string:join([RefID,String1, String2,"\n"], " ")). diff --git a/src/old/ggs_server_sup.erl b/src/old/ggs_server_sup.erl deleted file mode 100644 index 23d32f7..0000000 --- a/src/old/ggs_server_sup.erl +++ /dev/null @@ -1,48 +0,0 @@ --module(ggs_server_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - GGSServer = {ggs_server, - {ggs_server, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server] - }, - Backup = {ggs_backup, - {ggs_backup, start_link, []}, - permanent, - 2000, - worker, - [ggs_backup] - }, - MnesiaServer = {ggs_mnesia_controller_server, - {ggs_mnesia_controller_server, start_link, []}, - permanent, - 2000, - worker, - [ggs_mnesia_controller_server] - }, - Children = [MnesiaServer, Backup, GGSServer], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/ggs_sup.erl b/src/old/ggs_sup.erl deleted file mode 100644 index ee6f8cd..0000000 --- a/src/old/ggs_sup.erl +++ /dev/null @@ -1,34 +0,0 @@ --module(ggs_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - Server = {ggs_server_sup, - {ggs_server_sup, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server_sup] - }, - Children = [Server], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/js_runner.erl b/src/old/js_runner.erl deleted file mode 100644 index ca866c4..0000000 --- a/src/old/js_runner.erl +++ /dev/null @@ -1,13 +0,0 @@ --module(js_runner). --export([define/2,call/3, boot/0]). - -boot() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - Port. - -define(Port, Data) -> - ok = js:define(Port, list_to_binary(Data)). - -call(Port, Func, Params) -> - js:call(Port, list_to_binary(Func), Params). diff --git a/src/old/start_ggs.erl b/src/old/start_ggs.erl deleted file mode 100644 index 3955715..0000000 --- a/src/old/start_ggs.erl +++ /dev/null @@ -1,7 +0,0 @@ --module(start_ggs). --export([start/0]). - -start() -> - application:start(inets), - application:start(erlang_js), - application:start(ggs). From ec78283a4640ab4e126cb65c0ea39f1005bc86ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 19:49:43 +0100 Subject: [PATCH 17/67] Added some basic echo functionality --- ebin/ggs.app | 3 +- src/ggs_coordinator.erl | 14 ++- src/ggs_dispatcher.erl | 30 ++++- src/ggs_gamevm.erl | 2 +- src/ggs_player.erl | 24 +++- src/ggs_sup.erl | 9 +- src/ggs_table.erl | 22 ++-- src/helpers.erl | 4 + src/old/ggs_app.erl | 14 --- src/old/ggs_backup.erl | 41 ------- src/old/ggs_mnesia_controller_server.erl | 68 ----------- src/old/ggs_protocol.erl | 49 -------- src/old/ggs_server.erl | 141 ----------------------- src/old/ggs_server_sup.erl | 48 -------- src/old/ggs_sup.erl | 34 ------ src/old/js_runner.erl | 13 --- src/old/start_ggs.erl | 7 -- 17 files changed, 75 insertions(+), 448 deletions(-) create mode 100644 src/helpers.erl delete mode 100644 src/old/ggs_app.erl delete mode 100644 src/old/ggs_backup.erl delete mode 100644 src/old/ggs_mnesia_controller_server.erl delete mode 100644 src/old/ggs_protocol.erl delete mode 100644 src/old/ggs_server.erl delete mode 100644 src/old/ggs_server_sup.erl delete mode 100644 src/old/ggs_sup.erl delete mode 100644 src/old/js_runner.erl delete mode 100644 src/old/start_ggs.erl diff --git a/ebin/ggs.app b/ebin/ggs.app index 3315864..b3ea744 100644 --- a/ebin/ggs.app +++ b/ebin/ggs.app @@ -3,7 +3,8 @@ {vsn, "0.1.0"}, {modules, [ ggs_app, - ggs_sup + ggs_sup, + ggs_dispatcher ]}, {registered, [ggs_sup]}, {applications, [kernel, stdlib]}, diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4f38c6a..9acffe4 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,18 +1,19 @@ -module(ggs_coordinator). %% API Exports --export([start_link/1, stop/1]). +-export([start_link/0, stop/1]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. %% @doc Starts the coordinator process. start_link() -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @doc Terminates the coordinator process. stop(_Reason) -> @@ -40,12 +41,12 @@ respawn_table(_Token) -> not_implemented. %% @doc Removes a player from coordinator. -remove_player(From, Player) -> +remove_player(_From, _Player) -> not_implemented. %% gen_server callbacks -init([Port]) -> +init([]) -> {ok, ok}. handle_call(_Message, _From, State) -> @@ -54,8 +55,11 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info(_Message, State) -> + {noreply, State}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index bc3327a..4b47ba3 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -1,5 +1,7 @@ -module(ggs_dispatcher). +-behaviour(gen_server). + %% API Exports -export([start_link/1, stop/1]). @@ -7,6 +9,8 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). + %% @doc This module is the entry-point for clients connecting to GGS. This is %% the module responsible for: @@ -20,19 +24,21 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented. +stop(_Reason) -> not_implemented. %% gen_server callbacks %% @doc Initiate the dispatcher. This is called from gen_server init([Port]) -> - {ok, ok}. + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, LSock, 0}. handle_call(_Message, _From, State) -> {noreply, State}. @@ -40,8 +46,24 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info({tcp, _Socket, RawData}, State) -> + io:format("Got connect request!~n"), + {noreply, State}; + +handle_info({tcp_closed, Socket}, State) -> + gen_tcp:close(Socket), + {stop, "Client closed socket", State}; + +%% @doc This is our function for accepting connections. When a client connects, +%% it will immediately time out due to timing settings set in init and here, +%% and when it does, we accept the connection. +handle_info(timeout, LSock) -> + {ok, Sock} = gen_tcp:accept(LSock), + spawn(ggs_player, start_link, [Sock]), + {noreply, LSock, 0}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 8116a96..1a8f547 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -1,4 +1,4 @@ --module(ggs_vm_runner). +-module(ggs_gamevm). -export([start_link/0, define/2, user_command/4]). %% @doc This module is responsible for running the game VM:s. You can issue %% commands to a vm using this module. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index b5815af..a459499 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -12,21 +12,37 @@ %% an argument for storage and later usage. Creates a unique player token %% identifying the player. %% @spec start_link(Socket::socket()) -> ok -start_link(Socket) -> not_implemented. +start_link(Socket) -> + loop(Socket). %% @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) -> not_implemented. +notify(_Player, _From, _Message) -> not_implemented. %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -get_token() -> not_implemented. +get_token(_Player) -> not_implemented. %% @doc Properly terminates the player process. The player token will be destroyed. %% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(Table) -> not_implemented. +stop(_Table) -> not_implemented. + + +%% Internals + +loop(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()), + receive {tcp, Socket, Data} -> % Just echo for now.. + gen_tcp:send(Socket,Data), + loop(Socket) + end. + diff --git a/src/ggs_sup.erl b/src/ggs_sup.erl index bfb2617..05fab65 100644 --- a/src/ggs_sup.erl +++ b/src/ggs_sup.erl @@ -2,17 +2,12 @@ -behaviour(supervisor). %% API --export([start/1, start_link/1]). +-export([start_link/1]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - start_link(Port) -> supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). @@ -29,7 +24,7 @@ init([Port]) -> permanent, 2000, worker, - [ggs_dispatcher] + [ggs_coordinator] }, Children = [Dispatcher, Coordinator], diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 87a623a..e00b840 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -10,27 +10,27 @@ ]). % @doc returns a new table -start_link(Token) -> - not_implemented(). +start_link(_Token) -> + helpers:not_implemented(). % @doc adds a player to a table -add_player(Table, Player) -> - not_implemented(). +add_player(_Table, _Player) -> + helpers:not_implemented(). % @doc removes player form a table -remove_player(Table, Player) -> - not_implemented(). +remove_player(_Table, _Player) -> + helpers:not_implemented(). % @doc stops the table process -stop(Table) -> - not_implemented(). +stop(_Table, _Msg) -> + helpers:not_implemented(). % @doc notifies the table with a message from a player -notify(Table, Player, Message) -> - not_implemented(). +notify(_Table, _Player, _Message) -> + helpers:not_implemented(). % loop -% private helpers \ No newline at end of file +% private helpers diff --git a/src/helpers.erl b/src/helpers.erl new file mode 100644 index 0000000..1bf7825 --- /dev/null +++ b/src/helpers.erl @@ -0,0 +1,4 @@ +-module(helpers). + +not_implemented() -> + exit("Not implemented"). diff --git a/src/old/ggs_app.erl b/src/old/ggs_app.erl deleted file mode 100644 index d8b2e60..0000000 --- a/src/old/ggs_app.erl +++ /dev/null @@ -1,14 +0,0 @@ --module(ggs_app). --behaviour(application). --export([start/2, stop/1]). - -start(_StartType, _StartArgs) -> - case ggs_sup:start_link(9000) of - {ok, Pid} -> - {ok, Pid}; - Other -> - {error, Other} - end. - -stop(_State) -> - ok. diff --git a/src/old/ggs_backup.erl b/src/old/ggs_backup.erl deleted file mode 100644 index 30c80a2..0000000 --- a/src/old/ggs_backup.erl +++ /dev/null @@ -1,41 +0,0 @@ --module(ggs_backup). --behaviour(gen_server). - -%% API --export([start_link/0 ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). - --record(state, {port, lsock, client_vm_map = []}). - -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -init([]) -> - {ok, #state{port = -1, lsock = -1, client_vm_map = -1}, 0}. - -handle_call(get_backup, _From, State) -> - BackedUpState = case State of - #state{port = -1, lsock = -1, client_vm_map = -1} -> - not_initialized; - Other -> - Other - end, - {reply, {backup_state, BackedUpState}, State}. - -handle_cast({set_backup, NewState}, _State) -> - {noreply, NewState}. - -handle_info(_Msg, State) -> - {noreply, State}. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -terminate(_Reason, _State) -> - ok. diff --git a/src/old/ggs_mnesia_controller_server.erl b/src/old/ggs_mnesia_controller_server.erl deleted file mode 100644 index c1f8a10..0000000 --- a/src/old/ggs_mnesia_controller_server.erl +++ /dev/null @@ -1,68 +0,0 @@ --module(ggs_mnesia_controller_server). --behaviour(gen_server). - -%% API --export([start_link/0, - stop/0 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). - --record(state, {}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([]) -> - mnesia:create_schema([node()]), - mnesia:start(), - {ok, {}, 0}. - -handle_cast(a, State) -> - {noreply, State}. - -% Request a value from the Mnesia database -handle_call({getValue, _Key},_From,State) -> - {reply,value_of_key_requested_goes_here, State}; - -% Set a value in the Mnesia database -handle_call({setValue, _Key, Value},_From,State) -> - {reply,value_set_or_updated, State}. - -handle_info(timeout, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- diff --git a/src/old/ggs_protocol.erl b/src/old/ggs_protocol.erl deleted file mode 100644 index 46c1ba1..0000000 --- a/src/old/ggs_protocol.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(ggs_protocol). --export([parse/1]). - -parse(Data) -> - Parsed = do_parse(Data, []), - prettify(Parsed). - -do_parse(Data, ParsedMessage) -> - NewLinePos = string:chr(Data, $\n), - Line = string:substr(Data, 1, NewLinePos-1), - Tokens = re:split(Line, ": ", [{return, list}]), - case handle(Tokens) of - {Command, more} -> - do_parse(string:substr(Data, NewLinePos+1), ParsedMessage ++ [Command]); - {separator, data_next} -> - {_, Value} = lists:keyfind(content_len, 1, ParsedMessage), - {ContentLength, []} = string:to_integer(Value), - {ParsedMessage, handle_data(string:substr(Data, NewLinePos+1), ContentLength)} - end. - -handle([[]]) -> - {separator, data_next}; -handle(["Server-Command", Param]) -> - {{srv_cmd, Param}, more}; -handle(["Content-Length", Param]) -> - {{content_len, Param}, more}; -handle(["Token", Param]) -> - {{token, Param}, more}; -handle(["Content-Type", Param]) -> - {{content_type, Param}, more}. - -handle_data(Data, Length) -> - {data, string:substr(Data,1,Length)}. - - -%% Helpers -prettify({Args, Data}) -> - case lists:keyfind(srv_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {srv_cmd, Value, Args, Data}); - _Other -> - case lists:keyfind(game_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {game_cmd, Value, Args, Data}); - _ -> - ok - end - end. - diff --git a/src/old/ggs_server.erl b/src/old/ggs_server.erl deleted file mode 100644 index 34d297f..0000000 --- a/src/old/ggs_server.erl +++ /dev/null @@ -1,141 +0,0 @@ -%%%---------------------------------------------------- -%%% @author Jonatan PÃ¥lsson -%%% @copyright 2010 Jonatan PÃ¥lsson -%%% @doc RPC over TCP server -%%% @end -%%%---------------------------------------------------- - --module(ggs_server). --behaviour(gen_server). - -%% API --export([start_link/1, - start_link/0, - stop/0 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - --record(state, {port, lsock, client_vm_map = []}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link(Port) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). - -start_link() -> - start_link(?DEFAULT_PORT). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([Port]) -> - case gen_server:call(ggs_backup, get_backup) of - {backup_state, not_initialized} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}; - {backup_state, State} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, State#state{lsock = LSock}, 0} - end. - -handle_call({backup_state, OldState}, _From, State) -> - io:format("Received old state from backup~n"), - {noreply, OldState}. - - -handle_info({tcp, Socket, RawData}, State) -> - ggs_protocol:parse(RawData), - {noreply, State#state{lsock = Socket}}; - -handle_info({tcp_closed, Socket}, State) -> - gen_tcp:close(Socket), - {stop, "Client closed socket", State}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}; - -handle_info(Other, State) -> - erlang:display(Other). - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -handle_cast(stop, State) -> - {stop, normal, State}; - -% Handle javascript defines -handle_cast({define, Token, SourceCode}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:define(GameVM, SourceCode), - send(State#state.lsock, Token, "Okay, defined that for you!"), - {noreply, State}; - -% Handle javascript calls -handle_cast({call, Token, Command}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:user_command(GameVM, "User", Command, []), - %send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), Unessecary - {noreply, State}; - -% Set the new state to the reference generated, and JSVM associated -handle_cast({hello, _, _}, State) -> - GameVM = ggs_vm_runner:start_link(), - Client = getRef(), - send(State#state.lsock, Client, "This is your refID"), - OldMap = State#state.client_vm_map, - NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - %{A1,A2,A3} = now(), - %#random:seed(A1, A2, A3), - %random:uniform(1000). - string:strip(os:cmd("uuidgen"), right, $\n ). - -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - erlang:display(RefID), - erlang:display(VMs), - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. - -send(Socket, RefID, String) -> - gen_tcp:send(Socket, string:join([RefID,String,"\n"], " ")). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, string:join([RefID,String1, String2,"\n"], " ")). diff --git a/src/old/ggs_server_sup.erl b/src/old/ggs_server_sup.erl deleted file mode 100644 index 23d32f7..0000000 --- a/src/old/ggs_server_sup.erl +++ /dev/null @@ -1,48 +0,0 @@ --module(ggs_server_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - GGSServer = {ggs_server, - {ggs_server, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server] - }, - Backup = {ggs_backup, - {ggs_backup, start_link, []}, - permanent, - 2000, - worker, - [ggs_backup] - }, - MnesiaServer = {ggs_mnesia_controller_server, - {ggs_mnesia_controller_server, start_link, []}, - permanent, - 2000, - worker, - [ggs_mnesia_controller_server] - }, - Children = [MnesiaServer, Backup, GGSServer], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/ggs_sup.erl b/src/old/ggs_sup.erl deleted file mode 100644 index ee6f8cd..0000000 --- a/src/old/ggs_sup.erl +++ /dev/null @@ -1,34 +0,0 @@ --module(ggs_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - Server = {ggs_server_sup, - {ggs_server_sup, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server_sup] - }, - Children = [Server], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/js_runner.erl b/src/old/js_runner.erl deleted file mode 100644 index ca866c4..0000000 --- a/src/old/js_runner.erl +++ /dev/null @@ -1,13 +0,0 @@ --module(js_runner). --export([define/2,call/3, boot/0]). - -boot() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - Port. - -define(Port, Data) -> - ok = js:define(Port, list_to_binary(Data)). - -call(Port, Func, Params) -> - js:call(Port, list_to_binary(Func), Params). diff --git a/src/old/start_ggs.erl b/src/old/start_ggs.erl deleted file mode 100644 index 3955715..0000000 --- a/src/old/start_ggs.erl +++ /dev/null @@ -1,7 +0,0 @@ --module(start_ggs). --export([start/0]). - -start() -> - application:start(inets), - application:start(erlang_js), - application:start(ggs). From 4be808049e0de12cd0a2cb5ea08353bd251884f0 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 20:53:36 +0100 Subject: [PATCH 18/67] added ggs_logger module and implemented some ggs_table stuff --- src/ggs_coordinator.erl | 16 ++++++++-------- src/ggs_dispatcher.erl | 4 ++-- src/ggs_logger.erl | 8 ++++++++ src/ggs_player.erl | 8 ++++---- src/ggs_table.erl | 39 ++++++++++++++++++++++++++++++--------- 5 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 src/ggs_logger.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 1081077..21bb641 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -12,36 +12,36 @@ %% @doc Starts the coordinator process. start_link() -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Terminates the coordinator process. stop(_Reason) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Joins table with specified token join_table(_Token) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Create a new table create_table(_Params) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to table and respawns table when it gets bad data. respawn_table(_Token) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Removes a player from coordinator. remove_player(From, Player) -> - not_implemented(). + ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 69d5481..fadb96d 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -20,12 +20,12 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented(). +stop(Reason) -> ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_logger.erl b/src/ggs_logger.erl new file mode 100644 index 0000000..40a9595 --- /dev/null +++ b/src/ggs_logger.erl @@ -0,0 +1,8 @@ +-module(ggs_logger). +-export(not_implemented/0, log/2). + +not_implemented() -> + exit(not_implemented). + +log(Format, Args) -> + error_logger:info_msg(Format, Args). \ No newline at end of file diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 6eb31c9..ae20ae8 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -13,7 +13,7 @@ %% identifying the player. %% @spec start_link(Socket::socket()) -> ok start_link(Socket) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Handles incoming messages from the GGS and forwards them through the player @@ -21,16 +21,16 @@ start_link(Socket) -> %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok notify(Player, From, Message) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() get_token() -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Properly terminates the player process. The player token will be destroyed. %% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() stop(Table) -> - not_implemented(). + ggs_logger:not_implemented(). diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 87a623a..5c0cbf0 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -1,5 +1,3 @@ -%% @doc This module represents a Player with a Socket and a Token - -module(ggs_table). -export([ start_link/1, @@ -9,28 +7,51 @@ notify/3 ]). +%% @doc This module represents a Player with a Socket and a Token + % @doc returns a new table -start_link(Token) -> - not_implemented(). +start_link(Token, Socket) -> + spawn_link(fun(Token, Socket) -> + GameVM = ggs_gamevm:start_link(); + loop(Token, Socket, GameVM, []) + ). % @doc adds a player to a table add_player(Table, Player) -> - not_implemented(). + ggs_logger:not_implemented(). % @doc removes player form a table remove_player(Table, Player) -> - not_implemented(). + ggs_logger:not_implemented(). % @doc stops the table process stop(Table) -> - not_implemented(). + Table ! {'EXIT', self(), normal} % @doc notifies the table with a message from a player notify(Table, Player, Message) -> - not_implemented(). + Table ! {notify, Player, Message}. % loop - +loop(Token, Socket, GameVM, PlayerList) -> + receive + {add_player, Player} -> + NewPlayerList = list:append(PlayerList, [Player]), + loop(Token, Socket, GameVM, NewPlayerList); + {remove_player, Player} -> + NewPlayerList = list:delete(Player, PlayerList), + loop(Token, Socket, GameVM, NewPlayerList); + {notify, Player, Message} -> + case Message of + {server, define, Args} -> + ggs_gamevm:define(GameVM, Args), + loop(Token, Socket, GameVM, PlayerList); + {game, Command, Args} -> + ggs_gamevm:user_command(GameVM, Player, Command, Args), + loop(Token, Socket, GameVM, PlayerList); + end + end. + % private helpers \ No newline at end of file From 2455f5582ce6858065143330c47299cd89529a24 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 21:18:32 +0100 Subject: [PATCH 19/67] Added ggs_player_test skeleton. Return in player start_link is now {ok, Pid} | {error, Reason}. --- src/ggs_player.erl | 9 +++++---- tests/ggs_player_test.erl | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/ggs_player_test.erl diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 79d0d06..2a9aee1 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -11,7 +11,7 @@ %% @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 +%% @spec start_link(Socket::socket()) -> {ok, Pid} | {error, Reason} start_link(Socket) -> loop(Socket). @@ -27,10 +27,11 @@ notify(Player, From, Message) -> get_token(_Player) -> helpers:not_implemented(). -%% @doc Properly terminates the player process. The player token will be destroyed. -%% Makes table token unreferenced and destroys the process in the end. +%% @doc Properly terminates the player process. The player token will be lost +%% 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(_Table) -> +stop(_Player,_Table) -> helpers:not_implemented(). %% Internals diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl new file mode 100644 index 0000000..fc13eb5 --- /dev/null +++ b/tests/ggs_player_test.erl @@ -0,0 +1,23 @@ +-include_lib("eunit/include/eunit.hrl"). +-import(ggs_player). + +%% @doc start_link should always return ok for any valid socket. A valid socket +%% should always return {ok, Pid} and {error, Reason} otherwise. +start_link_test() -> + helpers:not_implemented(). + +%% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and +%% deliver a specified message through the socket. +notify_test() -> + helpers:not_implemented(). + +%% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid +%% player token. a valid token should be unique. +get_token_test() -> + helpers:not_implemented(). + +%% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to +%% execute this function with the same Player and Table arguments twice. +stop_test() -> + helpers:not_implemented(). + From 8a780adb2d8a89e78a191dea856f289d94e17555 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 01:01:54 +0100 Subject: [PATCH 20/67] changed to a gen_server --- src/ggs_table.erl | 132 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 40 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index e9c1518..cf22ddc 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -1,53 +1,105 @@ --module(ggs_table). --export([ - start_link/1, - add_player/2, - remove_player/2, - stop/2, - notify/3 -]). - %% @doc This module represents a Player with a Socket and a Token +-module(ggs_table). +-behaviour(gen_server). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, { token, players, socket, game_vm } ). + +%% API +-export([start_link/2, + add_player/2, + remove_player/2, + stop/1, + notify/3]). + +-include_lib("eunit/include/eunit.hrl"). + +%% ---------------------------------------------------------------------- +% API implementation + % @doc returns a new table start_link(Token, Socket) -> - spawn_link(fun(Token, Socket) -> - GameVM = ggs_gamevm:start_link(); - loop(Token, Socket, GameVM, []) - ). + GameVM = ggs_gamevm:start_link(), + {ok, Pid} = gen_server:start_link(?MODULE, [Token, Socket, GameVM], []), + Pid. + +%% @private +call(Pid, Msg) -> + gen_server:call(Pid, Msg, infinity). % @doc adds a player to a table add_player(Table, Player) -> - ggs_logger:not_implemented(). - + call(Table, {add_player, Player}). + % @doc removes player form a table remove_player(Table, Player) -> - ggs_logger:not_implemented(). - + call(Table, {remove_player, Player}). + % @doc stops the table process stop(Table) -> - Table ! {'EXIT', self(), normal} - + gen_server:cast(Table, stop). + % @doc notifies the table with a message from a player notify(Table, Player, Message) -> - Table ! {notify, Player, Message}. - -% loop -loop(Token, Socket, GameVM, PlayerList) -> - receive - {add_player, Player} -> - NewPlayerList = list:append(PlayerList, [Player]), - loop(Token, Socket, GameVM, NewPlayerList); - {remove_player, Player} -> - NewPlayerList = list:delete(Player, PlayerList), - loop(Token, Socket, GameVM, NewPlayerList); - {notify, Player, Message} -> - case Message of - {server, define, Args} -> - ggs_gamevm:define(GameVM, Args), - loop(Token, Socket, GameVM, PlayerList); - {game, Command, Args} -> - ggs_gamevm:user_command(GameVM, Player, Command, Args), - loop(Token, Socket, GameVM, PlayerList); - end - end. + gen_server:cast(Table, {notify, Player, Message}). + +%% ---------------------------------------------------------------------- + +%% @private +init([Token, Socket, GameVM]) -> + {ok, #state { token = Token, + socket = Socket, + game_vm = GameVM, + players = [] }}. + +%% @private +handle_call({add_player, Player}, _From, #state { players = Players } = State) -> + {reply, ok, State#state { players = [Player | Players] }}; +handle_call({remove_player, Player}, _From, #state { players = Players } = State) -> + {reply, ok, State#state { players = Players -- [Player] }}; +handle_call(Msg, _From, State) -> + error_logger:error_report([unknown_msg, Msg]), + {reply, ok, State}. + +%% @private +handle_cast({notify, Player, Message}, #state { game_vm = GameVM } = State) -> + case Message of + {server, define, Args} -> + ggs_gamevm:define(GameVM, Args); + {game, Command, Args} -> + ggs_gamevm:user_command(GameVM, Player, Command, Args) + end, + {noreply, State}; +handle_cast(stop, State) -> + {stop, normal, State}; +handle_cast(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +handle_info(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +terminate(_Reason, _State) -> + ok. + +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%% ---------------------------------------------------------------------- + +% Tests + +%% @private +start_link_test() -> + ClientToken = "123", + Pid = start_link(ClientToken, none), + ?assertNot(Pid =:= undefined). From 6865e7368412a4f55b786092d746bce05c6aa0a4 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 01:57:09 +0100 Subject: [PATCH 21/67] changed from stop/1 to stop/2 in export --- src/ggs_player.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 2a9aee1..c3695af 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,5 +1,5 @@ -module(ggs_player). --export([start_link/1, notify/3, get_token/1, stop/1]). +-export([start_link/1, notify/3, get_token/1, stop/2]). %% @doc This module handles communication between a player and GGS. This module is %%responsible for: From d018034b7f55ff4449a5984f5eb70e68f7c74fb9 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 01:57:29 +0100 Subject: [PATCH 22/67] added another test --- src/ggs_table.erl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index cf22ddc..db247c4 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -61,6 +61,8 @@ handle_call({add_player, Player}, _From, #state { players = Players } = State) - {reply, ok, State#state { players = [Player | Players] }}; handle_call({remove_player, Player}, _From, #state { players = Players } = State) -> {reply, ok, State#state { players = Players -- [Player] }}; +handle_call(get_player_list, _From, #state { players = Players } = State) -> + {reply, {ok, Players}, State}; handle_call(Msg, _From, State) -> error_logger:error_report([unknown_msg, Msg]), {reply, ok, State}. @@ -98,8 +100,15 @@ code_change(_OldVsn, State, _Extra) -> % Tests -%% @private start_link_test() -> ClientToken = "123", Pid = start_link(ClientToken, none), ?assertNot(Pid =:= undefined). + +add_player_test() -> + Table = start_link("123", none), + Player = "test", %ggs_player:start_link(none), + add_player(Table, Player), + {ok, [Player]} = gen_server:call(Table, get_player_list). + + From ea1557e2d74ca72bf2afcbf6d09aeef83b24190b Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 02:28:14 +0100 Subject: [PATCH 23/67] added a notify test --- src/ggs_table.erl | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index db247c4..1e4f323 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -101,14 +101,38 @@ code_change(_OldVsn, State, _Extra) -> % Tests start_link_test() -> - ClientToken = "123", - Pid = start_link(ClientToken, none), - ?assertNot(Pid =:= undefined). + Table = start_link("123", none), + ?assertNot(Table =:= undefined). add_player_test() -> Table = start_link("123", none), - Player = "test", %ggs_player:start_link(none), + Player = test_player, add_player(Table, Player), {ok, [Player]} = gen_server:call(Table, get_player_list). +remove_player_test() -> + Table = start_link("123", none), + Player = test_player, + Player2 = test_player2, + add_player(Table, Player), + {ok, [Player]} = gen_server:call(Table, get_player_list), + add_player(Table, Player2), + {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), + remove_player(Table, Player), + {ok, [Player2]} = gen_server:call(Table, get_player_list), + remove_player(Table, Player2), + {ok, []} = gen_server:call(Table, get_player_list). +stop_test() -> + Table = start_link("123", none), + ok = stop(Table). + +% @private +notify_test() -> + Table = start_link("123", none), + Player = test_player, + Message = {server, define, "function helloWorld(x) { }"}, + ok = notify(Table, Player, Message). + %Message2 = {game, "helloWorld", "test"}, + %ok = notify(Table, Player, Message2). + \ No newline at end of file From 94d9dc6d7f546b0e4613bb66510488f181934bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 08:33:55 +0100 Subject: [PATCH 24/67] ggs_logger got lost somewhere? I added it again, also replaced all references to helpers with ggs_logger --- src/ggs_coordinator.erl | 14 +++++++------- src/ggs_dispatcher.erl | 2 +- src/ggs_logger.erl | 8 ++++++++ src/ggs_player.erl | 6 +++--- tests/ggs_player_test.erl | 8 ++++---- 5 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 src/ggs_logger.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 2a755f0..4e6b623 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -17,32 +17,32 @@ start_link() -> %% @doc Terminates the coordinator process. stop(_Reason) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Joins table with specified token join_table(_Token) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Create a new table create_table(_Params) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to table and respawns table when it gets bad data. respawn_table(_Token) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Removes a player from coordinator. remove_player(_From, _Player) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 4e353da..49dcf4b 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -29,7 +29,7 @@ start_link(Port) -> %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(_Reason) -> helpers:not_implemented(). +stop(_Reason) -> ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_logger.erl b/src/ggs_logger.erl new file mode 100644 index 0000000..49f5abc --- /dev/null +++ b/src/ggs_logger.erl @@ -0,0 +1,8 @@ +-module(ggs_logger). +-export([not_implemented/0, log/2]). + +not_implemented() -> + exit(not_implemented). + +log(Format, Args) -> + error_logger:info_msg(Format, Args). diff --git a/src/ggs_player.erl b/src/ggs_player.erl index c3695af..37c8496 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -20,19 +20,19 @@ start_link(Socket) -> %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok notify(Player, From, Message) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() get_token(_Player) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Properly terminates the player process. The player token will be lost %% 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) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% Internals diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index fc13eb5..1067f71 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -4,20 +4,20 @@ %% @doc start_link should always return ok for any valid socket. A valid socket %% should always return {ok, Pid} and {error, Reason} otherwise. start_link_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and %% deliver a specified message through the socket. notify_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid %% player token. a valid token should be unique. get_token_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to %% execute this function with the same Player and Table arguments twice. stop_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). From 654aa837ddacc2623b418173a48072f6b22873de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 09:35:39 +0100 Subject: [PATCH 25/67] Added some tests for coordinator --- src/ggs_coordinator.erl | 7 +++++-- tests/ggs_coordinator_test.erl | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/ggs_coordinator_test.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4e6b623..a28fc2a 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -16,8 +16,8 @@ start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @doc Terminates the coordinator process. -stop(_Reason) -> - ggs_logger:not_implemented(). +stop(Reason) -> + gen_server:cast(ggs_coordinator, {stop, Reason}). %% @doc Joins table with specified token join_table(_Token) -> @@ -52,6 +52,9 @@ init([]) -> handle_call(_Message, _From, State) -> {noreply, State}. +handle_cast({stop, Reason}, State) -> + {stop, normal, state}; + handle_cast(_Message, State) -> {noreply, State}. diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl new file mode 100644 index 0000000..03b5389 --- /dev/null +++ b/tests/ggs_coordinator_test.erl @@ -0,0 +1,16 @@ +-module(ggs_coordinator_test). +-include_lib("eunit/include/eunit.hrl"). + +start_link_test() -> + {ok, Coord} = ggs_coordinator:start_link(), % Start + PInfo = erlang:process_info(Coord), % Check process info + ggs_coordinator:stop(""), % Clean up + timer:sleep(100), % Wait for cleaning.. + ?assert((PInfo /= undefined)). % Did the server start? + +stop_test() -> + ok = ggs_coordinator:stop(""), % Extra cleaning + {ok, Coord} = ggs_coordinator:start_link(), % Start server + ggs_coordinator:stop("Terminate now"), % Send stop message + timer:sleep(100), % Wait for cleaning.. + ?assert((erlang:process_info(Coord) == undefined)). % Did it stop? From 391af1a96af8b2f603459181bedcd1e191668a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 10:04:54 +0100 Subject: [PATCH 26/67] Added more tests & functionality. (failing join table, create_table_test with force) --- src/ggs_coordinator.erl | 21 ++++++++++++++------- tests/ggs_coordinator_test.erl | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index a28fc2a..2a5d509 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,7 +1,7 @@ -module(ggs_coordinator). %% API Exports --export([start_link/0, stop/1]). +-export([start_link/0, stop/1, join_table/1, create_table/1]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, @@ -19,13 +19,14 @@ start_link() -> stop(Reason) -> gen_server:cast(ggs_coordinator, {stop, Reason}). -%% @doc Joins table with specified token -join_table(_Token) -> - ggs_logger:not_implemented(). +%% @doc Joins table with specified token, returns {error, no_such_table} +%% if the specified table token does not exist +join_table(Token) -> + gen_server:call(ggs_coordinator, {join_table, Token}). -%% @doc Create a new table -create_table(_Params) -> - ggs_logger:not_implemented(). +%% @doc Create a new table, return {error, Reason} or {ok, TableToken} +create_table(Params) -> + gen_server:call(ggs_coordinator, {create_table, Params}). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. @@ -49,6 +50,12 @@ remove_player(_From, _Player) -> init([]) -> {ok, ok}. +handle_call({join_table, Table}, From, State) -> + {reply, {error, no_such_table}, State}; + +handle_call({create_table, {force, TID}}, From, State) -> + {reply, {ok, TID}, State}; + handle_call(_Message, _From, State) -> {noreply, State}. diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl index 03b5389..ba05c95 100644 --- a/tests/ggs_coordinator_test.erl +++ b/tests/ggs_coordinator_test.erl @@ -14,3 +14,20 @@ stop_test() -> ggs_coordinator:stop("Terminate now"), % Send stop message timer:sleep(100), % Wait for cleaning.. ?assert((erlang:process_info(Coord) == undefined)). % Did it stop? + +join_bad_table_test() -> + {ok, _Coord} = ggs_coordinator:start_link(), + Response = ggs_coordinator:join_table("Nonexistant table"), + ggs_coordinator:stop(""), + timer:sleep(100), + ?assert(Response == {error, no_such_table}). + + +create_table_test() -> + {ok, _Coord} = ggs_coordinator:start_link(), + % Forcibly create a table. This functionality should be disabled + % in the production system, but is pretty nice for testing. + Response = ggs_coordinator:create_table({force, 1337}), + ggs_coordinator:stop(""), + timer:sleep(100), + ?assert(Response == {ok, 1337}). From 818205e19b505580ee66c2836e97617c12455f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 12:12:12 +0100 Subject: [PATCH 27/67] Now we store the tables when they are created --- src/ggs_coordinator.erl | 10 ++++++-- start_test | 2 +- tests/ggs_coordinator_test.erl | 47 ++++++++++++++++++++-------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 2a5d509..c6e01d6 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -8,6 +8,11 @@ code_change/3]). -define(SERVER, ?MODULE). +-record(co_state, + {players = [], % List of all player processes + player_table_map = [], % Players <-> Table map + table_state_map = []}). % Table <-> Table state map + %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. @@ -48,13 +53,14 @@ remove_player(_From, _Player) -> %% gen_server callbacks init([]) -> - {ok, ok}. + {ok, #co_state{}}. handle_call({join_table, Table}, From, State) -> {reply, {error, no_such_table}, State}; handle_call({create_table, {force, TID}}, From, State) -> - {reply, {ok, TID}, State}; + TIDs = State#co_state.player_table_map, + {reply, {ok, TID}, State#co_state{player_table_map = [TID | TIDs]}}; handle_call(_Message, _From, State) -> {noreply, State}. diff --git a/start_test b/start_test index 5920151..76050c1 100755 --- a/start_test +++ b/start_test @@ -1,3 +1,3 @@ #!/usr/bin/env bash -erl -boot start_sasl -pa ebin_test -pa erlang_js/ebin/ -pa erlv8/ebin -pa ebin -pa src -eval 'ggs_protocol_test:test_parse().' +erl -boot start_sasl -pa ebin_test -pa erlang_js/ebin/ -pa ebin -pa src -eval 'ggs_coordinator_test:test().' diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl index ba05c95..ccc9256 100644 --- a/tests/ggs_coordinator_test.erl +++ b/tests/ggs_coordinator_test.erl @@ -1,33 +1,42 @@ -module(ggs_coordinator_test). -include_lib("eunit/include/eunit.hrl"). -start_link_test() -> - {ok, Coord} = ggs_coordinator:start_link(), % Start - PInfo = erlang:process_info(Coord), % Check process info - ggs_coordinator:stop(""), % Clean up - timer:sleep(100), % Wait for cleaning.. - ?assert((PInfo /= undefined)). % Did the server start? +coordinator_test_() -> + {foreach, + fun() -> + {ok, _Coord} = ggs_coordinator:start_link(), + timer:sleep(100) + end, + fun(_X) -> + ggs_coordinator:stop("End of test"), + timer:sleep(100) + end, + [ + fun test_start_link/0, + fun test_stop/0, + fun test_join_bad_table/0, + fun test_create_table/0 + ] + }. -stop_test() -> +test_start_link() -> + % Check process info + PInfo = whereis(ggs_coordinator), + ?assert((PInfo /= undefined)). % Did the server start? + +test_stop() -> ok = ggs_coordinator:stop(""), % Extra cleaning - {ok, Coord} = ggs_coordinator:start_link(), % Start server - ggs_coordinator:stop("Terminate now"), % Send stop message - timer:sleep(100), % Wait for cleaning.. - ?assert((erlang:process_info(Coord) == undefined)). % Did it stop? + timer:sleep(100), + % Did it stop? + ?assert((whereis(ggs_coordinator)) == undefined). -join_bad_table_test() -> - {ok, _Coord} = ggs_coordinator:start_link(), +test_join_bad_table() -> Response = ggs_coordinator:join_table("Nonexistant table"), - ggs_coordinator:stop(""), - timer:sleep(100), ?assert(Response == {error, no_such_table}). -create_table_test() -> - {ok, _Coord} = ggs_coordinator:start_link(), +test_create_table() -> % Forcibly create a table. This functionality should be disabled % in the production system, but is pretty nice for testing. Response = ggs_coordinator:create_table({force, 1337}), - ggs_coordinator:stop(""), - timer:sleep(100), ?assert(Response == {ok, 1337}). From 3f417692339b7d727b0ec37295bf10e489fc4f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 12:57:41 +0100 Subject: [PATCH 28/67] Now we have join_table, create_table and join_lobby + test cases --- src/ggs_coordinator.erl | 30 +++++++++++++++++++++++------- src/helpers.erl | 4 ++++ tests/ggs_coordinator_test.erl | 15 +++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index c6e01d6..756bb2c 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,7 +1,8 @@ -module(ggs_coordinator). %% API Exports --export([start_link/0, stop/1, join_table/1, create_table/1]). +-export([start_link/0, stop/1, join_table/1, create_table/1, join_lobby/0, + respawn_player/2, respawn_table/1, remove_player/2]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, @@ -11,7 +12,8 @@ -record(co_state, {players = [], % List of all player processes player_table_map = [], % Players <-> Table map - table_state_map = []}). % Table <-> Table state map + table_state_map = [], + tables = []}). % Table <-> Table state map %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. @@ -36,7 +38,7 @@ create_table(Params) -> %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - ggs_logger:not_implemented(). + gen_server:call(ggs_coordinator, join_lobby). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> @@ -55,12 +57,26 @@ remove_player(_From, _Player) -> init([]) -> {ok, #co_state{}}. -handle_call({join_table, Table}, From, State) -> - {reply, {error, no_such_table}, State}; +handle_call(join_lobby, _From, State) -> + Token = helpers:get_new_token(), + {reply, {ok, Token}, State}; + +handle_call({join_table, Table}, _From, State) -> + Tables = State#co_state.tables, + case lists:keyfind(Table, 1, Tables) of + {Table} -> + {reply, {ok, Table}, State}; %% @TODO: Also add player to table + false -> + {reply, {error, no_such_table}, State} + end; handle_call({create_table, {force, TID}}, From, State) -> - TIDs = State#co_state.player_table_map, - {reply, {ok, TID}, State#co_state{player_table_map = [TID | TIDs]}}; + TIDMap = State#co_state.player_table_map, + Tables = State#co_state.tables, + {reply, {ok, TID}, State#co_state{ + player_table_map = [{From, TID} | TIDMap], + tables = [{TID} | TID] + }}; handle_call(_Message, _From, State) -> {noreply, State}. diff --git a/src/helpers.erl b/src/helpers.erl index 1bf7825..3a42fbf 100644 --- a/src/helpers.erl +++ b/src/helpers.erl @@ -1,4 +1,8 @@ -module(helpers). +-export([not_implemented/0, get_new_token/0]). not_implemented() -> exit("Not implemented"). + +get_new_token() -> + string:strip(os:cmd("uuidgen"), right, $\n ). diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl index ccc9256..6ec41c6 100644 --- a/tests/ggs_coordinator_test.erl +++ b/tests/ggs_coordinator_test.erl @@ -15,7 +15,7 @@ coordinator_test_() -> fun test_start_link/0, fun test_stop/0, fun test_join_bad_table/0, - fun test_create_table/0 + fun test_join_lobby/0 ] }. @@ -34,9 +34,20 @@ test_join_bad_table() -> Response = ggs_coordinator:join_table("Nonexistant table"), ?assert(Response == {error, no_such_table}). +test_join_lobby() -> + {Response, _} = ggs_coordinator:join_lobby(), + ?assert(Response /= error). -test_create_table() -> +%% 'Manual' tests + +create_table_test() -> + {ok, _Coord} = ggs_coordinator:start_link(), + timer:sleep(100), % Forcibly create a table. This functionality should be disabled % in the production system, but is pretty nice for testing. Response = ggs_coordinator:create_table({force, 1337}), ?assert(Response == {ok, 1337}). + +join_good_table_test() -> + Response = ggs_coordinator:join_table(1337), + ?assert(Response == {ok, 1337}). From e38bab50545c71f20bd7234e6c6034bc965f5511 Mon Sep 17 00:00:00 2001 From: niklas Date: Thu, 17 Feb 2011 13:52:56 +0100 Subject: [PATCH 29/67] Modified player test --- tests/ggs_player_test.erl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index 1067f71..be38135 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -4,20 +4,24 @@ %% @doc start_link should always return ok for any valid socket. A valid socket %% should always return {ok, Pid} and {error, Reason} otherwise. start_link_test() -> - ggs_logger:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and %% deliver a specified message through the socket. notify_test() -> - ggs_logger:not_implemented(). - + Player = start_link("bad arg"), + Message = {"something", ""}, + Ret = ggs_player:notify(Player, self(), Message) + ?assertNot(ok =:= Ret). + %% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid %% player token. a valid token should be unique. get_token_test() -> - ggs_logger:not_implemented(). + ggs_logger:not_implemented(). -%% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to +%% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to %% execute this function with the same Player and Table arguments twice. stop_test() -> - ggs_logger:not_implemented(). - + Player = start_link(something), + Table = test, + ok = stop(Player, Table). From 041fee24419644398c9841ebd2b6450076053891 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 14:14:32 +0100 Subject: [PATCH 30/67] removed Token and Socket --- src/ggs_table.erl | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 1e4f323..3c0237d 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -1,4 +1,4 @@ -%% @doc This module represents a Player with a Socket and a Token +%% @doc This module represents a table with players -module(ggs_table). -behaviour(gen_server). @@ -7,10 +7,10 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --record(state, { token, players, socket, game_vm } ). +-record(state, { players, game_vm } ). %% API --export([start_link/2, +-export([start_link/0, add_player/2, remove_player/2, stop/1, @@ -22,9 +22,9 @@ % API implementation % @doc returns a new table -start_link(Token, Socket) -> +start_link() -> GameVM = ggs_gamevm:start_link(), - {ok, Pid} = gen_server:start_link(?MODULE, [Token, Socket, GameVM], []), + {ok, Pid} = gen_server:start_link(?MODULE, [GameVM], []), Pid. %% @private @@ -50,11 +50,8 @@ notify(Table, Player, Message) -> %% ---------------------------------------------------------------------- %% @private -init([Token, Socket, GameVM]) -> - {ok, #state { token = Token, - socket = Socket, - game_vm = GameVM, - players = [] }}. +init([GameVM]) -> + {ok, #state { game_vm = GameVM, players = [] }}. %% @private handle_call({add_player, Player}, _From, #state { players = Players } = State) -> @@ -97,21 +94,20 @@ code_change(_OldVsn, State, _Extra) -> %% ---------------------------------------------------------------------- - % Tests start_link_test() -> - Table = start_link("123", none), + Table = start_link(), ?assertNot(Table =:= undefined). add_player_test() -> - Table = start_link("123", none), + Table = start_link(), Player = test_player, add_player(Table, Player), {ok, [Player]} = gen_server:call(Table, get_player_list). remove_player_test() -> - Table = start_link("123", none), + Table = start_link(), Player = test_player, Player2 = test_player2, add_player(Table, Player), @@ -124,12 +120,12 @@ remove_player_test() -> {ok, []} = gen_server:call(Table, get_player_list). stop_test() -> - Table = start_link("123", none), + Table = start_link(), ok = stop(Table). % @private notify_test() -> - Table = start_link("123", none), + Table = start_link(), Player = test_player, Message = {server, define, "function helloWorld(x) { }"}, ok = notify(Table, Player, Message). From 44d26278ccc34a0c9a2d2718c063bd496d43bee1 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 20:05:12 +0100 Subject: [PATCH 31/67] rewrite to gen_server and added tests --- src/ggs_gamevm.erl | 126 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 29 deletions(-) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 1a8f547..15cbb64 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -1,24 +1,34 @@ --module(ggs_gamevm). --export([start_link/0, define/2, user_command/4]). %% @doc This module is responsible for running the game VM:s. You can issue %% commands to a vm using this module. +-module(ggs_gamevm). +-behaviour(gen_server). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, { port, table } ). + +%% API +-export([start_link/1, define/2, user_command/4, stop/1, call_js/2]). + +-include_lib("eunit/include/eunit.hrl"). + + +%% ---------------------------------------------------------------------- +% API implementation + %% @doc Create a new VM process. The process ID is returned and can be used %% with for example the define method of this module. -start_link() -> +start_link(Table) -> erlang_js:start(), %% @TODO: should only be done once - PortPid = spawn_link( fun() -> - process_flag(trap_exit, true), - {ok, Port} = js_driver:new(), - js:define(Port, <<"function userCommand(user, command, args){return 'Hello world';}">>), - loop(Port) - end ), - PortPid. + {ok, Pid} = gen_server:start_link(?MODULE, [Table], []), + Pid. %% @doc Define some new code on the specified VM, returns the atom ok. define(GameVM, SourceCode) -> - GameVM ! {define,SourceCode}, - ok. + gen_server:cast(GameVM, {define, SourceCode}). %% @doc Execute a user command on the specified VM. This function is %% asynchronous, and returns ok. @@ -28,23 +38,81 @@ define(GameVM, SourceCode) -> %% Command = a game command to run %% Args = arguments for the Command parameter user_command(GameVM, Player, Command, Args) -> - Ref = make_ref(), - GameVM ! {user_command, Player, Command, Args, self(), Ref}, + gen_server:cast(GameVM, {user_command, Player, Command, Args}). + +%% @private +% only for tests +call_js(GameVM, SourceCode) -> + gen_server:call(GameVM, {eval, SourceCode}). + +% @doc stops the gamevm process +stop(GameVM) -> + gen_server:cast(GameVM, stop). + + +%% ---------------------------------------------------------------------- + +%% @private +init([Table]) -> + process_flag(trap_exit, true), + {ok, Port} = js_driver:new(), + %% @TODO: add here default JS API instead + {ok, #state { port = Port, table = Table }}. + +%% private +% only needed for the tests +handle_call({eval, SourceCode}, _From, #state { port = Port } = State) -> + {ok, Ret} = js:eval(Port, list_to_binary(SourceCode)), + {reply, Ret, State}. + +%% @private +handle_cast({define, SourceCode}, #state { port = Port } = State) -> + ok = js:define(Port, list_to_binary(SourceCode)), + {noreply, State}; +handle_cast({user_command, Player, Command, Args}, #state { port = Port } = State) -> + Arguments = string:sub(string:join([Player, Command, Args], ","), "'", "\'"), + Js = list_to_binary(string:concat(string:concat("userCommand(", Arguments), ");")), + js_driver:define_js(Port, Js), + {noreply, State}; +handle_cast(stop, State) -> + {stop, normal, State}; +handle_cast(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +handle_info(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +terminate(_Reason, _State) -> ok. -%% Helper functions +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. -loop(Port) -> - receive - {define, SourceCode} -> - ok = js:define(Port, list_to_binary(SourceCode)), - loop(Port); - {user_command, User, Command, Args, From, Ref} -> - {ok, Ret} = js:call(Port, <<"userCommand">>, - [ list_to_binary(User), - list_to_binary(Command), - list_to_binary(Args) - ]), - From ! {Ref, Ret}, - loop(Port) - end. +%% ---------------------------------------------------------------------- +% Tests + +start_link_test() -> + erlang_js:start(), %% @TODO: should only be done once + GameVM = start_link(test_table), + ?assertNot(GameVM =:= undefined). + +define_test() -> + GameVM = start_link(test_table), + define(GameVM, "function hello(test) { return test; }"), + ?assertMatch(<<"jeena">>, gen_server:call(GameVM, {eval, "hello('jeena')"})). + +stop_test() -> + GameVM = start_link(test_table), + ok = stop(GameVM). + +user_command_test() -> + GameVM = start_link(test_table), + define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), + user_command(GameVM, "'jeena'", "'thecommand'", "'theargs'"), + ?assertMatch(<<"jeenathecommandtheargs">>, gen_server:call(GameVM, {eval, "t;"})). + From dd9b92bf43b7969d896209b2aad98371c9d31b33 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 20:14:45 +0100 Subject: [PATCH 32/67] fixed escaping problem --- src/ggs_gamevm.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 15cbb64..6493c9f 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -70,7 +70,8 @@ handle_cast({define, SourceCode}, #state { port = Port } = State) -> ok = js:define(Port, list_to_binary(SourceCode)), {noreply, State}; handle_cast({user_command, Player, Command, Args}, #state { port = Port } = State) -> - Arguments = string:sub(string:join([Player, Command, Args], ","), "'", "\'"), + Arguments = string:concat("'", string:concat( + string:join([js_escape(Player), js_escape(Command), js_escape(Args)], "','"), "'")), Js = list_to_binary(string:concat(string:concat("userCommand(", Arguments), ");")), js_driver:define_js(Port, Js), {noreply, State}; @@ -93,6 +94,9 @@ terminate(_Reason, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. +js_escape(S) -> + lists:flatmap(fun($\') -> [$\\, $\']; (X) -> [X] end, S). + %% ---------------------------------------------------------------------- % Tests @@ -113,6 +117,6 @@ stop_test() -> user_command_test() -> GameVM = start_link(test_table), define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), - user_command(GameVM, "'jeena'", "'thecommand'", "'theargs'"), - ?assertMatch(<<"jeenathecommandtheargs">>, gen_server:call(GameVM, {eval, "t;"})). + user_command(GameVM, "'jeena", "thecommand", "theargs'"), + ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). From 883cf9e9d714a79645df9b67068e2b5ec13e56a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 23:17:04 +0100 Subject: [PATCH 33/67] Now we have some myltiplayer action! --- src/ggs_coordinator.erl | 21 ++++---- src/ggs_gamevm_e.erl | 41 +++++++++++++++ src/ggs_player.erl | 40 ++++++++++---- src/ggs_table.erl | 112 +++++++++++++++++++++++++--------------- 4 files changed, 151 insertions(+), 63 deletions(-) create mode 100644 src/ggs_gamevm_e.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 756bb2c..733ff8d 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -61,21 +61,24 @@ handle_call(join_lobby, _From, State) -> Token = helpers:get_new_token(), {reply, {ok, Token}, State}; -handle_call({join_table, Table}, _From, State) -> +handle_call({join_table, Table}, From, State) -> + {FromPlayer, _Ref} = From, Tables = State#co_state.tables, case lists:keyfind(Table, 1, Tables) of - {Table} -> - {reply, {ok, Table}, State}; %% @TODO: Also add player to table + {TableID, TablePID} -> + ggs_table:add_player(TablePID, FromPlayer), + {reply, {ok, TablePID}, State}; false -> {reply, {error, no_such_table}, State} end; -handle_call({create_table, {force, TID}}, From, State) -> - TIDMap = State#co_state.player_table_map, - Tables = State#co_state.tables, - {reply, {ok, TID}, State#co_state{ - player_table_map = [{From, TID} | TIDMap], - tables = [{TID} | TID] +handle_call({create_table, {force, TableID}}, From, State) -> + TableIDMap = State#co_state.player_table_map, + Tables = State#co_state.tables, + NewTableProc = ggs_table:start_link(), + {reply, {ok, TableID}, State#co_state{ + player_table_map = [{From, TableID} | TableIDMap], + tables = [{TableID, NewTableProc} | Tables] }}; handle_call(_Message, _From, State) -> diff --git a/src/ggs_gamevm_e.erl b/src/ggs_gamevm_e.erl new file mode 100644 index 0000000..76b9350 --- /dev/null +++ b/src/ggs_gamevm_e.erl @@ -0,0 +1,41 @@ +-module(ggs_gamevm_e). +-export([start_link/1, define/2, user_command/4]). +%% @doc This module is responsible for running the game VM:s. You can issue +%% commands to a vm using this module. + +%% @doc Create a new VM process. The process ID is returned and can be used +%% with for example the define method of this module. +start_link(Table) -> + PortPid = spawn( fun() -> + loop(Table) + end ), + PortPid. + +%% @doc Define some new code on the specified VM, returns the atom ok. +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}, + ok. + +%% @doc Execute a user command on the specified VM. This function is +%% asynchronous, and returns ok. +%% @spec user_command(GameVM, User, Command, Args) -> ok +%% GameVM = process IS of VM +%% Player = the player running the command +%% Command = a game command to run +%% Args = arguments for the Command parameter +user_command(GameVM, Player, Command, Args) -> + Ref = make_ref(), + GameVM ! {user_command, Player, Command, Args, self(), Ref}, + ok. + +%% Helper functions + +loop(Table) -> + receive + {define, SourceCode} -> + loop(Table); + {user_command, _User, Command, _Args, _From, _Ref} -> + io:format("GameVM received a message~n"), + ggs_table:notify_all_players(Table, Command), + loop(Table) + end. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 37c8496..af92ad9 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,5 +1,9 @@ -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: @@ -13,14 +17,28 @@ %% identifying the player. %% @spec start_link(Socket::socket()) -> {ok, Pid} | {error, Reason} start_link(Socket) -> - loop(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()), + {ok, Token} = ggs_coordinator:join_lobby(), + TableStatus = ggs_coordinator:join_table(1337), + case TableStatus of + {ok, Table} -> + loop(#pl_state{socket = Socket, token = Token, table = Table}); + {error, no_such_table} -> + ggs_coordinator:create_table({force, 1337}), + {ok, Table} = ggs_coordinator:join_table(1337), + loop(#pl_state{socket = Socket, token = Token, table = Table}) + end. %% @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) -> - ggs_logger:not_implemented(). + Player ! {notify, From, Message}. %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() @@ -36,13 +54,13 @@ stop(_Player,_Table) -> %% Internals -loop(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()), - receive {tcp, Socket, Data} -> % Just echo for now.. - gen_tcp:send(Socket,Data), - loop(Socket) +loop(#pl_state{token = Token, socket = Socket, table = Table} = State) -> + receive + {tcp, Socket, Data} -> % Just echo for now.. + io:format("Notifying table..~n"), + ggs_table:notify_game(Table, Token, Data), + loop(State); + {notify, From, Message} -> + gen_tcp:send(Socket, Message), + loop(State) end. diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 1e4f323..53c27e9 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -5,12 +5,13 @@ %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + terminate/2, code_change/3, notify_all_players/2, notify_game/3, + add_player/2]). -record(state, { token, players, socket, game_vm } ). %% API --export([start_link/2, +-export([start_link/0, add_player/2, remove_player/2, stop/1, @@ -22,9 +23,8 @@ % API implementation % @doc returns a new table -start_link(Token, Socket) -> - GameVM = ggs_gamevm:start_link(), - {ok, Pid} = gen_server:start_link(?MODULE, [Token, Socket, GameVM], []), +start_link() -> + {ok, Pid} = gen_server:start_link(?MODULE, [], []), Pid. %% @private @@ -47,22 +47,34 @@ stop(Table) -> notify(Table, Player, Message) -> gen_server:cast(Table, {notify, Player, Message}). +notify_all_players(Table, Message) -> + gen_server:cast(Table, {notify_all_players, Message}). + +notify_game(Table, From, Message) -> + io:format("Notify game called on"), + erlang:display(Table), + io:format("~n"), + gen_server:cast(Table, {notify_game, Message, From}). + %% ---------------------------------------------------------------------- %% @private -init([Token, Socket, GameVM]) -> - {ok, #state { token = Token, - socket = Socket, +init([]) -> + GameVM = ggs_gamevm_e:start_link(self()), + {ok, #state { game_vm = GameVM, players = [] }}. %% @private handle_call({add_player, Player}, _From, #state { players = Players } = State) -> {reply, ok, State#state { players = [Player | Players] }}; + handle_call({remove_player, Player}, _From, #state { players = Players } = State) -> {reply, ok, State#state { players = Players -- [Player] }}; + handle_call(get_player_list, _From, #state { players = Players } = State) -> {reply, {ok, Players}, State}; + handle_call(Msg, _From, State) -> error_logger:error_report([unknown_msg, Msg]), {reply, ok, State}. @@ -71,11 +83,25 @@ handle_call(Msg, _From, State) -> handle_cast({notify, Player, Message}, #state { game_vm = GameVM } = State) -> case Message of {server, define, Args} -> - ggs_gamevm:define(GameVM, Args); + ggs_gamevm_e:define(GameVM, Args); {game, Command, Args} -> - ggs_gamevm:user_command(GameVM, Player, Command, Args) + ggs_gamevm_e:user_command(GameVM, Player, Command, Args) end, {noreply, State}; + +handle_cast({notify_game, Message, From}, #state { game_vm = GameVM } = State) -> + io:format("notify_game message received~n"), + ggs_gamevm_e:user_command(GameVM, From, Message, ""), + {noreply, State}; + +handle_cast({notify_all_players, Message}, #state{players = Players} = State) -> + io:format("Notifying all players... ~p~n", [Players]), + lists:foreach(fun(P) -> + io:format("Notifying ~p~n", [P]), + ggs_player:notify(P, "Server", Message) + end, Players), + {noreply, State}; + handle_cast(stop, State) -> {stop, normal, State}; handle_cast(Msg, S) -> @@ -100,39 +126,39 @@ code_change(_OldVsn, State, _Extra) -> % Tests -start_link_test() -> - Table = start_link("123", none), - ?assertNot(Table =:= undefined). +%start_link_test() -> +% Table = start_link("123", none), +% ?assertNot(Table =:= undefined). +% +%add_player_test() -> +% Table = start_link("123", none), +% Player = test_player, +% add_player(Table, Player), +% {ok, [Player]} = gen_server:call(Table, get_player_list). -add_player_test() -> - Table = start_link("123", none), - Player = test_player, - add_player(Table, Player), - {ok, [Player]} = gen_server:call(Table, get_player_list). - -remove_player_test() -> - Table = start_link("123", none), - Player = test_player, - Player2 = test_player2, - add_player(Table, Player), - {ok, [Player]} = gen_server:call(Table, get_player_list), - add_player(Table, Player2), - {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), - remove_player(Table, Player), - {ok, [Player2]} = gen_server:call(Table, get_player_list), - remove_player(Table, Player2), - {ok, []} = gen_server:call(Table, get_player_list). - -stop_test() -> - Table = start_link("123", none), - ok = stop(Table). - -% @private -notify_test() -> - Table = start_link("123", none), - Player = test_player, - Message = {server, define, "function helloWorld(x) { }"}, - ok = notify(Table, Player, Message). +%remove_player_test() -> +% Table = start_link("123", none), +% Player = test_player, +% Player2 = test_player2, +% add_player(Table, Player), +% {ok, [Player]} = gen_server:call(Table, get_player_list), +% add_player(Table, Player2), +% {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), +% remove_player(Table, Player), +% {ok, [Player2]} = gen_server:call(Table, get_player_list), +% remove_player(Table, Player2), +% {ok, []} = gen_server:call(Table, get_player_list). +% +%stop_test() -> +% Table = start_link("123", none), +% ok = stop(Table). +% +%% @private +%notify_test() -> +% Table = start_link("123", none), +% Player = test_player, +% Message = {server, define, "function helloWorld(x) { }"}, +% ok = notify(Table, Player, Message). %Message2 = {game, "helloWorld", "test"}, %ok = notify(Table, Player, Message2). - \ No newline at end of file + From 67567fe2636189c49a635661d9abf8502264d3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sun, 20 Feb 2011 01:41:40 +0100 Subject: [PATCH 34/67] Added some more ggsvm_e functionality and also a chat client --- .gitignore | 2 +- games/GGSCalc/calc.glade | 317 ++++++++++++++++++++++++++++++++++++ games/GGSCalc/calc.py | 101 ++++++++++++ games/GGSChat/calc.glade | 317 ++++++++++++++++++++++++++++++++++++ games/GGSChat/chat.py | 85 ++++++++++ games/GGSChat/ggschat.glade | 92 +++++++++++ mnesia/.gamedb.erl.swp | Bin 12288 -> 0 bytes python_client | 64 ++++---- src/.ggs_connection.erl.swp | Bin 12288 -> 0 bytes src/.ggs_server.erl.swo | Bin 12288 -> 0 bytes src/ggs_coordinator.erl | 8 +- src/ggs_gamevm_e.erl | 21 ++- src/ggs_player.erl | 23 ++- src/ggs_protocol.erl | 61 +++++++ src/ggs_table.erl | 12 +- 15 files changed, 1058 insertions(+), 45 deletions(-) create mode 100644 games/GGSCalc/calc.glade create mode 100644 games/GGSCalc/calc.py create mode 100644 games/GGSChat/calc.glade create mode 100644 games/GGSChat/chat.py create mode 100644 games/GGSChat/ggschat.glade delete mode 100644 mnesia/.gamedb.erl.swp delete mode 100644 src/.ggs_connection.erl.swp delete mode 100644 src/.ggs_server.erl.swo create mode 100644 src/ggs_protocol.erl diff --git a/.gitignore b/.gitignore index d176978..d6f2bf3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -*.swp +*.sw* *.dump *.beam Mnesia.* diff --git a/games/GGSCalc/calc.glade b/games/GGSCalc/calc.glade new file mode 100644 index 0000000..720b7b4 --- /dev/null +++ b/games/GGSCalc/calc.glade @@ -0,0 +1,317 @@ + + + + + + + + True + + + True + True + • + + + False + 0 + + + + + True + 5 + 4 + + + True + True + True + + + + + / + True + True + True + + + + 1 + 2 + + + + + * + True + True + True + + + + 2 + 3 + + + + + - + True + True + True + + + + 3 + 4 + + + + + 7 + True + True + True + + + + 1 + 2 + + + + + 8 + True + True + True + + + + 1 + 2 + 1 + 2 + + + + + 9 + True + True + True + + + + 2 + 3 + 1 + 2 + + + + + + + True + True + True + + + + 3 + 4 + 1 + 2 + + + + + 4 + True + True + True + + + + 2 + 3 + + + + + 5 + True + True + True + + + + 1 + 2 + 2 + 3 + + + + + 6 + True + True + True + + + + 2 + 3 + 2 + 3 + + + + + ← + True + True + True + + + + 3 + 4 + 2 + 3 + + + + + 1 + True + True + True + + + + 3 + 4 + + + + + 2 + True + True + True + + + + 1 + 2 + 3 + 4 + + + + + 3 + True + True + True + + + + 2 + 3 + 3 + 4 + + + + + = + True + True + True + + + + 3 + 4 + 3 + 4 + + + + + 0 + True + True + True + + + + 4 + 5 + + + + + True + True + True + + + 1 + 2 + 4 + 5 + + + + + True + True + True + + + 2 + 3 + 4 + 5 + + + + + ☎ + True + True + True + + + + 3 + 4 + 4 + 5 + + + + + 1 + + + + + True + 2 + + + False + 2 + + + + + + diff --git a/games/GGSCalc/calc.py b/games/GGSCalc/calc.py new file mode 100644 index 0000000..8468ceb --- /dev/null +++ b/games/GGSCalc/calc.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +import sys, socket +try: + import pygtk + pygtk.require("2.16") +except: + pass +try: + import gtk + import gtk.glade +except: + sys.exit(1) + +class GGSCalc: + + def __init__(self): + #Set the Glade file + self.gladefile = "calc.glade" + self.wTree = gtk.glade.XML(self.gladefile, "window1") + + #Create our dictionay and connect it + dic = {"on_mainWindow_destroy" : gtk.main_quit + , "on_btn0_clicked" : lambda x: self.OnBtnClick(0) + , "on_btn1_clicked" : lambda x: self.OnBtnClick(1) + , "on_btn2_clicked" : lambda x: self.OnBtnClick(2) + , "on_btn3_clicked" : lambda x: self.OnBtnClick(3) + , "on_btn4_clicked" : lambda x: self.OnBtnClick(4) + , "on_btn5_clicked" : lambda x: self.OnBtnClick(5) + , "on_btn6_clicked" : lambda x: self.OnBtnClick(6) + , "on_btn7_clicked" : lambda x: self.OnBtnClick(7) + , "on_btn8_clicked" : lambda x: self.OnBtnClick(8) + , "on_btn9_clicked" : lambda x: self.OnBtnClick(9) + , "on_btnDiv_clicked" : lambda x: self.OnBtnClick("/") + , "on_btnMul_clicked" : lambda x: self.OnBtnClick("*") + , "on_btnMin_clicked" : lambda x: self.OnBtnClick("-") + , "on_btnPlus_clicked" : lambda x: self.OnBtnClick("+") + , "on_btnEq_clicked" : lambda x: self.calc() + , "on_btnDel_clicked" : lambda x: self.OnBtnClick("Del") + , "on_btnConnect_clicked" : lambda x: self.connect() + } + + for i in range(0,9): + dic + self.wTree.signal_autoconnect(dic) + + self.wTree.get_widget("window1").show() + self.setStatus("Not connected") + + def setStatus(self, msg): + self.wTree.get_widget("statusbar").push(0, msg) + + def calc(self): + exp = self.wTree.get_widget("txtCalc").get_text() + self.s.send("Server-Command: call\n"+ + "Token: %s\n" % self.token + + "Content-Type: text\n"+ + "Content-Length: %s\n" % len(exp)+ + "\n"+ + exp) + fs = self.s.makefile() + self.wTree.get_widget("txtCalc").set_text(fs.readline().split(" ")[1]) + + + def connect(self): + print "Connecting" + self.setStatus("Connecting") + HOST = 'localhost' # The remote host + PORT = 9000 # The same port as used by the server + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.s.connect((HOST, PORT)) + self.s.send("Server-Command: hello\n"+ + "Content-Type: text\n"+ + "Content-Length: 0\n"+ + "\n") + fs = self.s.makefile() + self.token = fs.readline().split(" ")[0] + self.setStatus("Connected!") + + def OnBtnClick(self, btn): + calcTxt = self.wTree.get_widget("txtCalc") + t = calcTxt.get_text() + if btn == "+": + t += "+" + elif btn == "-": + t += "-" + elif btn == "/": + t += "/" + elif btn == "=": + t += "=" + elif btn == "*": + t += "*" + elif btn == "Del": + t = t[:-1] + else: + t += str("\""+str(btn)+"\"") + calcTxt.set_text(t) + +if __name__ == "__main__": + calc = GGSCalc() + gtk.main() diff --git a/games/GGSChat/calc.glade b/games/GGSChat/calc.glade new file mode 100644 index 0000000..720b7b4 --- /dev/null +++ b/games/GGSChat/calc.glade @@ -0,0 +1,317 @@ + + + + + + + + True + + + True + True + • + + + False + 0 + + + + + True + 5 + 4 + + + True + True + True + + + + + / + True + True + True + + + + 1 + 2 + + + + + * + True + True + True + + + + 2 + 3 + + + + + - + True + True + True + + + + 3 + 4 + + + + + 7 + True + True + True + + + + 1 + 2 + + + + + 8 + True + True + True + + + + 1 + 2 + 1 + 2 + + + + + 9 + True + True + True + + + + 2 + 3 + 1 + 2 + + + + + + + True + True + True + + + + 3 + 4 + 1 + 2 + + + + + 4 + True + True + True + + + + 2 + 3 + + + + + 5 + True + True + True + + + + 1 + 2 + 2 + 3 + + + + + 6 + True + True + True + + + + 2 + 3 + 2 + 3 + + + + + ← + True + True + True + + + + 3 + 4 + 2 + 3 + + + + + 1 + True + True + True + + + + 3 + 4 + + + + + 2 + True + True + True + + + + 1 + 2 + 3 + 4 + + + + + 3 + True + True + True + + + + 2 + 3 + 3 + 4 + + + + + = + True + True + True + + + + 3 + 4 + 3 + 4 + + + + + 0 + True + True + True + + + + 4 + 5 + + + + + True + True + True + + + 1 + 2 + 4 + 5 + + + + + True + True + True + + + 2 + 3 + 4 + 5 + + + + + ☎ + True + True + True + + + + 3 + 4 + 4 + 5 + + + + + 1 + + + + + True + 2 + + + False + 2 + + + + + + diff --git a/games/GGSChat/chat.py b/games/GGSChat/chat.py new file mode 100644 index 0000000..c10ca8f --- /dev/null +++ b/games/GGSChat/chat.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import sys, socket, thread, gobject, getpass +try: + import pygtk + pygtk.require("2.16") +except: + pass +try: + import gtk + import gtk.glade +except: + sys.exit(1) + +class GGSChat: + + def __init__(self,host, port): + #Set the Glade file + self.gladefile = "ggschat.glade" + self.wTree = gtk.glade.XML(self.gladefile, "window1") + + self.setStatus("Not connected") + self.connect(host, port) + thread.start_new_thread(self.listenChat, ()) + #Create our dictionay and connect it + dic = {"on_window1_destroy_event" : gtk.main_quit + , "on_sendButton_clicked" : lambda x: self.chat() + , "on_entry_activate" : lambda x : self.chat() + , "on_chatBox_focus" : lambda x, y: self.wTree.get_widget("entry").grab_focus() + } + + for i in range(0,9): + dic + self.wTree.signal_autoconnect(dic) + + self.wTree.get_widget("nickBox").set_text(getpass.getuser()) + self.wTree.get_widget("window1").show() + self.wTree.get_widget("entry").grab_focus() + + def setStatus(self, msg): + self.wTree.get_widget("statusbar").push(0, msg) + + def chat(self): + exp = self.wTree.get_widget("entry").get_text() + nick = self.wTree.get_widget("nickBox").get_text() + exp = "<%s> %s" % (nick, exp) + self.s.send("Game-Command: chat\n"+ + "Token: %s\n" % self.token + + "Content-Type: text\n"+ + "Content-Length: %s\n" % (len(exp))+ + "\n"+ + exp+"\n") + self.wTree.get_widget("entry").set_text("") + #self.listenChat() + + + def connect(self, host,port): + print "Connecting" + self.setStatus("Connecting") + HOST = host # The remote host + PORT = port # The same port as used by the server + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.s.connect((HOST, PORT)) + self.token = self.s.recv(1024) + self.setStatus("Connected!") + + def listenChat(self): + print "listening" + fs = self.s.makefile() + while True: + line = fs.readline() + print "Received: ", line + gobject.idle_add(self.updateChatText, line) + + def updateChatText(self, text): + self.wTree.get_widget("chatBox").get_buffer().insert_at_cursor(text) +if __name__ == "__main__": + host = "localhost" + port = 9000 + if len(sys.argv) >= 2: + host = sys.argv[1] + port = int(sys.argv[2]) + chat = GGSChat(host, port) + gobject.threads_init() + gtk.main() diff --git a/games/GGSChat/ggschat.glade b/games/GGSChat/ggschat.glade new file mode 100644 index 0000000..ac4e9cb --- /dev/null +++ b/games/GGSChat/ggschat.glade @@ -0,0 +1,92 @@ + + + + + + 500 + 500 + + + + True + + + True + + + True + True + False + + + + 0 + + + + + 0 + + + + + True + + + True + True + • + 10 + Anonymous + + + False + 0 + + + + + True + True + • + + + + 1 + + + + + Chat! + True + True + True + + + + False + False + 2 + + + + + False + False + 1 + + + + + True + 2 + + + False + 2 + + + + + + diff --git a/mnesia/.gamedb.erl.swp b/mnesia/.gamedb.erl.swp deleted file mode 100644 index 469b1f85b2ecf7663f6f99f957c41243aa53c9d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2zfTlF6vqcEQBk9XjV9wE^c~uUwxG9A3wj3SpnmAjS;oFXpP_fq7W5WsLG#cJs2}=` z*tenA&^%Ow94N`@1lEK?CIUo&2oM1xKm>@u|3rXec*zmXaifJFiH1>upT8UXg)*~~ z>5#r#WV<)}R~3ve1=%yL;PBeT2;Jn`8LfGIzc+H@1JWO|Mq+22omqCbw2|9xebwV&MdL9H&}jaz%JyTka;4q><#@S!BC3>)Gzy4_c#PjEwfs92d$g zeDw@9$s((11KAk4Xhgj&_xgNpO&Ft9Jx0hyu4N<8?xOOSg8Y(_Z5Pkd9xtpfAbI60 zlk|Vj0invbZ5$|a&pud5`Hgn$%6u+6_TAF$9KtKfl`zmIKWF2tIK{3yRjS4AN?}1q zeKFlpwTffYEh!vShrbk{ec%Od40`En@qpXv@LICLF(fp^C$W{KAKaj^+l+SvsEbH) z>}FiYzERkptP}oRXk`n+an@anrYxtnjUZgrs@XD}k2uvTuc1mxM0`dXBXtxd^zbqf jn-*N!@$V9T6Fa9h3+=0-$)+b%yW9vo`z7sdlVX1X$Qr-k diff --git a/python_client b/python_client index e265120..10feefd 100755 --- a/python_client +++ b/python_client @@ -7,50 +7,56 @@ PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) -# Say hello +# Define ourselves a function! +token = s.recv(1024) -print "Saying hello to server" +#print "Defining a function called myFun" +#s.send( +#"Token: %s\n\ +#Server-Command: define\n\ +#Content-Type: text\n\ +#Content-Length: 49\n\ +#\n\ +#function myFun() {return 'Hello World!' ;}" % token) +#fs = s.makefile() +#data = fs.readline() +#print "Token:", token +#print "Data: ", ' '.join(data.split(" ")[1:]) + +# Call that function! +fs = s.makefile() +print "Token: ", token s.send( -"Server-Command: hello\n\ +"Token: %s\n\ +Game-Command: greet\n\ Content-Type: text\n\ Content-Length: 0\n\ \n\ -") -fs = s.makefile() -data = fs.readline() -token = data.split(" ")[0] -print "Token:", token -print "Data: ", ' '.join(data.split(" ")[1:]) +" % token) +time.sleep(1) -# Define ourselves a function! - -print "Defining a function called myFun" s.send( "Token: %s\n\ -Server-Command: define\n\ +Game-Command: uname\n\ Content-Type: text\n\ -Content-Length: 49\n\ +Content-Length: 0\n\ \n\ -function myFun() {return 'Hello World!' ;}" % token) -fs = s.makefile() -data = fs.readline() -print "Token:", token -print "Data: ", ' '.join(data.split(" ")[1:]) +" % token) +time.sleep(1) -# Call that function! - -print "Calling myFun" s.send( "Token: %s\n\ -Server-Command: call\n\ +Game-Command: chat\n\ Content-Type: text\n\ -Content-Length: 6\n\ +Content-Length: 23\n\ \n\ -myFun" % token) -fs = s.makefile() -data = fs.readline() -print "Token:", token -print "Data: ", ' '.join(data.split(" ")[1:]) +Hello guys, what's up?\n" % token) +time.sleep(1) + + +while True: + data = fs.readline() + print "Data: ", data s.close() diff --git a/src/.ggs_connection.erl.swp b/src/.ggs_connection.erl.swp deleted file mode 100644 index 0c009f8287377d2e3763a3fb7610231c3237d3fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2O>Z1E7{^^+M0qKoqMo?8TdkN?XJ3-EAceGwl!%h3+pLndm(^7W&e$W5 zH=){YkdU|{!I^9M0Eiwz;sQv$@CmqagL`?A;O}|aYywf~wg)QN%3m`c+m9drp2wC} z@pkLxTARMpSRg2`6LRL$wf0X-7s$022}!jSJV-*tG&jx1l^q@@QXbcO@O^*UU^7v2 zpjaG-V$kF&Vt8D+veitL-y955&zC}QUx!jO(0X9RzF7j6z#|igm=49FN1 zorLbcO2}R4b0~m(Xd7xnSD`;o5%LH0JMre&y z^<_eSfqsPUL0>^0^cM8jON4v_-GN5XD)c7wJoFs&EOa0D7QTi)hWbziItx9(`pg>d znswS@30MM_fF)oFSOWih0yHZFE521sA2M4uN3~j?rI2cs zUSH|Z6&6J)MQs)%b%ft6aU`VTNp#y_!hO$iBmXLIxzsbX$Mn(!1M_{JXy>Z=UUSI~ z6G6niQ1qpv!-Ta5CfkPGeY#$L=44BCi-HeSx3 zr`>COFEh~_kKfH)4CP{9s+eh~f^HN87EKbA{Y)i~N^ZoRwDjOQ7G4@JT+2OZ9P%LV zS6YNWf%Mk54E9MPZnC{qrddI+=F;l*jn$1qXhz6hv=^CM3>cRqkZZ;nT1^;k#d6J6 zN_}Z=$I`x%amGI7YL}}bUbsvPbBJ2ZqJy9nvG7@{oxI0U;6;>2CbC)Ezpc1*3u!R1 zh}90b#>L#BKzzOT;MJ7#Gp8St`28$_R64T_V#sAHDiSD>N+V7kJY0G>2VL4KlG_Y= zSQ#lkOgRez)c+ z8=X?jj*O5x|G;o^y2h_24#=rcH|M9Ssh+BuZEmXO1Z^%9&kH@AsiYpuU>I@7+}}3) zo@?_JF3xl^nQ?R(v*a&<^vhu7dx++>|;O?y@+$5Y|N|GrN0mvvzuVYG#`0>1wNM zU}2o~fQcOR;J={Zju(~aNfTmXVvHeC4|?;UCW?f_tKaJG`2{LumV+eK$%mfmu6p(A z`(C~74PDNz9zQ{!OHUIVdkNWgb@s%Su?yshR|q-9eaY1I+Z?a5K=Rx4QMWfEgPD02 zHY5)+d0t_eW5-IFP&k=dEwn-=PBW2a!n*@wx{FpoD{$uuv}85){2p>}dMc|19T?wF zAA5A=&d2MXS^=$qRzNGD70?Q31+)TM0jsbJEl&t$KgIFiH1lr&ncn##iOW<*E;{ighfD7PlPykPXePA!RzLSt&!7t!* z@FBPaHb5CX4JN_E;5WqJYw!V3@i-4w!9MWU{r6yUX_vJE|1$+>|2QIQVVbCRn>S3V znjJc$+W&F~A0}CWEkc%y{UHeSjyX;*YhnhOjEOjOiZLk zIWUeM$9H7Hw>?^I`HpnCAC7E|C>0~2OVXCClO_&6BeR^k?bn!Lo%AZJp>NXYrb(@Z z4Jqu&$bU7EH_}8!&Gj+Xu!_tMIeJ@B_kOpw&jky-vxyx{q6SB^S}JHNO}de^9S5Jk z8B6Lq6oelYk6Er?<%V>djJFV-1EKP@?S<%rp;2FDqN#N-WKt88IFWW zvx6b-g{K>0&kZH>lbyEKwvoc8nMtK+v5wj`uJ1}?O<7)#71_d8QFF%MK~e|%uxvYx zEpC>+#atAJ!=;7d>O#?^Dj+B?>SRQIZ^7+3)HAiy=fZ$FYP0mLV$Vf4Dm=Q5oaaGE zWu4LFbI+}nf}zzRCwi;vB?p$+`+e8eN#pG|LtT`%8WYB(TI88J6KqI^;hEzS5)JJP ziE@-lr_N$o{8qEf1m#tlY}=4F?FyrkLp3){WZRl*s7FHLq2o7$TZNOw z8fW>~8cVDr#Kxq)_{l4ix#!G>TdGsi+zQkJQXT6~PqSP)-?Zs?=qs z%G{3VS9SKdq8p-ON;%doJ}8 z5{{{vRV+xV% ggs_logger:not_implemented(). %% @doc Removes a player from coordinator. -remove_player(_From, _Player) -> +remove_player(_From, Player) -> + %gen_server:cast(ggs_coordinator, {remove_player, Player}). ggs_logger:not_implemented(). %% gen_server callbacks @@ -87,6 +88,11 @@ handle_call(_Message, _From, State) -> handle_cast({stop, Reason}, State) -> {stop, normal, state}; +%% @TODO: Implement me +%handle_cast({remove_player, Player}) -> +% {noreply, State#co_state{ + + handle_cast(_Message, State) -> {noreply, State}. diff --git a/src/ggs_gamevm_e.erl b/src/ggs_gamevm_e.erl index 76b9350..4575ef1 100644 --- a/src/ggs_gamevm_e.erl +++ b/src/ggs_gamevm_e.erl @@ -33,9 +33,24 @@ user_command(GameVM, Player, Command, Args) -> loop(Table) -> receive {define, SourceCode} -> + io:format("GameVM_e can't define functions, sorry!~n"), loop(Table); - {user_command, _User, Command, _Args, _From, _Ref} -> - io:format("GameVM received a message~n"), - ggs_table:notify_all_players(Table, Command), + {user_command, Player, Command, Args, From, _Ref} -> + erlang:display(Player), + do_stuff(Command, Args, Player, Table), loop(Table) end. + +do_stuff(Command, Args, Player, Table) -> + case Command of + "greet" -> + ggs_player:notify(Player, server, "Hello there!\n"); + "chat" -> + ggs_table:notify_all_players(Table, Args ++ "\n"); + "uname" -> + Uname = os:cmd("uname -a"), + ggs_player:notify(Player, server, Uname); + + Other -> + ggs_player:notify(Player, server, "I don't know that command..\n") + end. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index af92ad9..bd3b198 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -26,10 +26,12 @@ start_link(Socket) -> TableStatus = ggs_coordinator:join_table(1337), case TableStatus of {ok, Table} -> + notify(self(), self(), Token), loop(#pl_state{socket = Socket, token = Token, table = Table}); {error, no_such_table} -> ggs_coordinator:create_table({force, 1337}), {ok, Table} = ggs_coordinator:join_table(1337), + notify(self(), self(), Token), loop(#pl_state{socket = Socket, token = Token, table = Table}) end. @@ -57,10 +59,25 @@ stop(_Player,_Table) -> loop(#pl_state{token = Token, socket = Socket, table = Table} = State) -> receive {tcp, Socket, Data} -> % Just echo for now.. - io:format("Notifying table..~n"), - ggs_table:notify_game(Table, Token, Data), + io:format("Parsing via protocol module..~n"), + Parsed = ggs_protocol:parse(Data), + self() ! Parsed, loop(State); {notify, From, Message} -> gen_tcp:send(Socket, Message), - loop(State) + 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. diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl new file mode 100644 index 0000000..3dc88f9 --- /dev/null +++ b/src/ggs_protocol.erl @@ -0,0 +1,61 @@ +-module(ggs_protocol). +-export([parse/1, getToken/1]). + +%% API Functions +parse(Data) -> + Parsed = do_parse(Data, []), + prettify(Parsed). + +getToken(Parsed) -> + case lists:keyfind(token, 1, Parsed) of + {_, Value} -> + Value; + false -> + false + end. + +%% Internal helpers +do_parse(Data, ParsedMessage) -> + NewLinePos = string:chr(Data, $\n), + Line = string:substr(Data, 1, NewLinePos-1), + Tokens = re:split(Line, ": ", [{return, list}]), + case handle(Tokens) of + {Command, more} -> + do_parse(string:substr(Data, NewLinePos+1), ParsedMessage ++ [Command]); + {separator, data_next} -> + {_, Value} = lists:keyfind(content_len, 1, ParsedMessage), + {ContentLength, []} = string:to_integer(Value), + {data, ArgumentData} = handle_data(string:substr(Data, NewLinePos+1), ContentLength), + {ParsedMessage, ArgumentData} + end. + +handle([[]]) -> + {separator, data_next}; +handle(["Server-Command", Param]) -> + {{srv_cmd, Param}, more}; +handle(["Game-Command", Param]) -> + {{game_cmd, Param}, more}; +handle(["Content-Length", Param]) -> + {{content_len, Param}, more}; +handle(["Token", Param]) -> + {{token, Param}, more}; +handle(["Content-Type", Param]) -> + {{content_type, Param}, more}. + +handle_data(Data, Length) -> + {data, string:substr(Data,1,Length)}. + + +prettify({Args, Data}) -> + case lists:keyfind(srv_cmd, 1, Args) of + {_, Value} -> + {srv_cmd, Value, Args, Data}; + _Other -> + case lists:keyfind(game_cmd, 1, Args) of + {_, Value} -> + {game_cmd, Value, Args, Data}; + _ -> + ok + end + end. + diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 53c27e9..118ae0d 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -51,7 +51,6 @@ notify_all_players(Table, Message) -> gen_server:cast(Table, {notify_all_players, Message}). notify_game(Table, From, Message) -> - io:format("Notify game called on"), erlang:display(Table), io:format("~n"), gen_server:cast(Table, {notify_game, Message, From}). @@ -82,22 +81,19 @@ handle_call(Msg, _From, State) -> %% @private handle_cast({notify, Player, Message}, #state { game_vm = GameVM } = State) -> case Message of - {server, define, Args} -> - ggs_gamevm_e:define(GameVM, Args); - {game, Command, Args} -> - ggs_gamevm_e:user_command(GameVM, Player, Command, Args) + {server, define, Args} -> + ggs_gamevm_e:define(GameVM, Args); + {game, Command, Args} -> + ggs_gamevm_e:user_command(GameVM, Player, Command, Args) end, {noreply, State}; handle_cast({notify_game, Message, From}, #state { game_vm = GameVM } = State) -> - io:format("notify_game message received~n"), ggs_gamevm_e:user_command(GameVM, From, Message, ""), {noreply, State}; handle_cast({notify_all_players, Message}, #state{players = Players} = State) -> - io:format("Notifying all players... ~p~n", [Players]), lists:foreach(fun(P) -> - io:format("Notifying ~p~n", [P]), ggs_player:notify(P, "Server", Message) end, Players), {noreply, State}; From 507081c234f70d0c734059e2dea7c3d1a31c52e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sun, 20 Feb 2011 01:58:48 +0100 Subject: [PATCH 35/67] Now we have a /lusers command in chat ;) --- games/GGSChat/chat.py | 13 +++++++++---- src/ggs_gamevm_e.erl | 4 +++- src/ggs_table.erl | 6 +++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/games/GGSChat/chat.py b/games/GGSChat/chat.py index c10ca8f..9c94728 100644 --- a/games/GGSChat/chat.py +++ b/games/GGSChat/chat.py @@ -29,8 +29,6 @@ class GGSChat: , "on_chatBox_focus" : lambda x, y: self.wTree.get_widget("entry").grab_focus() } - for i in range(0,9): - dic self.wTree.signal_autoconnect(dic) self.wTree.get_widget("nickBox").set_text(getpass.getuser()) @@ -43,8 +41,15 @@ class GGSChat: def chat(self): exp = self.wTree.get_widget("entry").get_text() nick = self.wTree.get_widget("nickBox").get_text() - exp = "<%s> %s" % (nick, exp) - self.s.send("Game-Command: chat\n"+ + if exp[0] == "/": + self.s.send("Game-Command: %s\n" % exp[1:] + + "Token: %s\n" % self.token + + "Content-Type: text\n" + + "Content-Length: 0\n"+ + "\n") + else: + exp = "<%s> %s" % (nick, exp) + self.s.send("Game-Command: chat\n"+ "Token: %s\n" % self.token + "Content-Type: text\n"+ "Content-Length: %s\n" % (len(exp))+ diff --git a/src/ggs_gamevm_e.erl b/src/ggs_gamevm_e.erl index 4575ef1..ad2527b 100644 --- a/src/ggs_gamevm_e.erl +++ b/src/ggs_gamevm_e.erl @@ -50,7 +50,9 @@ do_stuff(Command, Args, Player, Table) -> "uname" -> Uname = os:cmd("uname -a"), ggs_player:notify(Player, server, Uname); - + "lusers" -> + {ok, Players} = ggs_table:get_player_list(Table), + ggs_player:notify(Player, server,io_lib:format("~p\n",[Players])); Other -> ggs_player:notify(Player, server, "I don't know that command..\n") end. diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 118ae0d..93b79fd 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -6,7 +6,7 @@ %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, notify_all_players/2, notify_game/3, - add_player/2]). + add_player/2, get_player_list/1]). -record(state, { token, players, socket, game_vm } ). @@ -39,6 +39,10 @@ add_player(Table, Player) -> remove_player(Table, Player) -> call(Table, {remove_player, Player}). +%% @doc Get a list of all player processes attached to this table +get_player_list(Table) -> + gen_server:call(Table, get_player_list). + % @doc stops the table process stop(Table) -> gen_server:cast(Table, stop). From 7412087d4a93663a6194197e6d5ec21bf1b9642a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Mon, 21 Feb 2011 15:11:28 +0100 Subject: [PATCH 36/67] worked more on chat --- games/GGSChat/chat.py | 8 ++++++-- src/ggs_coordinator.erl | 8 ++++---- src/ggs_dispatcher.erl | 2 +- src/ggs_gamevm.erl | 5 +++-- src/ggs_gamevm_e.erl | 10 ++++++---- src/ggs_player.erl | 8 ++++---- src/ggs_table.erl | 2 +- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/games/GGSChat/chat.py b/games/GGSChat/chat.py index 9c94728..17c30ea 100644 --- a/games/GGSChat/chat.py +++ b/games/GGSChat/chat.py @@ -42,11 +42,15 @@ class GGSChat: exp = self.wTree.get_widget("entry").get_text() nick = self.wTree.get_widget("nickBox").get_text() if exp[0] == "/": + cmdStr = exp[1:].split(" ") + cmd = cmdStr[0] + params = ' '.join(cmdStr[1:]) self.s.send("Game-Command: %s\n" % exp[1:] + "Token: %s\n" % self.token + "Content-Type: text\n" + - "Content-Length: 0\n"+ - "\n") + "Content-Length: %s\n" % len(params)+ + "\n"+ + params) else: exp = "<%s> %s" % (nick, exp) self.s.send("Game-Command: chat\n"+ diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index a7f0ab8..f1e7caa 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -49,7 +49,7 @@ respawn_table(_Token) -> ggs_logger:not_implemented(). %% @doc Removes a player from coordinator. -remove_player(_From, Player) -> +remove_player(_From, _Player) -> %gen_server:cast(ggs_coordinator, {remove_player, Player}). ggs_logger:not_implemented(). @@ -66,7 +66,7 @@ handle_call({join_table, Table}, From, State) -> {FromPlayer, _Ref} = From, Tables = State#co_state.tables, case lists:keyfind(Table, 1, Tables) of - {TableID, TablePID} -> + {_TableID, TablePID} -> ggs_table:add_player(TablePID, FromPlayer), {reply, {ok, TablePID}, State}; false -> @@ -85,8 +85,8 @@ handle_call({create_table, {force, TableID}}, From, State) -> handle_call(_Message, _From, State) -> {noreply, State}. -handle_cast({stop, Reason}, State) -> - {stop, normal, state}; +handle_cast({stop, _Reason}, State) -> + {stop, normal, State}; %% @TODO: Implement me %handle_cast({remove_player, Player}) -> diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 49dcf4b..11dd729 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -45,7 +45,7 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. -handle_info({tcp, _Socket, RawData}, State) -> +handle_info({tcp, _Socket, _RawData}, State) -> io:format("Got connect request!~n"), {noreply, State}; diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 1a8f547..a16e6a6 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -6,7 +6,6 @@ %% @doc Create a new VM process. The process ID is returned and can be used %% with for example the define method of this module. start_link() -> - erlang_js:start(), %% @TODO: should only be done once PortPid = spawn_link( fun() -> process_flag(trap_exit, true), {ok, Port} = js_driver:new(), @@ -46,5 +45,7 @@ loop(Port) -> list_to_binary(Args) ]), From ! {Ref, Ret}, - loop(Port) + loop(Port); + {eval, JS} -> + end. diff --git a/src/ggs_gamevm_e.erl b/src/ggs_gamevm_e.erl index ad2527b..3cc6b17 100644 --- a/src/ggs_gamevm_e.erl +++ b/src/ggs_gamevm_e.erl @@ -32,11 +32,11 @@ user_command(GameVM, Player, Command, Args) -> loop(Table) -> receive - {define, SourceCode} -> + {define, _SourceCode} -> io:format("GameVM_e can't define functions, sorry!~n"), loop(Table); - {user_command, Player, Command, Args, From, _Ref} -> - erlang:display(Player), + {user_command, Player, Command, Args, _From, _Ref} -> + erlang:display(Command), do_stuff(Command, Args, Player, Table), loop(Table) end. @@ -53,6 +53,8 @@ do_stuff(Command, Args, Player, Table) -> "lusers" -> {ok, Players} = ggs_table:get_player_list(Table), ggs_player:notify(Player, server,io_lib:format("~p\n",[Players])); - Other -> + "nick" -> + io:format("Changing nickname of ~p to ~p.", [Player, Args]); + _Other -> ggs_player:notify(Player, server, "I don't know that command..\n") end. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index bd3b198..0211f3f 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -56,21 +56,21 @@ stop(_Player,_Table) -> %% Internals -loop(#pl_state{token = Token, socket = Socket, table = Table} = State) -> +loop(#pl_state{token = _Token, socket = Socket, table = Table} = State) -> receive {tcp, Socket, Data} -> % Just echo for now.. io:format("Parsing via protocol module..~n"), Parsed = ggs_protocol:parse(Data), self() ! Parsed, loop(State); - {notify, From, Message} -> + {notify, _From, Message} -> gen_tcp:send(Socket, Message), loop(State); % Below are messages generated by the parser - {game_cmd,Cmd, Headers, Data} -> + {game_cmd,Cmd, _Headers, Data} -> ggs_table:notify(Table, self(), {game, Cmd, Data}), loop(State); - {srv_cmd,"define", Headers, Data} -> + {srv_cmd,"define", _Headers, Data} -> ggs_table:notify(Table, self(), {server, define, Data}), loop(State); {tcp_closed, _Socket} -> diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 93b79fd..cf77f30 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -6,7 +6,7 @@ %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, notify_all_players/2, notify_game/3, - add_player/2, get_player_list/1]). + get_player_list/1]). -record(state, { token, players, socket, game_vm } ). From b3d8c5ba991192f1cd50fe57abb93466bc8d18bc Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Mon, 21 Feb 2011 15:43:39 +0100 Subject: [PATCH 37/67] added more test --- src/ggs_gamevm.erl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 6493c9f..acfe2fb 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -120,3 +120,9 @@ user_command_test() -> user_command(GameVM, "'jeena", "thecommand", "theargs'"), ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). +user_command2_test() -> + GameVM = start_link(test_table), + define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), + user_command(GameVM, "jeena", "test", ""), + io:format("test ~p~n", [binary_to_list(gen_server:call(GameVM, {eval, "t;"}))]), + ?assertMatch(<<"rt">>, gen_server:call(GameVM, {eval, "t;"})). From ee4059ac5a1d308f1020ff8385de9579b93a4a2a Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 21 Feb 2011 20:43:00 +0100 Subject: [PATCH 38/67] getItem, setItem complete. Added scripts. --- mnesia/build_db | 4 ++++ mnesia/build_test_db | 4 ++++ mnesia/ggs_db.erl | 47 ++++++++++++++++++++++++++++++++++++++++++ mnesia/ggs_db.hrl | 6 ++++++ mnesia/ggs_db_test.erl | 31 ++++++++++++++++++++++++++++ mnesia/test_db | 3 +++ 6 files changed, 95 insertions(+) create mode 100755 mnesia/build_db create mode 100755 mnesia/build_test_db create mode 100644 mnesia/ggs_db.erl create mode 100644 mnesia/ggs_db.hrl create mode 100644 mnesia/ggs_db_test.erl create mode 100755 mnesia/test_db diff --git a/mnesia/build_db b/mnesia/build_db new file mode 100755 index 0000000..0aa2042 --- /dev/null +++ b/mnesia/build_db @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + + erlc -o . ggs_db.erl + erlc -o . ggs_db_test.erl diff --git a/mnesia/build_test_db b/mnesia/build_test_db new file mode 100755 index 0000000..f5aa938 --- /dev/null +++ b/mnesia/build_test_db @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +./build_db +./test_db diff --git a/mnesia/ggs_db.erl b/mnesia/ggs_db.erl new file mode 100644 index 0000000..5067e16 --- /dev/null +++ b/mnesia/ggs_db.erl @@ -0,0 +1,47 @@ +%%%%---------------------------------------------------- +%%% @author Mattias Pettersson +%%% @copyright 2011 Mattias Pettersson +%%% @doc Database for runtime game variable storage. +%%% @end + +-module(ggs_db). +-import(mnesia). +-export([init/0,setItem/4,getItem/3]). +-include("ggs_db.hrl"). + +%%----------------------------------------------------- +%% Creation +%%----------------------------------------------------- +init() -> + mnesia:create_table(data, [{attributes, record_info(fields, data)}]). + +%%----------------------------------------------------- +%% Test +%%----------------------------------------------------- + +%test_data() -> +% set(0, "Hello"), +% get(0). + +%%----------------------------------------------------- +%% Insertions +%%----------------------------------------------------- +setItem(Db,Ns,Key,Value) -> + Fun = fun() -> + Data = #data{key = {Db,Ns,Key}, value = Value}, + mnesia:write(Data) + end, + mnesia:transaction(Fun). + + + +%%----------------------------------------------------- +%% Querries +%%----------------------------------------------------- +getItem(Db,Ns,Key) -> + Fun = fun() -> + [Data] = mnesia:read(data, {Db,Ns,Key}), + Data#data.value + end, + mnesia:transaction(Fun). + diff --git a/mnesia/ggs_db.hrl b/mnesia/ggs_db.hrl new file mode 100644 index 0000000..bc13c3a --- /dev/null +++ b/mnesia/ggs_db.hrl @@ -0,0 +1,6 @@ +%% gamedb.hrl + +-record(player, {id, name}). +-record(data, {key, value}). + + diff --git a/mnesia/ggs_db_test.erl b/mnesia/ggs_db_test.erl new file mode 100644 index 0000000..4baaaed --- /dev/null +++ b/mnesia/ggs_db_test.erl @@ -0,0 +1,31 @@ +-module(ggs_db_test). +%-compile({no_auto_import,[get/1,set/2]}). +-include_lib("eunit/include/eunit.hrl"). + +%ggs_db_test_() -> +% {spawn, +% {setup, fun setup/0, fun cleanup/1,[ fun ggs_db_test/0 ]} +% }. + + +%Key should be a tuple of two elements +setup_test() -> + mnesia:start(), + ggs_db:init(), + ggs_db:setItem("dbname","nsname","keyname","Hello"), + ?assertMatch({atomic,"Hello"},ggs_db:getItem("dbname","nsname","keyname")), + mnesia:stop(). + +%cleanup(Val) -> +% mnesia:stop(). + + + +%tests() -> +% ggs_db_test(). + +%ggs_db_test() -> +% ggs_db:set(0, "Hello"), + %io:format("~s",[Val]), +% ?assertMatch({atomic,"Hello"},ggs_db:get(0)). + diff --git a/mnesia/test_db b/mnesia/test_db new file mode 100755 index 0000000..958b005 --- /dev/null +++ b/mnesia/test_db @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +erl -eval 'eunit:test(ggs_db_test), q().' From 08e0be70e2c15446ebac33aba64d66b95093cfe2 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Mon, 21 Feb 2011 20:54:43 +0100 Subject: [PATCH 39/67] fixed test with js callback --- erlang_js | 2 +- src/ggs_gamevm.erl | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/erlang_js b/erlang_js index 5350ed2..2f2785f 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 +Subproject commit 2f2785fafb0da6db75810eb6fa97d09c58257588 diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index acfe2fb..294eb10 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -119,10 +119,15 @@ user_command_test() -> define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), user_command(GameVM, "'jeena", "thecommand", "theargs'"), ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). + +to_string({A, B, C}) -> + "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}". user_command2_test() -> GameVM = start_link(test_table), define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), - user_command(GameVM, "jeena", "test", ""), - io:format("test ~p~n", [binary_to_list(gen_server:call(GameVM, {eval, "t;"}))]), - ?assertMatch(<<"rt">>, gen_server:call(GameVM, {eval, "t;"})). + user_command(GameVM, "", "", ""), + T = to_string(erlang:time()), + io:format("test ~p~n", [T]), + ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). + From e55e0bd8a3003cfc1ae5f8740fd7249b4b021dba Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 21 Feb 2011 22:31:25 +0100 Subject: [PATCH 40/67] length(Db,Ns) and tests for get,set and length. --- mnesia/ggs_db.erl | 10 +++++++++- mnesia/ggs_db_test.erl | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mnesia/ggs_db.erl b/mnesia/ggs_db.erl index 5067e16..0b59822 100644 --- a/mnesia/ggs_db.erl +++ b/mnesia/ggs_db.erl @@ -6,7 +6,8 @@ -module(ggs_db). -import(mnesia). --export([init/0,setItem/4,getItem/3]). +%-compile({no_auto_import,[length/2]}). +-export([init/0,setItem/4,getItem/3,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- @@ -45,3 +46,10 @@ getItem(Db,Ns,Key) -> end, mnesia:transaction(Fun). +length(Db,Ns) -> + Fun = fun() -> + Keys = mnesia:all_keys(data), + length(lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys)) + end, + {atomic, Ret} = mnesia:transaction(Fun), + Ret. diff --git a/mnesia/ggs_db_test.erl b/mnesia/ggs_db_test.erl index 4baaaed..0e65593 100644 --- a/mnesia/ggs_db_test.erl +++ b/mnesia/ggs_db_test.erl @@ -9,11 +9,18 @@ %Key should be a tuple of two elements -setup_test() -> +get_set_test() -> mnesia:start(), ggs_db:init(), ggs_db:setItem("dbname","nsname","keyname","Hello"), - ?assertMatch({atomic,"Hello"},ggs_db:getItem("dbname","nsname","keyname")), + ?assertMatch({atomic,"Hello"},ggs_db:getItem("dbname","nsname","keyname")). + +length_test() -> + ggs_db:setItem(1,1,2,"112"), + ggs_db:setItem(1,2,2,"122"), + ggs_db:setItem(1,1,3,"113"), + ggs_db:setItem(1,1,4,"114"), + ?assertEqual(ggs_db:length(1,1), 3), mnesia:stop(). %cleanup(Val) -> From c66d1cef69fb032287f28ceea23a95de55f306f9 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 21 Feb 2011 22:59:11 +0100 Subject: [PATCH 41/67] removeItem with test. --- mnesia/ggs_db.erl | 13 ++++++++++++- mnesia/ggs_db_test.erl | 8 ++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mnesia/ggs_db.erl b/mnesia/ggs_db.erl index 0b59822..1c15536 100644 --- a/mnesia/ggs_db.erl +++ b/mnesia/ggs_db.erl @@ -7,7 +7,7 @@ -module(ggs_db). -import(mnesia). %-compile({no_auto_import,[length/2]}). --export([init/0,setItem/4,getItem/3,length/2]). +-export([init/0,setItem/4,getItem/3,removeItem/3,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- @@ -35,6 +35,15 @@ setItem(Db,Ns,Key,Value) -> mnesia:transaction(Fun). +%%----------------------------------------------------- +%% Deletions +%%----------------------------------------------------- +removeItem(Db,Ns,Key) -> + Fun = fun() -> + mnesia:delete({data,{Db,Ns,Key}}) + end, + mnesia:transaction(Fun). + %%----------------------------------------------------- %% Querries @@ -53,3 +62,5 @@ length(Db,Ns) -> end, {atomic, Ret} = mnesia:transaction(Fun), Ret. + + diff --git a/mnesia/ggs_db_test.erl b/mnesia/ggs_db_test.erl index 0e65593..e15ddf4 100644 --- a/mnesia/ggs_db_test.erl +++ b/mnesia/ggs_db_test.erl @@ -9,7 +9,7 @@ %Key should be a tuple of two elements -get_set_test() -> +getItem_setItem_test() -> mnesia:start(), ggs_db:init(), ggs_db:setItem("dbname","nsname","keyname","Hello"), @@ -20,7 +20,11 @@ length_test() -> ggs_db:setItem(1,2,2,"122"), ggs_db:setItem(1,1,3,"113"), ggs_db:setItem(1,1,4,"114"), - ?assertEqual(ggs_db:length(1,1), 3), + ?assertEqual(ggs_db:length(1,1), 3). + +removeItem_test() -> + ggs_db:removeItem(1,1,4), + ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}), mnesia:stop(). %cleanup(Val) -> From 8b978934c70b9b1755bdf13f8c494337609d6434 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 21 Feb 2011 23:55:20 +0100 Subject: [PATCH 42/67] key with test. --- mnesia/ggs_db.erl | 11 +++++++++-- mnesia/ggs_db_test.erl | 7 +++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mnesia/ggs_db.erl b/mnesia/ggs_db.erl index 1c15536..9c7cb3c 100644 --- a/mnesia/ggs_db.erl +++ b/mnesia/ggs_db.erl @@ -7,7 +7,7 @@ -module(ggs_db). -import(mnesia). %-compile({no_auto_import,[length/2]}). --export([init/0,setItem/4,getItem/3,removeItem/3,length/2]). +-export([init/0,setItem/4,getItem/3,removeItem/3,key/3,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- @@ -63,4 +63,11 @@ length(Db,Ns) -> {atomic, Ret} = mnesia:transaction(Fun), Ret. - +key(Db,Ns,Position) -> + Fun = fun() -> + Keys = mnesia:all_keys(data), + Rest = lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys), + lists:nth(Position, Rest) + end, + {atomic, Ret} = mnesia:transaction(Fun), + Ret. diff --git a/mnesia/ggs_db_test.erl b/mnesia/ggs_db_test.erl index e15ddf4..a1a2ff1 100644 --- a/mnesia/ggs_db_test.erl +++ b/mnesia/ggs_db_test.erl @@ -24,9 +24,12 @@ length_test() -> removeItem_test() -> ggs_db:removeItem(1,1,4), - ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}), - mnesia:stop(). + ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}). + %mnesia:stop(). +key_test() -> + ?assert(ggs_db:key(1,1,2) =:= {1,1,3}), + mnesia:stop(). %cleanup(Val) -> % mnesia:stop(). From 276a1837383eb9604f30d6d9070d8ccfdffa7463 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 00:14:11 +0100 Subject: [PATCH 43/67] clear with test. --- mnesia/ggs_db.erl | 13 ++++++++++++- mnesia/ggs_db_test.erl | 11 +++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/mnesia/ggs_db.erl b/mnesia/ggs_db.erl index 9c7cb3c..eef1415 100644 --- a/mnesia/ggs_db.erl +++ b/mnesia/ggs_db.erl @@ -7,7 +7,7 @@ -module(ggs_db). -import(mnesia). %-compile({no_auto_import,[length/2]}). --export([init/0,setItem/4,getItem/3,removeItem/3,key/3,length/2]). +-export([init/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- @@ -71,3 +71,14 @@ key(Db,Ns,Position) -> end, {atomic, Ret} = mnesia:transaction(Fun), Ret. + + +clear(Db,Ns) -> + Fun = fun() -> + Keys = mnesia:all_keys(data), + Rest = lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys), + lists:map(fun({A,B,C}) -> removeItem(A,B,C) end, Rest) + end, + {atomic, Ret} = mnesia:transaction(Fun), + Ret. + diff --git a/mnesia/ggs_db_test.erl b/mnesia/ggs_db_test.erl index a1a2ff1..ea6e12e 100644 --- a/mnesia/ggs_db_test.erl +++ b/mnesia/ggs_db_test.erl @@ -25,15 +25,14 @@ length_test() -> removeItem_test() -> ggs_db:removeItem(1,1,4), ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}). - %mnesia:stop(). key_test() -> - ?assert(ggs_db:key(1,1,2) =:= {1,1,3}), + ?assert(ggs_db:key(1,1,2) =:= {1,1,3}). + +clear_test() -> + ggs_db:clear(1,1), + ?assert(ggs_db:length(1,1) =:= 0), mnesia:stop(). -%cleanup(Val) -> -% mnesia:stop(). - - %tests() -> % ggs_db_test(). From e03f3cf69d475b2aa90a133cdd39835dcc3c1781 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 00:15:21 +0100 Subject: [PATCH 44/67] better js_erlang_test --- src/ggs_gamevm.erl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 294eb10..6dd19a7 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -120,14 +120,11 @@ user_command_test() -> user_command(GameVM, "'jeena", "thecommand", "theargs'"), ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). -to_string({A, B, C}) -> - "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}". - -user_command2_test() -> +js_erlang_test() -> GameVM = start_link(test_table), define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), user_command(GameVM, "", "", ""), - T = to_string(erlang:time()), - io:format("test ~p~n", [T]), - ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). + {A, B, C} = erlang:time(), + T = "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}", + ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). From a7ffc843437e66ca5996f8965a884c2d43ad16d1 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 00:18:13 +0100 Subject: [PATCH 45/67] refactoring. --- mnesia/ggs_db.erl | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mnesia/ggs_db.erl b/mnesia/ggs_db.erl index eef1415..912d349 100644 --- a/mnesia/ggs_db.erl +++ b/mnesia/ggs_db.erl @@ -45,6 +45,16 @@ removeItem(Db,Ns,Key) -> mnesia:transaction(Fun). +clear(Db,Ns) -> + Fun = fun() -> + Keys = mnesia:all_keys(data), + Rest = lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys), + lists:map(fun({A,B,C}) -> removeItem(A,B,C) end, Rest) + end, + {atomic, Ret} = mnesia:transaction(Fun), + Ret. + + %%----------------------------------------------------- %% Querries %%----------------------------------------------------- @@ -73,12 +83,4 @@ key(Db,Ns,Position) -> Ret. -clear(Db,Ns) -> - Fun = fun() -> - Keys = mnesia:all_keys(data), - Rest = lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys), - lists:map(fun({A,B,C}) -> removeItem(A,B,C) end, Rest) - end, - {atomic, Ret} = mnesia:transaction(Fun), - Ret. From 073c4d49b01b057094ce47e5b8ffaf4a12e9c923 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 00:35:54 +0100 Subject: [PATCH 46/67] merged rewrite and master --- .gitignore | 1 + mnesia/gamedb.erl | 50 ----------------------- src/.ggs_connection.erl.swp | Bin 12288 -> 0 bytes src/.ggs_server.erl.swo | Bin 12288 -> 0 bytes src/ggs_table.erl | 78 ------------------------------------ src/js_helper.erl | 8 ---- tests/ggs_table_test.erl | 44 ++++++++++++++++++++ 7 files changed, 45 insertions(+), 136 deletions(-) delete mode 100644 mnesia/gamedb.erl delete mode 100644 src/.ggs_connection.erl.swp delete mode 100644 src/.ggs_server.erl.swo delete mode 100644 src/js_helper.erl create mode 100644 tests/ggs_table_test.erl diff --git a/.gitignore b/.gitignore index d176978..f6b93e9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.dump *.beam Mnesia.* +*.swo diff --git a/mnesia/gamedb.erl b/mnesia/gamedb.erl deleted file mode 100644 index 751eb92..0000000 --- a/mnesia/gamedb.erl +++ /dev/null @@ -1,50 +0,0 @@ -%%%%---------------------------------------------------- -%%% @author Mattias Pettersson -%%% @copyright 2011 Mattias Pettersson -%%% @doc Database for runtime game variable storage. -%%% @end - - Test Mnesia --module(gamedb). --import(mnesia). --export([init/0,insert_player/1,example_player/0,read_player/1,test_player/0]). --include("gamedb.hrl"). - -%%----------------------------------------------------- -%% Creation -%%----------------------------------------------------- -init() -> - mnesia:create_table(player, [{attributes, record_info(fields, player)}]). - -%%----------------------------------------------------- -%% Test -%%----------------------------------------------------- -test_player() -> - insert_player(example_player()), - read_player(0001). - -example_player() -> - #player{id = 0001, - name = "Tux"}. - -%%----------------------------------------------------- -%% Insertions -%%----------------------------------------------------- -insert_player(Player) -> - Fun = fun() -> - mnesia:write(Player) - end, - mnesia:transaction(Fun). - - -%%----------------------------------------------------- -%% Querries -%%----------------------------------------------------- -read_player(Player_Key) -> - Fun = fun() -> - [P] = mnesia:read(player, Player_Key), - Name = P#player.name, - io:format("Player name: ~s~n",[Name]) - end, - mnesia:transaction(Fun). - diff --git a/src/.ggs_connection.erl.swp b/src/.ggs_connection.erl.swp deleted file mode 100644 index 0c009f8287377d2e3763a3fb7610231c3237d3fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2O>Z1E7{^^+M0qKoqMo?8TdkN?XJ3-EAceGwl!%h3+pLndm(^7W&e$W5 zH=){YkdU|{!I^9M0Eiwz;sQv$@CmqagL`?A;O}|aYywf~wg)QN%3m`c+m9drp2wC} z@pkLxTARMpSRg2`6LRL$wf0X-7s$022}!jSJV-*tG&jx1l^q@@QXbcO@O^*UU^7v2 zpjaG-V$kF&Vt8D+veitL-y955&zC}QUx!jO(0X9RzF7j6z#|igm=49FN1 zorLbcO2}R4b0~m(Xd7xnSD`;o5%LH0JMre&y z^<_eSfqsPUL0>^0^cM8jON4v_-GN5XD)c7wJoFs&EOa0D7QTi)hWbziItx9(`pg>d znswS@30MM_fF)oFSOWih0yHZFE521sA2M4uN3~j?rI2cs zUSH|Z6&6J)MQs)%b%ft6aU`VTNp#y_!hO$iBmXLIxzsbX$Mn(!1M_{JXy>Z=UUSI~ z6G6niQ1qpv!-Ta5CfkPGeY#$L=44BCi-HeSx3 zr`>COFEh~_kKfH)4CP{9s+eh~f^HN87EKbA{Y)i~N^ZoRwDjOQ7G4@JT+2OZ9P%LV zS6YNWf%Mk54E9MPZnC{qrddI+=F;l*jn$1qXhz6hv=^CM3>cRqkZZ;nT1^;k#d6J6 zN_}Z=$I`x%amGI7YL}}bUbsvPbBJ2ZqJy9nvG7@{oxI0U;6;>2CbC)Ezpc1*3u!R1 zh}90b#>L#BKzzOT;MJ7#Gp8St`28$_R64T_V#sAHDiSD>N+V7kJY0G>2VL4KlG_Y= zSQ#lkOgRez)c+ z8=X?jj*O5x|G;o^y2h_24#=rcH|M9Ssh+BuZEmXO1Z^%9&kH@AsiYpuU>I@7+}}3) zo@?_JF3xl^nQ?R(v*a&<^vhu7dx++>|;O?y@+$5Y|N|GrN0mvvzuVYG#`0>1wNM zU}2o~fQcOR;J={Zju(~aNfTmXVvHeC4|?;UCW?f_tKaJG`2{LumV+eK$%mfmu6p(A z`(C~74PDNz9zQ{!OHUIVdkNWgb@s%Su?yshR|q-9eaY1I+Z?a5K=Rx4QMWfEgPD02 zHY5)+d0t_eW5-IFP&k=dEwn-=PBW2a!n*@wx{FpoD{$uuv}85){2p>}dMc|19T?wF zAA5A=&d2MXS^=$qRzNGD70?Q31+)TM0jsbJEl&t$KgIFiH1lr&ncn##iOW<*E;{ighfD7PlPykPXePA!RzLSt&!7t!* z@FBPaHb5CX4JN_E;5WqJYw!V3@i-4w!9MWU{r6yUX_vJE|1$+>|2QIQVVbCRn>S3V znjJc$+W&F~A0}CWEkc%y{UHeSjyX;*YhnhOjEOjOiZLk zIWUeM$9H7Hw>?^I`HpnCAC7E|C>0~2OVXCClO_&6BeR^k?bn!Lo%AZJp>NXYrb(@Z z4Jqu&$bU7EH_}8!&Gj+Xu!_tMIeJ@B_kOpw&jky-vxyx{q6SB^S}JHNO}de^9S5Jk z8B6Lq6oelYk6Er?<%V>djJFV-1EKP@?S<%rp;2FDqN#N-WKt88IFWW zvx6b-g{K>0&kZH>lbyEKwvoc8nMtK+v5wj`uJ1}?O<7)#71_d8QFF%MK~e|%uxvYx zEpC>+#atAJ!=;7d>O#?^Dj+B?>SRQIZ^7+3)HAiy=fZ$FYP0mLV$Vf4Dm=Q5oaaGE zWu4LFbI+}nf}zzRCwi;vB?p$+`+e8eN#pG|LtT`%8WYB(TI88J6KqI^;hEzS5)JJP ziE@-lr_N$o{8qEf1m#tlY}=4F?FyrkLp3){WZRl*s7FHLq2o7$TZNOw z8fW>~8cVDr#Kxq)_{l4ix#!G>TdGsi+zQkJQXT6~PqSP)-?Zs?=qs z%G{3VS9SKdq8p-ON;%doJ}8 z5{{{vRV+xV% code_change(_OldVsn, State, _Extra) -> {ok, State}. -%% @TODO: Please put these tests in a separate file. We can't compile this file if -%% they contain errors from switching vms -%% ---------------------------------------------------------------------- -% Tests - -%<<<<<<< HEAD -%start_link_test() -> -% Table = start_link(), -% ?assertNot(Table =:= undefined). - -%add_player_test() -> -% Table = start_link(), -% Player = test_player, -% add_player(Table, Player), -% {ok, [Player]} = gen_server:call(Table, get_player_list). - -%remove_player_test() -> -% Table = start_link(), -% Player = test_player, -% Player2 = test_player2, -% add_player(Table, Player), -% {ok, [Player]} = gen_server:call(Table, get_player_list), -% add_player(Table, Player2), -% {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), -% remove_player(Table, Player), -% {ok, [Player2]} = gen_server:call(Table, get_player_list), -% remove_player(Table, Player2), -% {ok, []} = gen_server:call(Table, get_player_list). -% -%stop_test() -> -% Table = start_link(), -% ok = stop(Table). - -% @private -%notify_test() -> -% Table = start_link(), -% Player = test_player, -% Message = {server, define, "function helloWorld(x) { }"}, -% ok = notify(Table, Player, Message). -%======= -%%start_link_test() -> -% Table = start_link("123", none), -% ?assertNot(Table =:= undefined). -% -%add_player_test() -> -% Table = start_link("123", none), -% Player = test_player, -% add_player(Table, Player), -% {ok, [Player]} = gen_server:call(Table, get_player_list). - -%remove_player_test() -> -% Table = start_link("123", none), -% Player = test_player, -% Player2 = test_player2, -% add_player(Table, Player), -% {ok, [Player]} = gen_server:call(Table, get_player_list), -% add_player(Table, Player2), -% {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), -% remove_player(Table, Player), -% {ok, [Player2]} = gen_server:call(Table, get_player_list), -% remove_player(Table, Player2), -% {ok, []} = gen_server:call(Table, get_player_list). -% -%stop_test() -> -% Table = start_link("123", none), -% ok = stop(Table). -% -%% @private -%notify_test() -> -% Table = start_link("123", none), -% Player = test_player, -% Message = {server, define, "function helloWorld(x) { }"}, -% ok = notify(Table, Player, Message). -%>>>>>>> jonte_rewrite - %Message2 = {game, "helloWorld", "test"}, - %ok = notify(Table, Player, Message2). - diff --git a/src/js_helper.erl b/src/js_helper.erl deleted file mode 100644 index efb38f4..0000000 --- a/src/js_helper.erl +++ /dev/null @@ -1,8 +0,0 @@ --module(js_helper). --export([test/0, echo/1]). - -test() -> - {ok, test}. - -echo(String) -> - {ok, String}. \ No newline at end of file diff --git a/tests/ggs_table_test.erl b/tests/ggs_table_test.erl new file mode 100644 index 0000000..5757456 --- /dev/null +++ b/tests/ggs_table_test.erl @@ -0,0 +1,44 @@ +-include_lib("eunit/include/eunit.hrl"). +-import(ggs_table). + + +% @private +start_link_test() -> + Table = start_link(), + ?assertNot(Table =:= undefined). + +% @private +add_player_test() -> + Table = start_link(), + Player = test_player, + add_player(Table, Player), + {ok, [Player]} = gen_server:call(Table, get_player_list). + +% @private +remove_player_test() -> + Table = start_link(), + Player = test_player, + Player2 = test_player2, + add_player(Table, Player), + {ok, [Player]} = gen_server:call(Table, get_player_list), + add_player(Table, Player2), + {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), + remove_player(Table, Player), + {ok, [Player2]} = gen_server:call(Table, get_player_list), + remove_player(Table, Player2), + {ok, []} = gen_server:call(Table, get_player_list). + +% @private +stop_test() -> + Table = start_link(), + ok = stop(Table). + +% @private +notify_test() -> + Table = start_link(), + Player = test_player, + Message = {server, define, "function helloWorld(x) { }"}, + ok = notify(Table, Player, Message). + Message2 = {game, "helloWorld", "test"}, + ok = notify(Table, Player, Message2). + From eb3925bebdd99f6eee8402688ea7dbceed2e9549 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 00:39:15 +0100 Subject: [PATCH 47/67] fixed issues with tests --- tests/ggs_player_test.erl | 1 + tests/ggs_table_test.erl | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index be38135..66900d6 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -1,3 +1,4 @@ +-module(ggs_player_test). -include_lib("eunit/include/eunit.hrl"). -import(ggs_player). diff --git a/tests/ggs_table_test.erl b/tests/ggs_table_test.erl index 5757456..7a270ed 100644 --- a/tests/ggs_table_test.erl +++ b/tests/ggs_table_test.erl @@ -1,3 +1,4 @@ +-module(ggs_table_test). -include_lib("eunit/include/eunit.hrl"). -import(ggs_table). From e4753b2c074c01ac2f08e981cbbed88c5e0e64dc Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 00:49:43 +0100 Subject: [PATCH 48/67] minor changes --- erlang_js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erlang_js b/erlang_js index 2f2785f..709b568 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 2f2785fafb0da6db75810eb6fa97d09c58257588 +Subproject commit 709b568efbc99c954507d1593bc5633f900bc5dc From bf4d7439233b33770b92bcb0b464204c34baeabc Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 01:09:55 +0100 Subject: [PATCH 49/67] ggs_db.erl only init and stop left to do. ggs_db.test.erl only init and stop left todo. Everything else is done with these two files. --- erlang_js | 2 +- {mnesia => src}/ggs_db.erl | 0 {mnesia => tests}/ggs_db_test.erl | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename {mnesia => src}/ggs_db.erl (100%) rename {mnesia => tests}/ggs_db_test.erl (100%) diff --git a/erlang_js b/erlang_js index 709b568..5350ed2 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 709b568efbc99c954507d1593bc5633f900bc5dc +Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 diff --git a/mnesia/ggs_db.erl b/src/ggs_db.erl similarity index 100% rename from mnesia/ggs_db.erl rename to src/ggs_db.erl diff --git a/mnesia/ggs_db_test.erl b/tests/ggs_db_test.erl similarity index 100% rename from mnesia/ggs_db_test.erl rename to tests/ggs_db_test.erl From 6ee945379f0c41e6f12bb26f9626165dbdbfdb6e Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 03:11:35 +0100 Subject: [PATCH 50/67] added makefile, fixed problems with tests --- Makefile | 28 ++++++++++++++++++++++++++++ src/ggs_coordinator.erl | 4 ++-- src/ggs_dispatcher.erl | 2 +- src/ggs_gamevm_e.erl | 2 +- src/ggs_player.erl | 2 +- src/ggs_table.erl | 14 ++++++++------ tests/ggs_player_test.erl | 9 ++++----- tests/ggs_table_test.erl | 33 +++++++++++++-------------------- 8 files changed, 58 insertions(+), 36 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5c0e61d --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +ERLC=erlc +ERLCFLAGS=-o +SRCDIR=src +TESTDIR=tests +BEAMDIR=./ebin + +all: compile erlang_js + +compile: + @ mkdir -p $(BEAMDIR) ; + @ $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(SRCDIR)/*.erl ; + +erlang_js: + $(MAKE) -C erlang_js/ + +test: compile erlang_js + @ mkdir -p $(BEAMDIR) ; + @ $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(TESTDIR)/*.erl ; + @ cd $(BEAMDIR) ; erl -noinput -eval 'eunit:test({dir, "."}, [verbose]), init:stop()' ; + +clean: + @ rm -rf $(BEAMDIR)/*.beam ; + @ rm -rf erl_crush.dump ; + @ echo "==> clean ggs" ; + @ $(MAKE) -C erlang_js/ clean + +run: + @ erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 733ff8d..83f7e14 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -65,7 +65,7 @@ handle_call({join_table, Table}, From, State) -> {FromPlayer, _Ref} = From, Tables = State#co_state.tables, case lists:keyfind(Table, 1, Tables) of - {TableID, TablePID} -> + {_TableID, TablePID} -> ggs_table:add_player(TablePID, FromPlayer), {reply, {ok, TablePID}, State}; false -> @@ -84,7 +84,7 @@ handle_call({create_table, {force, TableID}}, From, State) -> handle_call(_Message, _From, State) -> {noreply, State}. -handle_cast({stop, Reason}, State) -> +handle_cast({stop, _Reason}, _State) -> {stop, normal, state}; handle_cast(_Message, State) -> diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 49dcf4b..11dd729 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -45,7 +45,7 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. -handle_info({tcp, _Socket, RawData}, State) -> +handle_info({tcp, _Socket, _RawData}, State) -> io:format("Got connect request!~n"), {noreply, State}; diff --git a/src/ggs_gamevm_e.erl b/src/ggs_gamevm_e.erl index 76b9350..6ca4e1b 100644 --- a/src/ggs_gamevm_e.erl +++ b/src/ggs_gamevm_e.erl @@ -32,7 +32,7 @@ user_command(GameVM, Player, Command, Args) -> loop(Table) -> receive - {define, SourceCode} -> + {define, _SourceCode} -> loop(Table); {user_command, _User, Command, _Args, _From, _Ref} -> io:format("GameVM received a message~n"), diff --git a/src/ggs_player.erl b/src/ggs_player.erl index af92ad9..27c73d0 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -60,7 +60,7 @@ loop(#pl_state{token = Token, socket = Socket, table = Table} = State) -> io:format("Notifying table..~n"), ggs_table:notify_game(Table, Token, Data), loop(State); - {notify, From, Message} -> + {notify, _From, Message} -> gen_tcp:send(Socket, Message), loop(State) end. diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 4715e79..9ddc7d6 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -5,17 +5,18 @@ %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3, notify_all_players/2, notify_game/3, - add_player/2]). + terminate/2, code_change/3]). -record(state, { players, game_vm } ). %% API -export([start_link/0, - add_player/2, - remove_player/2, - stop/1, - notify/3]). + add_player/2, + remove_player/2, + stop/1, + notify/3, + notify_all_players/2, + notify_game/3]). %% ---------------------------------------------------------------------- @@ -24,6 +25,7 @@ % @doc returns a new table start_link() -> {ok, Pid} = gen_server:start_link(?MODULE, [], []), + Pid. %% @private call(Pid, Msg) -> diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index 66900d6..efe7530 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -1,6 +1,5 @@ -module(ggs_player_test). -include_lib("eunit/include/eunit.hrl"). --import(ggs_player). %% @doc start_link should always return ok for any valid socket. A valid socket %% should always return {ok, Pid} and {error, Reason} otherwise. @@ -10,9 +9,9 @@ start_link_test() -> %% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and %% deliver a specified message through the socket. notify_test() -> - Player = start_link("bad arg"), + Player = ggs_player:start_link("bad arg"), Message = {"something", ""}, - Ret = ggs_player:notify(Player, self(), Message) + Ret = ggs_player:notify(Player, self(), Message), ?assertNot(ok =:= Ret). %% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid @@ -23,6 +22,6 @@ get_token_test() -> %% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to %% execute this function with the same Player and Table arguments twice. stop_test() -> - Player = start_link(something), + Player = ggs_player:start_link(something), Table = test, - ok = stop(Player, Table). + ok = ggs_player:stop(Player, Table). diff --git a/tests/ggs_table_test.erl b/tests/ggs_table_test.erl index 7a270ed..c10effb 100644 --- a/tests/ggs_table_test.erl +++ b/tests/ggs_table_test.erl @@ -1,45 +1,38 @@ -module(ggs_table_test). -include_lib("eunit/include/eunit.hrl"). --import(ggs_table). - -% @private start_link_test() -> - Table = start_link(), + Table = ggs_table:start_link(), ?assertNot(Table =:= undefined). -% @private add_player_test() -> - Table = start_link(), + Table = ggs_table:start_link(), Player = test_player, - add_player(Table, Player), + ggs_table:add_player(Table, Player), {ok, [Player]} = gen_server:call(Table, get_player_list). -% @private remove_player_test() -> - Table = start_link(), + Table = ggs_table:start_link(), Player = test_player, Player2 = test_player2, - add_player(Table, Player), + ggs_table:add_player(Table, Player), {ok, [Player]} = gen_server:call(Table, get_player_list), - add_player(Table, Player2), + ggs_table:add_player(Table, Player2), {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), - remove_player(Table, Player), + ggs_table:remove_player(Table, Player), {ok, [Player2]} = gen_server:call(Table, get_player_list), - remove_player(Table, Player2), + ggs_table:remove_player(Table, Player2), {ok, []} = gen_server:call(Table, get_player_list). -% @private stop_test() -> - Table = start_link(), - ok = stop(Table). + Table = ggs_table:start_link(), + ok = ggs_table:stop(Table). -% @private notify_test() -> - Table = start_link(), + Table = ggs_table:start_link(), Player = test_player, Message = {server, define, "function helloWorld(x) { }"}, - ok = notify(Table, Player, Message). + ok = ggs_table:notify(Table, Player, Message), Message2 = {game, "helloWorld", "test"}, - ok = notify(Table, Player, Message2). + ok = ggs_table:notify(Table, Player, Message2). From 17356692c67ee3125b05151247de9d65f3e975d3 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 03:14:48 +0100 Subject: [PATCH 51/67] latest erlang_js update --- erlang_js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erlang_js b/erlang_js index 5350ed2..709b568 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 +Subproject commit 709b568efbc99c954507d1593bc5633f900bc5dc From 597070f2d608781f797cd7982249e568a1135239 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 11:18:13 +0100 Subject: [PATCH 52/67] added ggs_db.hrl to src --- {mnesia => src}/ggs_db.hrl | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {mnesia => src}/ggs_db.hrl (100%) diff --git a/mnesia/ggs_db.hrl b/src/ggs_db.hrl similarity index 100% rename from mnesia/ggs_db.hrl rename to src/ggs_db.hrl From 0c530dde5d1d7bffc2d107c5301a3bc432f028a5 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 12:36:36 +0100 Subject: [PATCH 53/67] clear(GameToken) aded. --- erlang_js | 2 +- src/ggs_db.erl | 52 +++++++++++++++++++++++++------------------ tests/ggs_db_test.erl | 6 ++++- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/erlang_js b/erlang_js index 709b568..5350ed2 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 709b568efbc99c954507d1593bc5633f900bc5dc +Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 diff --git a/src/ggs_db.erl b/src/ggs_db.erl index 912d349..b21bab2 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -7,7 +7,7 @@ -module(ggs_db). -import(mnesia). %-compile({no_auto_import,[length/2]}). --export([init/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,length/2]). +-export([init/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- @@ -27,9 +27,9 @@ init() -> %%----------------------------------------------------- %% Insertions %%----------------------------------------------------- -setItem(Db,Ns,Key,Value) -> +setItem(GameToken,Ns,Key,Value) -> Fun = fun() -> - Data = #data{key = {Db,Ns,Key}, value = Value}, + Data = #data{key = {GameToken,Ns,Key}, value = Value}, mnesia:write(Data) end, mnesia:transaction(Fun). @@ -38,45 +38,53 @@ setItem(Db,Ns,Key,Value) -> %%----------------------------------------------------- %% Deletions %%----------------------------------------------------- -removeItem(Db,Ns,Key) -> +removeItem(GameToken,Ns,Key) -> Fun = fun() -> - mnesia:delete({data,{Db,Ns,Key}}) + mnesia:delete({data,{GameToken,Ns,Key}}) end, mnesia:transaction(Fun). -clear(Db,Ns) -> +clear(GameToken,Ns) -> Fun = fun() -> Keys = mnesia:all_keys(data), - Rest = lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys), + Rest = lists:filter(fun({A,B,_}) -> ((A==GameToken) and (B==Ns)) end, Keys), lists:map(fun({A,B,C}) -> removeItem(A,B,C) end, Rest) end, {atomic, Ret} = mnesia:transaction(Fun), Ret. - -%%----------------------------------------------------- -%% Querries -%%----------------------------------------------------- -getItem(Db,Ns,Key) -> - Fun = fun() -> - [Data] = mnesia:read(data, {Db,Ns,Key}), - Data#data.value - end, - mnesia:transaction(Fun). - -length(Db,Ns) -> +clear(GameToken) -> Fun = fun() -> Keys = mnesia:all_keys(data), - length(lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys)) + Rest = lists:filter(fun({A,_,_}) -> (A==GameToken) end, Keys), + lists:map(fun({A,B,C}) -> removeItem(A,B,C) end, Rest) end, {atomic, Ret} = mnesia:transaction(Fun), Ret. -key(Db,Ns,Position) -> +%%----------------------------------------------------- +%% Querries +%%----------------------------------------------------- +getItem(GameToken,Ns,Key) -> + Fun = fun() -> + [Data] = mnesia:read(data, {GameToken,Ns,Key}), + Data#data.value + end, + mnesia:transaction(Fun). + +length(GameToken,Ns) -> Fun = fun() -> Keys = mnesia:all_keys(data), - Rest = lists:filter(fun({A,B,_}) -> ((A==Db) and (B==Ns)) end, Keys), + length(lists:filter(fun({A,B,_}) -> ((A==GameToken) and (B==Ns)) end, Keys)) + end, + {atomic, Ret} = mnesia:transaction(Fun), + Ret. + +key(GameToken,Ns,Position) -> + Fun = fun() -> + Keys = mnesia:all_keys(data), + Rest = lists:filter(fun({A,B,_}) -> ((A==GameToken) and (B==Ns)) end, Keys), lists:nth(Position, Rest) end, {atomic, Ret} = mnesia:transaction(Fun), diff --git a/tests/ggs_db_test.erl b/tests/ggs_db_test.erl index ea6e12e..5f990c8 100644 --- a/tests/ggs_db_test.erl +++ b/tests/ggs_db_test.erl @@ -31,7 +31,11 @@ key_test() -> clear_test() -> ggs_db:clear(1,1), - ?assert(ggs_db:length(1,1) =:= 0), + ?assert(ggs_db:length(1,1) =:= 0). + +clear_GameToken_test() -> + ggs_db:clear(1), + ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), mnesia:stop(). %tests() -> From 873e88eefdc90afeb3b676928ef02d9a02cb7085 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 12:42:22 +0100 Subject: [PATCH 54/67] Removed init from ggs_db. --- src/ggs_db.erl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ggs_db.erl b/src/ggs_db.erl index b21bab2..5d2ee61 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -10,12 +10,6 @@ -export([init/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). -include("ggs_db.hrl"). -%%----------------------------------------------------- -%% Creation -%%----------------------------------------------------- -init() -> - mnesia:create_table(data, [{attributes, record_info(fields, data)}]). - %%----------------------------------------------------- %% Test %%----------------------------------------------------- From 0c76c85d8fcc3fe551b9a2d6c49a27fa57f4b844 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 13:55:38 +0100 Subject: [PATCH 55/67] added test for one module --- Makefile | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 5c0e61d..cc165a3 100644 --- a/Makefile +++ b/Makefile @@ -7,22 +7,30 @@ BEAMDIR=./ebin all: compile erlang_js compile: - @ mkdir -p $(BEAMDIR) ; - @ $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(SRCDIR)/*.erl ; + mkdir -p $(BEAMDIR) ; + $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(SRCDIR)/*.erl ; erlang_js: - $(MAKE) -C erlang_js/ + $(MAKE) -C erlang_js/ ; -test: compile erlang_js - @ mkdir -p $(BEAMDIR) ; - @ $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(TESTDIR)/*.erl ; - @ cd $(BEAMDIR) ; erl -noinput -eval 'eunit:test({dir, "."}, [verbose]), init:stop()' ; +test: + echo "==> test $(MOD)" ; + mkdir -p $(BEAMDIR) ; +ifeq ($(strip $(MOD)),) + $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(TESTDIR)/*.erl ; + cd $(BEAMDIR) ; erl -noinput -eval 'eunit:test({dir, "."}, [verbose]), init:stop()' ; +else + $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(TESTDIR)/$(MOD)_test.erl ; + cd $(BEAMDIR) ; erl -noinput -eval 'eunit:test($(MOD)_test, [verbose]), init:stop()' ; +endif clean: - @ rm -rf $(BEAMDIR)/*.beam ; - @ rm -rf erl_crush.dump ; - @ echo "==> clean ggs" ; - @ $(MAKE) -C erlang_js/ clean + rm -rf $(BEAMDIR)/*.beam ; + rm -rf erl_crush.dump ; + echo "==> clean ggs" ; + $(MAKE) -C erlang_js/ clean run: - @ erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs + erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs + + \ No newline at end of file From dcc1a6086f39a0c46bc70e0f05ee4e45b06103f8 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 13:56:27 +0100 Subject: [PATCH 56/67] removed io --- src/ggs_table.erl | 12 ++++-------- tests/ggs_table_test.erl | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 9ddc7d6..b696688 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -51,9 +51,6 @@ notify_all_players(Table, Message) -> gen_server:cast(Table, {notify_all_players, Message}). notify_game(Table, From, Message) -> - io:format("Notify game called on"), - erlang:display(Table), - io:format("~n"), gen_server:cast(Table, {notify_game, Message, From}). %% ---------------------------------------------------------------------- @@ -95,11 +92,10 @@ handle_cast({notify_game, Message, From}, #state { game_vm = GameVM } = State) - {noreply, State}; handle_cast({notify_all_players, Message}, #state{players = Players} = State) -> - io:format("Notifying all players... ~p~n", [Players]), - lists:foreach(fun(P) -> - io:format("Notifying ~p~n", [P]), - ggs_player:notify(P, "Server", Message) - end, Players), + lists:foreach( + fun(P) -> ggs_player:notify(P, "Server", Message) end, + Players + ), {noreply, State}; handle_cast(stop, State) -> diff --git a/tests/ggs_table_test.erl b/tests/ggs_table_test.erl index c10effb..8dbe11e 100644 --- a/tests/ggs_table_test.erl +++ b/tests/ggs_table_test.erl @@ -31,7 +31,7 @@ stop_test() -> notify_test() -> Table = ggs_table:start_link(), Player = test_player, - Message = {server, define, "function helloWorld(x) { }"}, + Message = {server, define, "function helloWorld(x) { }"}, ok = ggs_table:notify(Table, Player, Message), Message2 = {game, "helloWorld", "test"}, ok = ggs_table:notify(Table, Player, Message2). From ce7b7d2764e29db0d0a793b935fd205df1608f34 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 13:57:07 +0100 Subject: [PATCH 57/67] removed init from export --- src/ggs_db.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ggs_db.erl b/src/ggs_db.erl index 5d2ee61..7661ae6 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -7,7 +7,7 @@ -module(ggs_db). -import(mnesia). %-compile({no_auto_import,[length/2]}). --export([init/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). +-export([setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- From 059948d7c3b34d200666babf058e6e39b93bd229 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 15:08:25 +0100 Subject: [PATCH 58/67] merge. --- src/ggs_db.erl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ggs_db.erl b/src/ggs_db.erl index 7661ae6..ec8e5a9 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -6,17 +6,20 @@ -module(ggs_db). -import(mnesia). -%-compile({no_auto_import,[length/2]}). --export([setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). +-export([init/0,stop/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). -include("ggs_db.hrl"). %%----------------------------------------------------- -%% Test +%% Creation %%----------------------------------------------------- +init() -> + mnesia:create_schema([node()]), + mnesia:start(), + mnesia:create_table(data, [{attributes, record_info(fields, data)}]). + +stop() -> + mnesia:stop(). -%test_data() -> -% set(0, "Hello"), -% get(0). %%----------------------------------------------------- %% Insertions From 3751ba8c95c83644eb9e8a9af631081c84499c73 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Tue, 22 Feb 2011 16:44:39 +0100 Subject: [PATCH 59/67] Bad code. --- src/ggs_db.erl | 9 +++++---- src/ggs_db.hrl | 1 - tests/ggs_db_test.erl | 44 ++++++++++++++++++++++--------------------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/ggs_db.erl b/src/ggs_db.erl index ec8e5a9..57ff5ac 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -5,15 +5,15 @@ %%% @end -module(ggs_db). --import(mnesia). -export([init/0,stop/0,setItem/4,getItem/3,removeItem/3,key/3,clear/2,clear/1,length/2]). --include("ggs_db.hrl"). +%-include("ggs_db.hrl"). +-record(data, {key, value}). %%----------------------------------------------------- %% Creation %%----------------------------------------------------- init() -> - mnesia:create_schema([node()]), +% mnesia:create_schema([node()]), mnesia:start(), mnesia:create_table(data, [{attributes, record_info(fields, data)}]). @@ -68,7 +68,8 @@ getItem(GameToken,Ns,Key) -> [Data] = mnesia:read(data, {GameToken,Ns,Key}), Data#data.value end, - mnesia:transaction(Fun). + {atomic, Ret} = mnesia:transaction(Fun), + Ret. length(GameToken,Ns) -> Fun = fun() -> diff --git a/src/ggs_db.hrl b/src/ggs_db.hrl index bc13c3a..b7f1f4c 100644 --- a/src/ggs_db.hrl +++ b/src/ggs_db.hrl @@ -1,6 +1,5 @@ %% gamedb.hrl --record(player, {id, name}). -record(data, {key, value}). diff --git a/tests/ggs_db_test.erl b/tests/ggs_db_test.erl index 5f990c8..dcebdb9 100644 --- a/tests/ggs_db_test.erl +++ b/tests/ggs_db_test.erl @@ -10,33 +10,35 @@ %Key should be a tuple of two elements getItem_setItem_test() -> - mnesia:start(), ggs_db:init(), - ggs_db:setItem("dbname","nsname","keyname","Hello"), - ?assertMatch({atomic,"Hello"},ggs_db:getItem("dbname","nsname","keyname")). + ggs_db:setItem("dbname","nsname","keyname1","Hello"), + ggs_db:setItem("dbname","nsname","keyname2","Hello"), + ggs_db:setItem("dbname","nsname","keyname3","Hello"), + %system:wait(2000), + ggs_db:getItem("dbname","nsname","keyname"). -length_test() -> - ggs_db:setItem(1,1,2,"112"), - ggs_db:setItem(1,2,2,"122"), - ggs_db:setItem(1,1,3,"113"), - ggs_db:setItem(1,1,4,"114"), - ?assertEqual(ggs_db:length(1,1), 3). +%length_test() -> +% ggs_db:setItem(1,1,2,"112"), +% ggs_db:setItem(1,2,2,"122"), +% ggs_db:setItem(1,1,3,"113"), +% ggs_db:setItem(1,1,4,"114"), +% ?assertEqual(ggs_db:length(1,1), 3). -removeItem_test() -> - ggs_db:removeItem(1,1,4), - ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}). +%removeItem_test() -> +% ggs_db:removeItem(1,1,4), +% ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}). -key_test() -> - ?assert(ggs_db:key(1,1,2) =:= {1,1,3}). +%key_test() -> +% ?assert(ggs_db:key(1,1,2) =:= {1,1,3}). -clear_test() -> - ggs_db:clear(1,1), - ?assert(ggs_db:length(1,1) =:= 0). +%clear_test() -> +% ggs_db:clear(1,1), +% ?assert(ggs_db:length(1,1) =:= 0). -clear_GameToken_test() -> - ggs_db:clear(1), - ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), - mnesia:stop(). +%clear_GameToken_test() -> +% ggs_db:clear(1), +% ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), +% ggs_db:stop(). %tests() -> % ggs_db_test(). From 0a67224c97bbb6e3235bc98d4c9cae6211f9f4c9 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 16:08:16 +0100 Subject: [PATCH 60/67] more beautiful code --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cc165a3..14f07de 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ ERLC=erlc ERLCFLAGS=-o SRCDIR=src TESTDIR=tests -BEAMDIR=./ebin +BEAMDIR=ebin all: compile erlang_js @@ -31,6 +31,13 @@ clean: $(MAKE) -C erlang_js/ clean run: - erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs + erl \ + -sname ggs \ + -mnesia dir '"/tmp/ggs"' \ + -boot start_sasl \ + -pa erlang_js/ebin/ \ + -pa ebin \ + -pa src \ + -s start_ggs \ No newline at end of file From 2a884cb9a7e9159b8559a462e89cca348d689af0 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 16:09:53 +0100 Subject: [PATCH 61/67] fixed problem with getItem() --- src/ggs_db.erl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ggs_db.erl b/src/ggs_db.erl index 57ff5ac..5e5e727 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -64,12 +64,11 @@ clear(GameToken) -> %% Querries %%----------------------------------------------------- getItem(GameToken,Ns,Key) -> - Fun = fun() -> - [Data] = mnesia:read(data, {GameToken,Ns,Key}), - Data#data.value - end, - {atomic, Ret} = mnesia:transaction(Fun), - Ret. + Fun = fun() -> + mnesia:read(data, {GameToken,Ns,Key}) + end, + {atomic, [Ret]} = mnesia:transaction(Fun), + Ret#data.value. length(GameToken,Ns) -> Fun = fun() -> From a544484f1a25cefad9299ba80054d4b2906bfe87 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 17:28:41 +0100 Subject: [PATCH 62/67] Fixed problem with erlang_js make where it wouldn't make --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 14f07de..d40790a 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ compile: mkdir -p $(BEAMDIR) ; $(ERLC) $(ERLCFLAGS) $(BEAMDIR) $(SRCDIR)/*.erl ; -erlang_js: - $(MAKE) -C erlang_js/ ; +erlang_js: force_look + cd erlang_js ; $(MAKE) $(MFLAGS); test: echo "==> test $(MOD)" ; @@ -40,4 +40,5 @@ run: -pa src \ -s start_ggs - \ No newline at end of file +force_look: + true \ No newline at end of file From 4591a29c21e5e36a79720f44a49b84dab53e06e7 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 19:48:07 +0100 Subject: [PATCH 63/67] removed unnecessary files --- HOWTO | 21 --------------------- build | 6 ------ build_test | 8 -------- client | 17 ----------------- echo_test | 20 -------------------- mnesia/.gamedb.erl.swp | Bin 12288 -> 0 bytes mnesia/build_db | 4 ---- mnesia/build_test_db | 4 ---- mnesia/gamedb.hrl | 6 ------ mnesia/gamedb_usage.txt | 12 ------------ mnesia/test_db | 3 --- start | 3 --- start_test | 3 --- start_test_shell | 3 --- 14 files changed, 110 deletions(-) delete mode 100644 HOWTO delete mode 100755 build delete mode 100755 build_test delete mode 100644 client delete mode 100755 echo_test delete mode 100644 mnesia/.gamedb.erl.swp delete mode 100755 mnesia/build_db delete mode 100755 mnesia/build_test_db delete mode 100644 mnesia/gamedb.hrl delete mode 100644 mnesia/gamedb_usage.txt delete mode 100755 mnesia/test_db delete mode 100755 start delete mode 100755 start_test delete mode 100755 start_test_shell diff --git a/HOWTO b/HOWTO deleted file mode 100644 index 2d28ea8..0000000 --- a/HOWTO +++ /dev/null @@ -1,21 +0,0 @@ -PREREQUISITES: -python version 2.x set to default. - -INSTALL -1. Cd into directory where you to have the project -2. git clone git@github.com:jeena/GGS.git (remember to have a local key) -3. cd GGS/ -4. git submodule init -5. git submodule update -6. cd erlang_js -7. make -8. make test (Optional. It has to work though.) -10. cd ../ -11. ./build -12. - -USAGE -1. start a second terminal -2. in new terminal do command: ./python_client 9000 -3. back to first terminal -4. ./start diff --git a/build b/build deleted file mode 100755 index a9c1c79..0000000 --- a/build +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -for i in `find src -name "*.erl"` -do - erlc -o ebin $i -done \ No newline at end of file diff --git a/build_test b/build_test deleted file mode 100755 index 2f9d630..0000000 --- a/build_test +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -./build - -for i in `find tests -name "*.erl"` -do - erlc -o ebin_test $i -done diff --git a/client b/client deleted file mode 100644 index dff11aa..0000000 --- a/client +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -wKU - -require 'socket' # Sockets are in standard library - -hostname = 'localhost' -port = 7000 - -s = TCPSocket.open(hostname, port) - - - -s.print(q.chop) - -while line = s.gets # Read lines from the socket - puts "Got Echo: " + line.chop # And print with platform line terminator -end -s.close # Close the socket when done diff --git a/echo_test b/echo_test deleted file mode 100755 index 1bbff1f..0000000 --- a/echo_test +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env ruby -wKU - -require 'socket' # Sockets are in standard library - -hostname = 'localhost' -port = 7000 - -print "Which port @ loclhost?" -port = gets - -s = TCPSocket.open(hostname, port.chop) - -s.print("__hello 0") - -while true - line = s.gets # Read lines from the socket - puts ">> " + line.chop # And print with platform line terminator - s.print(gets.chop) -end -s.close # Close the socket when done diff --git a/mnesia/.gamedb.erl.swp b/mnesia/.gamedb.erl.swp deleted file mode 100644 index 469b1f85b2ecf7663f6f99f957c41243aa53c9d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2zfTlF6vqcEQBk9XjV9wE^c~uUwxG9A3wj3SpnmAjS;oFXpP_fq7W5WsLG#cJs2}=` z*tenA&^%Ow94N`@1lEK?CIUo&2oM1xKm>@u|3rXec*zmXaifJFiH1>upT8UXg)*~~ z>5#r#WV<)}R~3ve1=%yL;PBeT2;Jn`8LfGIzc+H@1JWO|Mq+22omqCbw2|9xebwV&MdL9H&}jaz%JyTka;4q><#@S!BC3>)Gzy4_c#PjEwfs92d$g zeDw@9$s((11KAk4Xhgj&_xgNpO&Ft9Jx0hyu4N<8?xOOSg8Y(_Z5Pkd9xtpfAbI60 zlk|Vj0invbZ5$|a&pud5`Hgn$%6u+6_TAF$9KtKfl`zmIKWF2tIK{3yRjS4AN?}1q zeKFlpwTffYEh!vShrbk{ec%Od40`En@qpXv@LICLF(fp^C$W{KAKaj^+l+SvsEbH) z>}FiYzERkptP}oRXk`n+an@anrYxtnjUZgrs@XD}k2uvTuc1mxM0`dXBXtxd^zbqf jn-*N!@$V9T6Fa9h3+=0-$)+b%yW9vo`z7sdlVX1X$Qr-k diff --git a/mnesia/build_db b/mnesia/build_db deleted file mode 100755 index 0aa2042..0000000 --- a/mnesia/build_db +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - - erlc -o . ggs_db.erl - erlc -o . ggs_db_test.erl diff --git a/mnesia/build_test_db b/mnesia/build_test_db deleted file mode 100755 index f5aa938..0000000 --- a/mnesia/build_test_db +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -./build_db -./test_db diff --git a/mnesia/gamedb.hrl b/mnesia/gamedb.hrl deleted file mode 100644 index 1ae9c8f..0000000 --- a/mnesia/gamedb.hrl +++ /dev/null @@ -1,6 +0,0 @@ -%% gamedb.hrl - --record(player, {id, name}). - - - diff --git a/mnesia/gamedb_usage.txt b/mnesia/gamedb_usage.txt deleted file mode 100644 index b3a07a0..0000000 --- a/mnesia/gamedb_usage.txt +++ /dev/null @@ -1,12 +0,0 @@ -1. From terminal: erl -mnesia dir '"/home/user/dir/to/GGS/GameDB.Player"' -2. mnesia:create_schema([node()]). -3. mnesia:start(). -4. c(gamedb). -5. gamedb:init(). -6. mnesia:info(). -7. gamedb:test_player(). - -Last output should be: - Player name: Tux - {atomic,ok} - diff --git a/mnesia/test_db b/mnesia/test_db deleted file mode 100755 index 958b005..0000000 --- a/mnesia/test_db +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -erl -eval 'eunit:test(ggs_db_test), q().' diff --git a/start b/start deleted file mode 100755 index 6de5737..0000000 --- a/start +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs diff --git a/start_test b/start_test deleted file mode 100755 index 76050c1..0000000 --- a/start_test +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -erl -boot start_sasl -pa ebin_test -pa erlang_js/ebin/ -pa ebin -pa src -eval 'ggs_coordinator_test:test().' diff --git a/start_test_shell b/start_test_shell deleted file mode 100755 index f2135c4..0000000 --- a/start_test_shell +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -erl -boot start_sasl -pa ebin_test -pa erlang_js/ebin/ -pa erlv8/ebin -pa ebin -pa src From c38b2120abf774537410a0b4c7632a6771cf8888 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 19:48:33 +0100 Subject: [PATCH 64/67] merged with HOWTO --- README | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README b/README index 853cc89..9aa5357 100644 --- a/README +++ b/README @@ -1,3 +1,35 @@ GGS is a Generic Game Server -Check out http://ggs-kandidat.blogspot.com/ \ No newline at end of file +Check out http://ggs-kandidat.blogspot.com/ + +PREREQUISITES: +python version 2.x set to default. + +INSTALL +1. cd into directory where you to have the project +2. git clone git@github.com:jeena/GGS.git (remember to have a local key) +3. cd GGS/ +4. git submodule init +5. git submodule update + +USAGE +1. start a second terminal +2. in new terminal do command: ./python_client 9000 +3. back to first terminal +4. make run + +MAKE +To compile modules (even erlang_js): + make + +To run server: + make run + +To clean (even erlang_js): + make clean + +To compile and run all tests: + make test + +To compile and run one test: + make test MOD=ggs_modulename # (must have /tests/ggs_modulename_test.erl) From 8a1a520ac0e2760835318c75b3d7981d3c545ae9 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 19:49:57 +0100 Subject: [PATCH 65/67] moved tests to own file --- src/ggs_gamevm.erl | 31 ------------------------------- tests/ggs_gamevm_test.erl | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 tests/ggs_gamevm_test.erl diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 6dd19a7..babee27 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -97,34 +97,3 @@ code_change(_OldVsn, State, _Extra) -> js_escape(S) -> lists:flatmap(fun($\') -> [$\\, $\']; (X) -> [X] end, S). -%% ---------------------------------------------------------------------- -% Tests - -start_link_test() -> - erlang_js:start(), %% @TODO: should only be done once - GameVM = start_link(test_table), - ?assertNot(GameVM =:= undefined). - -define_test() -> - GameVM = start_link(test_table), - define(GameVM, "function hello(test) { return test; }"), - ?assertMatch(<<"jeena">>, gen_server:call(GameVM, {eval, "hello('jeena')"})). - -stop_test() -> - GameVM = start_link(test_table), - ok = stop(GameVM). - -user_command_test() -> - GameVM = start_link(test_table), - define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), - user_command(GameVM, "'jeena", "thecommand", "theargs'"), - ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). - -js_erlang_test() -> - GameVM = start_link(test_table), - define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), - user_command(GameVM, "", "", ""), - {A, B, C} = erlang:time(), - T = "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}", - ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). - diff --git a/tests/ggs_gamevm_test.erl b/tests/ggs_gamevm_test.erl new file mode 100644 index 0000000..1689dd1 --- /dev/null +++ b/tests/ggs_gamevm_test.erl @@ -0,0 +1,31 @@ +-module(ggs_gamevm_test). +-include_lib("eunit/include/eunit.hrl"). + +start_link_test() -> + erlang_js:start(), %% @TODO: should only be done once + GameVM = start_link(test_table), + ?assertNot(GameVM =:= undefined). + +define_test() -> + GameVM = start_link(test_table), + define(GameVM, "function hello(test) { return test; }"), + ?assertMatch(<<"jeena">>, gen_server:call(GameVM, {eval, "hello('jeena')"})). + +stop_test() -> + GameVM = start_link(test_table), + ok = stop(GameVM). + +user_command_test() -> + GameVM = start_link(test_table), + define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), + user_command(GameVM, "'jeena", "thecommand", "theargs'"), + ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). + +js_erlang_test() -> + GameVM = start_link(test_table), + define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), + user_command(GameVM, "", "", ""), + {A, B, C} = erlang:time(), + T = "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}", + ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). + From 21b2b9aeda38e84280ee9d0b9e1c451e89043567 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 19:51:48 +0100 Subject: [PATCH 66/67] readded tests after fix --- tests/ggs_db_test.erl | 54 ++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/tests/ggs_db_test.erl b/tests/ggs_db_test.erl index dcebdb9..0ee4686 100644 --- a/tests/ggs_db_test.erl +++ b/tests/ggs_db_test.erl @@ -12,39 +12,31 @@ getItem_setItem_test() -> ggs_db:init(), ggs_db:setItem("dbname","nsname","keyname1","Hello"), - ggs_db:setItem("dbname","nsname","keyname2","Hello"), - ggs_db:setItem("dbname","nsname","keyname3","Hello"), - %system:wait(2000), - ggs_db:getItem("dbname","nsname","keyname"). + ggs_db:setItem("dbname","nsname","keyname2","Hello2"), + ggs_db:setItem("dbname2","nsname","keyname1","Hello3"), + ggs_db:setItem("dbname2","nsname","keyname1","Hello4"), + ggs_db:setItem("dbname3","nsname","keyname1","Hello5"), + "Hello" = ggs_db:getItem("dbname","nsname","keyname1"). -%length_test() -> -% ggs_db:setItem(1,1,2,"112"), -% ggs_db:setItem(1,2,2,"122"), -% ggs_db:setItem(1,1,3,"113"), -% ggs_db:setItem(1,1,4,"114"), -% ?assertEqual(ggs_db:length(1,1), 3). +length_test() -> + ggs_db:setItem(1,1,2,"112"), + ggs_db:setItem(1,2,2,"122"), + ggs_db:setItem(1,1,3,"113"), + ggs_db:setItem(1,1,4,"114"), + ?assertEqual(ggs_db:length(1,1), 3). -%removeItem_test() -> -% ggs_db:removeItem(1,1,4), -% ?assertNot(ggs_db:getItem(1,1,4) =:= {atomic,"114"}). +removeItem_test() -> + ggs_db:removeItem(1,1,4), + ?assertNot(ggs_db:getItem(1,1,4) =:= "114"). -%key_test() -> -% ?assert(ggs_db:key(1,1,2) =:= {1,1,3}). +key_test() -> + ?assert(ggs_db:key(1,1,2) =:= {1,1,3}). -%clear_test() -> -% ggs_db:clear(1,1), -% ?assert(ggs_db:length(1,1) =:= 0). - -%clear_GameToken_test() -> -% ggs_db:clear(1), -% ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), -% ggs_db:stop(). - -%tests() -> -% ggs_db_test(). - -%ggs_db_test() -> -% ggs_db:set(0, "Hello"), - %io:format("~s",[Val]), -% ?assertMatch({atomic,"Hello"},ggs_db:get(0)). +clear_test() -> + ggs_db:clear(1,1), + ?assert(ggs_db:length(1,1) =:= 0). +clear_GameToken_test() -> + ggs_db:clear(1), + ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), + ggs_db:stop(). From 0aac25cd42c89d6b70c9b49e3adfefa521992058 Mon Sep 17 00:00:00 2001 From: niklas Date: Wed, 23 Feb 2011 22:29:10 +0100 Subject: [PATCH 67/67] Fixed getItem in ggs_db --- src/ggs_db.erl | 20 +++++++++--------- tests/ggs_db_test.erl | 47 ++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/ggs_db.erl b/src/ggs_db.erl index 5e5e727..29665a3 100644 --- a/src/ggs_db.erl +++ b/src/ggs_db.erl @@ -41,7 +41,6 @@ removeItem(GameToken,Ns,Key) -> end, mnesia:transaction(Fun). - clear(GameToken,Ns) -> Fun = fun() -> Keys = mnesia:all_keys(data), @@ -61,14 +60,18 @@ clear(GameToken) -> Ret. %%----------------------------------------------------- -%% Querries +%% Queries %%----------------------------------------------------- getItem(GameToken,Ns,Key) -> - Fun = fun() -> - mnesia:read(data, {GameToken,Ns,Key}) - end, - {atomic, [Ret]} = mnesia:transaction(Fun), - Ret#data.value. + Fun = fun() -> + mnesia:read(data, {GameToken,Ns,Key}) + end, + case mnesia:transaction(Fun) of + {atomic, []} -> + {error}; + {atomic, [Ret]} -> + Ret#data.value +end. length(GameToken,Ns) -> Fun = fun() -> @@ -86,6 +89,3 @@ key(GameToken,Ns,Position) -> end, {atomic, Ret} = mnesia:transaction(Fun), Ret. - - - diff --git a/tests/ggs_db_test.erl b/tests/ggs_db_test.erl index 0ee4686..f2608f1 100644 --- a/tests/ggs_db_test.erl +++ b/tests/ggs_db_test.erl @@ -9,34 +9,39 @@ %Key should be a tuple of two elements -getItem_setItem_test() -> - ggs_db:init(), - ggs_db:setItem("dbname","nsname","keyname1","Hello"), - ggs_db:setItem("dbname","nsname","keyname2","Hello2"), - ggs_db:setItem("dbname2","nsname","keyname1","Hello3"), - ggs_db:setItem("dbname2","nsname","keyname1","Hello4"), - ggs_db:setItem("dbname3","nsname","keyname1","Hello5"), - "Hello" = ggs_db:getItem("dbname","nsname","keyname1"). +getItem_setItem_test() -> + ggs_db:init(), + ggs_db:setItem("dbname","nsname","keyname1","Hello"), + ggs_db:setItem("dbname","nsname","keyname2","Hello2"), + ggs_db:setItem("dbname2","nsname","keyname1","Hello3"), + ggs_db:setItem("dbname2","nsname","keyname1","Hello4"), + ggs_db:setItem("dbname3","nsname","keyname1","Hello5"), + "Hello" = ggs_db:getItem("dbname","nsname","keyname1"). +%Test the length function of our database length_test() -> - ggs_db:setItem(1,1,2,"112"), - ggs_db:setItem(1,2,2,"122"), - ggs_db:setItem(1,1,3,"113"), - ggs_db:setItem(1,1,4,"114"), - ?assertEqual(ggs_db:length(1,1), 3). + ggs_db:setItem(1,1,2,"112"), + ggs_db:setItem(1,2,2,"122"), + ggs_db:setItem(1,1,3,"113"), + ggs_db:setItem(1,1,4,"114"), + ?assertEqual(ggs_db:length(1,1), 3). +%Test if we can remove correctly from the database removeItem_test() -> - ggs_db:removeItem(1,1,4), - ?assertNot(ggs_db:getItem(1,1,4) =:= "114"). + ggs_db:removeItem(1,1,4), + ?assertNot(ggs_db:getItem(1,1,4) =:= "114"). +%Test the key function key_test() -> - ?assert(ggs_db:key(1,1,2) =:= {1,1,3}). + ?assert(ggs_db:key(1,1,2) =:= {1,1,2}). +%Test the clear function(for gametoken and ns) clear_test() -> - ggs_db:clear(1,1), - ?assert(ggs_db:length(1,1) =:= 0). + ggs_db:clear(1,1), + ?assert(ggs_db:length(1,1) =:= 0). +%Test the clear function(gametoken) clear_GameToken_test() -> - ggs_db:clear(1), - ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), - ggs_db:stop(). + ggs_db:clear(1), + ?assert((ggs_db:length(1,1) + ggs_db:length(1,2)) =:= 0), + ggs_db:stop().