merge
This commit is contained in:
commit
0718031e22
10 changed files with 3251 additions and 4 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit aad268d03a3c23de917cfecf767d583d3cb32633
|
Subproject commit 00312859714bef6e9a4fdb9931a41fef56eeb89a
|
7
games/Pong/Pong.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
games/Pong/Pong.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:Pong.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
2937
games/Pong/Pong.xcodeproj/project.xcworkspace/xcuserdata/jeena.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
2937
games/Pong/Pong.xcodeproj/project.xcworkspace/xcuserdata/jeena.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
|
||||||
|
BuildableName = "Pong.app"
|
||||||
|
BlueprintName = "Pong"
|
||||||
|
ReferencedContainer = "container:Pong.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||||
|
displayScaleIsEnabled = "NO"
|
||||||
|
displayScale = "1.00"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
<BuildableProductRunnable>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
|
||||||
|
BuildableName = "Pong.app"
|
||||||
|
BlueprintName = "Pong"
|
||||||
|
ReferencedContainer = "container:Pong.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
displayScaleIsEnabled = "NO"
|
||||||
|
displayScale = "1.00"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
buildConfiguration = "Release">
|
||||||
|
<BuildableProductRunnable>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
|
||||||
|
BuildableName = "Pong.app"
|
||||||
|
BlueprintName = "Pong"
|
||||||
|
ReferencedContainer = "container:Pong.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>Pong.xcscheme</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>1D6058900D05DD3D006BFB54</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -60,7 +60,8 @@ while True:
|
||||||
|
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
"""
|
time.sleep(2)
|
||||||
|
|
||||||
HOST = 'localhost' # The remote host
|
HOST = 'localhost' # The remote host
|
||||||
PORT = int(sys.argv[1]) # The same port as used by the server
|
PORT = int(sys.argv[1]) # The same port as used by the server
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
@ -81,4 +82,3 @@ print "Token:", token
|
||||||
print "Data: ", ' '.join(data.split(" ")[1:])
|
print "Data: ", ' '.join(data.split(" ")[1:])
|
||||||
|
|
||||||
s.close()
|
s.close()
|
||||||
"""
|
|
||||||
|
|
23
python_client_reconnect
Executable file
23
python_client_reconnect
Executable file
|
@ -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()
|
|
@ -25,7 +25,6 @@ create_message(Cmd, Enc, Acc, Data) ->
|
||||||
Data,
|
Data,
|
||||||
Msg.
|
Msg.
|
||||||
|
|
||||||
|
|
||||||
%% Internal helpers
|
%% Internal helpers
|
||||||
do_parse(Data, ParsedMessage) ->
|
do_parse(Data, ParsedMessage) ->
|
||||||
NewLinePos = string:chr(Data, $\n),
|
NewLinePos = string:chr(Data, $\n),
|
||||||
|
|
141
src/ggs_server.erl
Normal file
141
src/ggs_server.erl
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
-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({srv_cmd, "define", Headers, Data}, State) ->
|
||||||
|
Token = ggs_protocol:getToken(Headers),
|
||||||
|
GameVM = getJSVM(Token, State),
|
||||||
|
ggs_vm_runner:define(GameVM, Data),
|
||||||
|
send(State#state.lsock, "Token", "Okay, defined that for you!"),
|
||||||
|
{noreply, State};
|
||||||
|
|
||||||
|
% Handle javascript calls
|
||||||
|
handle_cast({srv_cmd, "call", Headers, Data}, State) ->
|
||||||
|
Token = ggs_protocol:getToken(Headers),
|
||||||
|
io:format("Got call request: ~p~n", [Data]),
|
||||||
|
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({server, hello, Headers}, State) ->
|
||||||
|
handle_cast({srv_cmd, "hello", Headers, Data}, State) ->
|
||||||
|
GameToken = case proplist:get_value(game_token, Headers) of ->
|
||||||
|
undefined -> getNewToken();
|
||||||
|
GT -> GT;
|
||||||
|
end,
|
||||||
|
ClientToken = getNewToken(),
|
||||||
|
OldMap = State#state.client_vm_map,
|
||||||
|
NewState = State#state{client_vm_map = OldMap ++ [{ClientToken, GameVM, GameToken}]},
|
||||||
|
gen_server:cast(ggs_backup, {set_backup, NewState}),
|
||||||
|
{noreply, NewState}.
|
||||||
|
|
||||||
|
|
||||||
|
%%-----------------------------------------------------
|
||||||
|
%% Helpers
|
||||||
|
%%-----------------------------------------------------
|
||||||
|
getNewToken() ->
|
||||||
|
string:strip(os:cmd("uuidgen"), right, $\n ).
|
||||||
|
|
||||||
|
getJSVM(ClientToken, State) ->
|
||||||
|
VMs = State#state.client_vm_map,
|
||||||
|
{value, {_,VM}} = lists:keysearch(ClientToken, 1, VMs),
|
||||||
|
VM.
|
||||||
|
|
||||||
|
getGameVMByGameToken(GameToken, State) ->
|
||||||
|
VMs = State#state.client_vm_map,
|
||||||
|
{value, {_,VM}} = lists:keysearch(GameToken, 3, 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"], " ")).
|
42
src/ggs_vm_runner.erl
Normal file
42
src/ggs_vm_runner.erl
Normal file
|
@ -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.
|
Reference in a new issue