/
session.ex
172 lines (145 loc) · 3.55 KB
/
session.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
defmodule Game.Session do
@moduledoc """
Client access to the `Game.Session.Process` GenServer.
"""
@type t :: pid
alias Data.User
alias Game.Character
alias Game.Session
alias Game.Session.Supervisor
alias Game.World.Master, as: WorldMaster
@doc """
Start a new session
Creates a session pointing at a socket
"""
@spec start(pid) :: {:ok, pid}
def start(socket) do
Supervisor.start_child(socket)
end
@doc """
Start a new session that is signed in
Creates a session pointing at a socket
"""
@spec start_with_user(pid, integer()) :: {:ok, pid}
def start_with_user(socket, nil), do: start(socket)
def start_with_user(socket, user_id) do
Supervisor.start_child(socket, user_id)
end
@doc """
Send a disconnect signal to a session
"""
@spec disconnect(pid) :: :ok
def disconnect(pid) do
GenServer.cast(pid, :disconnect)
end
@doc """
Send a disconnect signal to a session with options
"""
@spec disconnect(pid, Keyword.t()) :: :ok
def disconnect(pid, opts) do
GenServer.cast(pid, {:disconnect, opts})
end
@doc """
Send a recv signal from the socket
"""
@spec recv(pid, String.t()) :: :ok
def recv(pid, message) do
GenServer.cast(pid, {:recv, message})
end
@doc """
Receive a GMCP request from the client
"""
@spec recv_gmcp(pid(), String.t(), map()) :: :ok
def recv_gmcp(pid, module, data \\ %{}) do
GenServer.cast(pid, {:recv_gmcp, module, data})
end
@doc """
Echo to the socket
"""
@spec echo(pid, String.t()) :: :ok
def echo(user = %User{}, message) do
case find_connected_player(user) do
nil ->
:ok
%{pid: pid} ->
echo(pid, message)
end
end
def echo(user = %Character.Simple{type: :user}, message) do
case find_connected_player(user) do
nil ->
:ok
%{pid: pid} ->
echo(pid, message)
end
end
def echo(pid, message) do
GenServer.cast(pid, {:echo, message})
end
@doc """
Send a tick to the session
"""
@spec tick(pid, DateTime.t()) :: :ok
def tick(pid, time) do
GenServer.cast(pid, {:tick, time})
end
@doc """
Notify the session of an event, e.g. someone left the room
"""
@spec notify(pid, tuple()) :: :ok
def notify(user = %User{}, action) do
case find_connected_player(user) do
nil ->
:ok
%{pid: pid} ->
notify(pid, action)
end
end
def notify(user = %Character.Simple{type: :user}, action) do
case find_connected_player(user) do
nil ->
:ok
%{pid: pid} ->
notify(pid, action)
end
end
def notify(pid, action) do
GenServer.cast(pid, {:notify, action})
end
@doc """
Teleport the user to the room passed in
"""
@spec teleport(pid, integer) :: :ok
def teleport(pid, room_id) do
GenServer.cast(pid, {:teleport, room_id})
end
@doc """
Sign in a user to a session, from the web client
"""
@spec sign_in(pid(), User.t()) :: :ok
def sign_in(pid, user) do
case WorldMaster.is_world_online?() do
true ->
GenServer.cast(pid, {:sign_in, user.id})
false ->
:ok
end
end
@doc """
Room crashed, rejoin if necessary
"""
@spec room_crashed(integer(), integer()) :: :ok
def room_crashed(pid, room_id) do
GenServer.cast(pid, {:room_crashed, room_id})
end
@doc """
Find a connected user by their user struct
"""
@spec find_connected_player(User.t()) :: pid()
def find_connected_player(user) do
Session.Registry.connected_players()
|> Enum.find(fn %{user: player} ->
player.id == user.id
end)
end
end