diff --git a/.gitignore b/.gitignore index 3f2a73f..d176978 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.dump *.beam +Mnesia.* diff --git a/HOWTO b/HOWTO index 064d127..2d28ea8 100644 --- a/HOWTO +++ b/HOWTO @@ -3,7 +3,7 @@ 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) +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 diff --git a/build b/build index d468113..a9c1c79 100755 --- a/build +++ b/build @@ -3,4 +3,4 @@ for i in `find src -name "*.erl"` do erlc -o ebin $i -done +done \ No newline at end of file diff --git a/client b/client new file mode 100644 index 0000000..dff11aa --- /dev/null +++ b/client @@ -0,0 +1,17 @@ +#!/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/games/tic-tac-toe-js/index.html b/games/tic-tac-toe-js/index.html index 97d3c4f..5bdb286 100644 --- a/games/tic-tac-toe-js/index.html +++ b/games/tic-tac-toe-js/index.html @@ -12,8 +12,16 @@ function init() { GameServer.addGame(game_name, main()); - GameServer.addClient(game_name, new TicTacToeClient(frames.player1.document.getElementById("p1"), GameServer)); - GameServer.addClient(game_name, new TicTacToeClient(frames.player2.document.getElementById("p2"), GameServer)); + GameServer.addClient( + game_name, + new TicTacToeClient(frames.player1.document.getElementById("p1"), + GameServer + )); + GameServer.addClient( + game_name, + new TicTacToeClient(frames.player2.document.getElementById("p2"), + GameServer + )); } diff --git a/games/tic-tac-toe-js/js/TicTacToeClient.js b/games/tic-tac-toe-js/js/TicTacToeClient.js index 80f8ef1..79e4064 100644 --- a/games/tic-tac-toe-js/js/TicTacToeClient.js +++ b/games/tic-tac-toe-js/js/TicTacToeClient.js @@ -90,4 +90,4 @@ TicTacToeClient.prototype.updateBoard = function(gameBoardData) { this.spots[k++].innerHTML = t; } } -} \ No newline at end of file +} diff --git a/games/tic-tac-toe-js/proxy.rb b/games/tic-tac-toe-js/proxy.rb new file mode 100644 index 0000000..e69de29 diff --git a/games/tic-tac-toe/TODO b/games/tic-tac-toe/TODO index 07c0710..a957a1f 100644 --- a/games/tic-tac-toe/TODO +++ b/games/tic-tac-toe/TODO @@ -1,12 +1,6 @@ -- background image -- subimages for game_area:s -- subimages for game markers (X or 0) -- rectangle collision on game_area:s +- background - redraw background then all game_area:s -- board_state: a hashtable where key is game_area_index - and value is either'x' 'o' or ' ' - board contains nr_of_squares = 9 board contains array of squares with nr_of_squares elements board contains x, y, width and height board contains a frame diff --git a/games/tic-tac-toe/data.py b/games/tic-tac-toe/data.py new file mode 100644 index 0000000..b83c3ad --- /dev/null +++ b/games/tic-tac-toe/data.py @@ -0,0 +1,15 @@ +def greatest_sequence(match, pattern): + m = match + p = pattern + size = 0 + max_size = 0 + + for p in pattern: + if m == p: + size += 1 + else: + if size > max_size: + max_size = size + size = 0 + + return max_size diff --git a/games/tic-tac-toe/data.pyc b/games/tic-tac-toe/data.pyc new file mode 100644 index 0000000..682dfaa Binary files /dev/null and b/games/tic-tac-toe/data.pyc differ diff --git a/games/tic-tac-toe/e.png b/games/tic-tac-toe/e.png index 4cbf977..1b1d7f7 100644 Binary files a/games/tic-tac-toe/e.png and b/games/tic-tac-toe/e.png differ diff --git a/games/tic-tac-toe/player.py b/games/tic-tac-toe/player.py new file mode 100644 index 0000000..081112c --- /dev/null +++ b/games/tic-tac-toe/player.py @@ -0,0 +1,15 @@ +from pygame.mouse import get_pos +from point import Point + +class Player(object): + def __init__(self, id, shape, board): + self.shape = shape + self.board = board + self.id = id + + + def turn(self): + #Ask mouse for position + board.make_turn(Point(get_pos()[0],get_pos()[1])) + + diff --git a/games/tic-tac-toe/server.py b/games/tic-tac-toe/server.py new file mode 100644 index 0000000..91e32b5 --- /dev/null +++ b/games/tic-tac-toe/server.py @@ -0,0 +1,23 @@ +#server.py +import json +from socket import socket, AF_INET, SOCK_STREAM + + +class server(object): + def __init__(self, port=None): + self.port = port + self.world = GGS.init() + self.socket = socket(AF_INET, SOCK_STREAM) + self.socket.connect(("www.???.com", 80)) + + def turn(self, id, index): + rows = sqrt(board.nr_of_rectangles) + x = int(index / rows) + y = int(index % rows) + + json.dumps({"x": x, "y": y} + world.callCommand("tictactoe", "set", json.dumps({"x": x, "y": y})) + + sent = 0 + length = len( + while sent diff --git a/games/tic-tac-toe/test_data.py b/games/tic-tac-toe/test_data.py new file mode 100644 index 0000000..38282f0 --- /dev/null +++ b/games/tic-tac-toe/test_data.py @@ -0,0 +1,14 @@ +import unittest +import data + + +class TestData(unittest.TestCase): + def setUp(self): + array = [0,1,1,1,3,4,5,2,2,3,3,3,3,3,33,4,2,2] + + self.assertTrue(data.greatest_sequence(array, 3) == 5) + +if __name__ == '__main__': + unittest.main() + + diff --git a/games/tic-tac-toe/tictactoeboard.py b/games/tic-tac-toe/tictactoeboard.py index ee1c057..10562dd 100644 --- a/games/tic-tac-toe/tictactoeboard.py +++ b/games/tic-tac-toe/tictactoeboard.py @@ -4,6 +4,7 @@ from point import Point from pygame.image import load from pygame.rect import Rect from pygame import Surface +from data import greatest_sequence #inherits Board. #Used for displaying the board on the screen and interact with it @@ -47,4 +48,14 @@ class TicTacToeBoard(Board): game_rectangle.state = 'o' self.players_turn = (self.players_turn + 1) % 2 + """ + def turn(self, mouse_point): + if player.id != players_turn: + print "Other players turn" + else: + for game_rectangle in self.game_rectangles: + if (mouse_point.inside(game_rectangle) and + game_rectangle.state == ' '): + server.turn(player.id, game_rectangle.index) + """ diff --git a/games/tic-tac-toe/tictactoeboard.pyc b/games/tic-tac-toe/tictactoeboard.pyc index 1243dc1..8913f16 100644 Binary files a/games/tic-tac-toe/tictactoeboard.pyc and b/games/tic-tac-toe/tictactoeboard.pyc differ diff --git a/mnesia/.gamedb.erl.swp b/mnesia/.gamedb.erl.swp new file mode 100644 index 0000000..469b1f8 Binary files /dev/null and b/mnesia/.gamedb.erl.swp differ diff --git a/Mnesia/gamedb.erl b/mnesia/gamedb.erl similarity index 50% rename from Mnesia/gamedb.erl rename to mnesia/gamedb.erl index 9d6bbbe..751eb92 100644 --- a/Mnesia/gamedb.erl +++ b/mnesia/gamedb.erl @@ -1,26 +1,45 @@ -%Test Mnesia +%%%%---------------------------------------------------- +%%% @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). -example_player() -> - #player{id = 0001, - name = "Tux"}. +%%----------------------------------------------------- +%% Querries +%%----------------------------------------------------- read_player(Player_Key) -> Fun = fun() -> [P] = mnesia:read(player, Player_Key), diff --git a/Mnesia/gamedb.hrl b/mnesia/gamedb.hrl similarity index 100% rename from Mnesia/gamedb.hrl rename to mnesia/gamedb.hrl diff --git a/Mnesia/gamedb_usage.txt b/mnesia/gamedb_usage.txt similarity index 100% rename from Mnesia/gamedb_usage.txt rename to mnesia/gamedb_usage.txt diff --git a/python_client b/python_client index e707115..3db0751 100755 --- a/python_client +++ b/python_client @@ -29,9 +29,9 @@ s.send( "Token: %s\n\ Server-Command: define\n\ Content-Type: text\n\ -Content-Length: 42\n\ +Content-Length: 49\n\ \n\ -function myFun() {return 'Hello world!' ;}" % token) +function myFun() {return 'Hello World!' ;}" % token) fs = s.makefile() data = fs.readline() print "Token:", token @@ -54,6 +54,8 @@ print "Data: ", ' '.join(data.split(" ")[1:]) s.close() +time.sleep(2) + HOST = 'localhost' # The remote host PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/python_client_reconnect b/python_client_reconnect new file mode 100755 index 0000000..2a41b70 --- /dev/null +++ b/python_client_reconnect @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +import sys, time, socket + +HOST = 'localhost' # The remote host +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)) +# Call that function! + +print "Calling myFun" +s.send( +"Token: %s\n\ +Server-Command: call\n\ +Content-Type: text\n\ +Content-Length: 6\n\ +\n\ +myFun" % raw_input("Token >> ")) +fs = s.makefile() +data = fs.readline() +print "Data: ", ' '.join(data.split(" ")[1:]) + +s.close() diff --git a/src/.ggs_connection.erl.swp b/src/.ggs_connection.erl.swp new file mode 100644 index 0000000..0c009f8 Binary files /dev/null and b/src/.ggs_connection.erl.swp differ diff --git a/src/ggs_network.erl b/src/ggs_network.erl new file mode 100644 index 0000000..be1b9d1 --- /dev/null +++ b/src/ggs_network.erl @@ -0,0 +1,170 @@ +%%%---------------------------------------------------- +%%% @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_server.erl b/src/ggs_server.erl index f8eae1e..ab9b8f8 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -90,8 +90,8 @@ handle_cast(stop, State) -> % Handle javascript defines handle_cast({srv_cmd, "define", Headers, Data}, State) -> Token = ggs_protocol:getToken(Headers), - JSVM = getJSVM(Token, State), - js_runner:define(JSVM, Data), + GameVM = getJSVM(Token, State), + ggs_vm_runner:define(GameVM, Data), send(State#state.lsock, "Token", "Okay, defined that for you!"), {noreply, State}; @@ -99,21 +99,21 @@ handle_cast({srv_cmd, "define", Headers, Data}, State) -> handle_cast({srv_cmd, "call", Headers, Data}, State) -> Token = ggs_protocol:getToken(Headers), io:format("Got call request: ~p~n", [Data]), - JSVM = getJSVM(Token, State), - erlang:display(erlang:port_info(JSVM)), - {ok, Ret} = js_runner:call(JSVM, Data, []),%Payload, []), + GameVM = getJSVM(Token, State), + Ret = ggs_vm_runner:user_command(GameVM, "User", Data, []), send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), {noreply, State}; - + % Set the new state to the reference generated, and JSVM associated handle_cast({srv_cmd, "hello", Headers, Data}, State) -> - JSVM = js_runner:boot(), + 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, JSVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), + NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]}, + gen_server:cast(ggs_backup, {set_backup, NewState}), {noreply, NewState}. + %%----------------------------------------------------- %% Helpers %%----------------------------------------------------- diff --git a/src/ggs_vm_runner.erl b/src/ggs_vm_runner.erl new file mode 100644 index 0000000..e149c51 --- /dev/null +++ b/src/ggs_vm_runner.erl @@ -0,0 +1,42 @@ +-module(ggs_vm_runner). +-export([start_link/0, define/2, user_command/4]). + +%Mattias +start_link() -> + erlang_js:start(), + 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. + + +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. + + +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}. + +user_command(GameVM, User, Command, Args) -> + Ref = make_ref(), + GameVM ! {user_command, User, Command, Args, self(), Ref}, + receive + {Ref, RetVal} -> + RetVal; + Other -> Other + end. diff --git a/src/js_runner.erl b/src/js_runner.erl deleted file mode 100644 index ca866c4..0000000 --- a/src/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).