Created
December 7, 2016 08:51
-
-
Save landongn/9dac005a4ec440a8d5d884a7165f3d32 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Server.CharacterChannel do | |
use Server.Web, :channel | |
alias Phoenix.View | |
alias Server.CharacterView | |
alias Server.Repo | |
alias Server.Player | |
alias Server.Character | |
alias Ecto.Query | |
def join("character", _payload, socket) do | |
{:ok, socket} | |
end | |
def handle_in("game.zone.character.list", _, socket) do | |
q = Character | |
|> Query.where(player_id: ^socket.user_id) | |
results = Repo.all(q) | |
push socket, "msg", %{ | |
opcode: "game.zone.character.list", | |
characters: results, | |
message: View.render_to_string(CharacterView, "character-list.html", %{characters: results}) | |
} | |
{:noreply, socket} | |
end | |
def handle_in("game.zone.character.create", payload, socket) do | |
{:noreply, socket} | |
end | |
def handle_in("game.zone.character.new", payload, socket) do | |
{:noreply, socket} | |
end | |
def handle_in("game.zone.character.delete", payload, socket) do | |
{:noreply, socket} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[error] GenServer #PID<0.400.0> terminating | |
** (KeyError) key :user_id not found in: %Phoenix.Socket{assigns: %{}, channel: Server.CharacterChannel, channel_pid: #PID<0.400.0>, endpoint: Server.Endpoint, handler: Server.UserSocket, id: nil, joined: true, pubsub_server: Server.PubSub, ref: "15", serializer: Phoenix.Transports.WebSocketSerializer, topic: "character", transport: Phoenix.Transports.WebSocket, transport_name: :websocket, transport_pid: #PID<0.396.0>} | |
(server) web/channels/character_channel.ex:17: Server.CharacterChannel.handle_in/3 | |
(phoenix) lib/phoenix/channel/server.ex:226: anonymous fn/4 in Phoenix.Channel.Server.handle_info/2 | |
(stdlib) gen_server.erl:601: :gen_server.try_dispatch/4 | |
(stdlib) gen_server.erl:667: :gen_server.handle_msg/5 | |
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3 | |
Last message: %Phoenix.Socket.Message{event: "game.zone.character.list", payload: %{}, ref: "15", topic: "character"} | |
State: %Phoenix.Socket{assigns: %{}, channel: Server.CharacterChannel, channel_pid: #PID<0.400.0>, endpoint: Server.Endpoint, handler: Server.UserSocket, id: nil, joined: true, pubsub_server: Server.PubSub, ref: nil, serializer: Phoenix.Transports.WebSocketSerializer, topic: "character", transport: Phoenix.Transports.WebSocket, transport_name: :websocket, transport_pid: #PID<0.396.0>} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Server.UserSocket do | |
use Phoenix.Socket | |
## Channels | |
channel "zone", Server.ZoneChannel | |
channel "world:system", Server.WorldChannel | |
channel "messaging", Server.MessagingChannel | |
channel "combat", Server.CombatChannel | |
channel "forest", Server.ForestChannel | |
channel "village", Server.VillageChannel | |
channel "character", Server.CharacterChannel | |
## Transports | |
transport :websocket, Phoenix.Transports.WebSocket | |
# Socket params are passed from the client and can | |
# be used to verify and authenticate a user. After | |
# verification, you can put default assigns into | |
# the socket that will be set for all channels, ie | |
#[] | |
# {:ok, assign(socket, :user_id, verified_user_id)} | |
# | |
# To deny connection, return `:error`. | |
# | |
# See `Phoenix.Token` documentation for examples in | |
# performing token verification on connect. | |
def connect(_params, socket) do | |
{:ok, socket} | |
end | |
# Socket id's are topics that allow you to identify all sockets for a given user: | |
# | |
# def id(socket), do: "users_socket:#{socket.assigns.user_id}" | |
# | |
# Would allow you to broadcast a "disconnect" event and terminate | |
# all active sockets and channels for a given user: | |
# | |
# Server.Endpoint.broadcast("users_socket:#{user.id}", "disconnect", %{}) | |
# | |
# Returning `nil` makes this socket anonymous. | |
def id(_socket), do: nil | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Server.WorldChannel do | |
use Server.Web, :channel | |
require Logger | |
require Comeonin.Bcrypt | |
alias Server.Player | |
alias Phoenix.View | |
alias Server.WorldView | |
alias Server.CharacterView | |
alias Server.Auth | |
def join("world:system", _, socket) do | |
msg = View.render_to_string(WorldView, "welcome_message.html", %{}) | |
{:ok, %{message: msg, opcode: "game.client.connect", actions: ["enter"]}, socket} | |
end | |
def handle_in("motd", _, socket) do | |
msg = View.render_to_string(WorldView, "motd.html", %{}) | |
push socket, "msg", %{message: msg, opcode: "game.client.motd", actions: ["enter"]} | |
{:noreply, socket} | |
end | |
def handle_in("ident", _, socket) do | |
push socket, "msg", %{ | |
message: View.render_to_string(WorldView, "auth_challenge.html", %{}), | |
opcode: "game.client.ident-challenge", | |
actions: ["e"] | |
} | |
{:noreply, socket} | |
end | |
def handle_in("email-ident", _, socket) do | |
push socket, "msg", %{ | |
message: View.render_to_string(WorldView, "auth-email.html", %{}), | |
opcode: "game.client.ident-email", | |
actions: ["enter"] | |
} | |
{:noreply, socket} | |
end | |
def handle_in("email-identify", %{"email" => payload}, socket) do | |
case Server.Repo.get_by Player, email: payload do | |
record when record != nil -> | |
push socket, "msg", %{ | |
message: View.render_to_string(WorldView, "password.html", record), | |
opcode: "game.client.ident.validuser" | |
} | |
nil -> | |
push socket, "msg", %{ | |
message: View.render_to_string(WorldView, "user-not-found.html", %{email: payload}), | |
opcode: "game.client.ident.notfound", | |
actions: ["enter"] | |
} | |
end | |
{:noreply, socket} | |
end | |
def handle_in("password-identify", %{"password" => password, "email" => email}, socket) do | |
case Server.Repo.get_by Player, email: email do | |
player when player != nil -> | |
case Comeonin.Bcrypt.checkpw(password, player.password) do | |
true -> | |
token = Phoenix.Token.sign(Server.Endpoint, "player_id", player.id) | |
updated = Ecto.Changeset.change player, secret: token | |
Server.Repo.update updated | |
assign(socket, :user_id, player.id) | |
assign(socket, :token, token) | |
push socket, "data", %{ | |
opcode: 'game.client.session.create', | |
token: token, | |
user_id: player.id | |
} | |
push socket, "msg", %{ | |
message: View.render_to_string(CharacterView, "character-select.html", %{}), | |
opcode: "game.zone.character.select", | |
actions: [] | |
} | |
_ -> | |
push socket, "msg", %{ | |
message: View.render_to_string(WorldView, "auth_challenge.html", %{}), | |
opcode: "game.client.ident-challenge", | |
actions: ["e"] | |
} | |
end | |
nil -> | |
changeset = Player.changeset(%Player{}, %{ | |
email: email, password: Comeonin.Bcrypt.hashpwsalt(password) | |
}) | |
case changeset.valid? do | |
true -> | |
case Server.Repo.insert(changeset) do | |
{:ok, player} -> | |
token = Phoenix.Token.sign(Server.Endpoint, "player_id", player.id) | |
updated = Ecto.Changeset.change player, secret: token | |
Server.Repo.update updated | |
assign(socket, :user_id, player.id) | |
assign(socket, :token, token) | |
push socket, "data", %{ | |
opcode: 'game.client.session.create', | |
token: token, | |
user_id: player.id, | |
} | |
push socket, "msg", %{ | |
message: View.render_to_string(CharacterView, "character-select.html", %{}), | |
opcode: "game.zone.character.select", | |
actions: [] | |
} | |
{:error, changeset} -> | |
push socket, "msg", %{opcode: "game.client.ident.error"} | |
end | |
false -> | |
push socket, "msg", %{ | |
opcode: "game.client.ident.bad-password", | |
message: "That password didn't work. Sorry.", | |
actions: [] | |
} | |
end | |
end | |
{:noreply, socket} | |
end | |
# # Channels can be used in a request/response fashion | |
# # by sending replies to requests from the client | |
# def handle_in("ping", payload, socket) do | |
# {:reply, {:ok, payload}, socket} | |
# end | |
# # It is also common to receive messages from the client and | |
# # broadcast to everyone in the current topic (world:lobby). | |
# def handle_in("shout", payload, socket) do | |
# broadcast socket, "shout", payload | |
# {:noreply, socket} | |
# end | |
# Add authorization logic here as required. | |
# defp authorized?(_payload) do | |
# true | |
# end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment