n2o_game.erl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. -module(n2o_game).
  2. -author('Maxim Sokhatsky').
  3. -include_lib("n2o/include/wf.hrl").
  4. -export([init/4]).
  5. -export([stream/3]).
  6. -export([info/3]).
  7. -export([terminate/2]).
  8. -define(PERIOD, 1000).
  9. init(_Transport, Req, _Opts, _Active) ->
  10. put(actions,[]),
  11. Ctx = wf_context:init_context(Req),
  12. NewCtx = wf_core:fold(init,Ctx#context.handlers,Ctx),
  13. wf_context:context(NewCtx),
  14. Res = ets:update_counter(globals,onlineusers,{2,1}),
  15. wf:reg(broadcast,wf:peer(Req)),
  16. wf:send(broadcast,{counter,Res}),
  17. Req1 = wf:header(<<"Access-Control-Allow-Origin">>, <<"*">>, NewCtx#context.req),
  18. {ok, Req1, NewCtx}.
  19. %% {'KamfMessage',23,game_event,[{game,undefined},{event,okey_tile_taken},{args,[{player,<<"dusler">>},{pile,0},{revealed,null},{pile_height,43}]}]}
  20. is_proplist([]) -> true;
  21. is_proplist([{K,_}|L]) when is_atom(K) -> is_proplist(L);
  22. is_proplist(_) -> false.
  23. stream(<<"ping">>, Req, State) ->
  24. wf:info("ping received~n"),
  25. {reply, <<"pong">>, Req, State};
  26. stream({text,Data}, Req, State) ->
  27. wf:info("Text Received ~p",[Data]),
  28. self() ! Data,
  29. {ok, Req,State};
  30. stream({binary,Info}, Req, State) ->
  31. wf:info("Binary Received: ~p",[Info]),
  32. Pro = binary_to_term(Info,[safe]),
  33. wf:info("N2O Unknown Event: ~p",[Pro]),
  34. case Pro of
  35. {client,M} -> info({client,M},Req,State);
  36. _ ->
  37. Pickled = proplists:get_value(pickle,Pro),
  38. Linked = proplists:get_value(linked,Pro),
  39. Depickled = wf:depickle(Pickled),
  40. wf:info("Depickled: ~p",[Depickled]),
  41. case Depickled of
  42. #ev{module=Module,name=Function,payload=Parameter,trigger=Trigger} ->
  43. case Function of
  44. control_event -> lists:map(fun({K,V})-> put(K,V) end,Linked),
  45. Module:Function(Trigger, Parameter);
  46. api_event -> Module:Function(Parameter,Linked,State);
  47. event -> lists:map(fun({K,V})-> put(K,V) end,Linked),
  48. Module:Function(Parameter);
  49. UserCustomEvent -> Module:Function(Parameter,Trigger,State) end;
  50. _Ev -> wf:error("N2O allows only #ev{} events") end,
  51. Actions = get(actions),
  52. wf_context:clear_actions(),
  53. Render = wf:render(Actions),
  54. GenActions = get(actions),
  55. RenderGenActions = wf:render(GenActions),
  56. wf_context:clear_actions(),
  57. {reply, [Render,RenderGenActions], Req, State} end;
  58. stream(Data, Req, State) ->
  59. wf:info("Data Received ~p",[Data]),
  60. self() ! Data,
  61. {ok, Req,State}.
  62. render_actions(InitActions) ->
  63. RenderInit = wf:render(InitActions),
  64. InitGenActions = get(actions),
  65. RenderInitGenActions = wf:render(InitGenActions),
  66. wf_context:clear_actions(),
  67. [RenderInit,RenderInitGenActions].
  68. info({client,Message}, Req, State) ->
  69. wf:info("Client Message: ~p",[Message]),
  70. {reply,[],Req,State};
  71. info({send_message,Message}, Req, State) ->
  72. wf:info("Game Message: ~p",[Message]),
  73. Ret = io_lib:format("~p",[Message]),
  74. {reply,Ret,Req,State};
  75. info(Pro, Req, State) ->
  76. Render =
  77. case Pro of
  78. {flush,Actions} ->
  79. % wf:info("Comet Actions: ~p",[Actions]),
  80. wf:render(Actions);
  81. <<"N2O,",Rest/binary>> ->
  82. Module = State#context.module, Module:event(init),
  83. InitActions = get(actions),
  84. wf_context:clear_actions(),
  85. Pid = wf:depickle(Rest),
  86. %wf:info("Transition Pid: ~p",[Pid]),
  87. case Pid of
  88. undefined ->
  89. %wf:info("Path: ~p",[wf:path(Req)]),
  90. %wf:info("Module: ~p",[Module]),
  91. Elements = try Module:main() catch C:E -> wf:error_page(C,E) end,
  92. wf_core:render(Elements),
  93. render_actions(InitActions);
  94. Transition ->
  95. X = Pid ! {'N2O',self()},
  96. R = receive Actions -> [ render_actions(InitActions) | wf:render(Actions) ]
  97. after 100 ->
  98. QS = element(14, Req),
  99. wf:redirect(case QS of <<>> -> ""; _ -> "" ++ "?" ++ wf:to_list(QS) end),
  100. []
  101. end,
  102. R
  103. end;
  104. <<"PING">> -> [];
  105. Unknown ->
  106. wf:info("Unknown WS Info Message ~p", [Unknown]),
  107. M = State#context.module,
  108. catch M:event(Unknown),
  109. Actions = get(actions),
  110. wf_context:clear_actions(),
  111. wf:render(Actions) end,
  112. GenActions = get(actions),
  113. wf_context:clear_actions(),
  114. RenderGenActions = wf:render(GenActions),
  115. wf_context:clear_actions(),
  116. {reply, [Render,RenderGenActions], Req, State}.
  117. terminate(_Req, _State=#context{module=Module}) ->
  118. % wf:info("Bullet Terminated~n"),
  119. Res = ets:update_counter(globals,onlineusers,{2,-1}),
  120. wf:send(broadcast,{counter,Res}),
  121. catch Module:event(terminate),
  122. ok.