-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathconfig.ru
More file actions
executable file
·146 lines (116 loc) · 2.37 KB
/
Copy pathconfig.ru
File metadata and controls
executable file
·146 lines (116 loc) · 2.37 KB
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
#!/usr/bin/env -S falcon serve --count 1 --bind http://127.0.0.1:7070 -c
# frozen_string_literal: true
require "async/websocket/adapters/rack"
class Room
def initialize(name, description = nil)
@name = name
@description = description
@actions = {}
@users = []
end
attr :name
attr :description
attr :actions
def connect(key, room)
@actions[key] = lambda do |user|
self.exit(user)
room.enter(user)
end
return room
end
def broadcast(message)
@users.each do |user|
user.write(message)
user.flush
end
end
def enter(user)
user.notify("You have entered the #{@name}.")
user.room = self
@users << user
@users.each do |user|
user.notify("#{user.name} entered the room.")
end
end
def exit(user)
if @users.delete(user)
@users.each do |user|
user.notify("#{user.name} left the room.")
end
end
end
def as_json
{
name: @name,
description: @description,
actions: @actions.keys,
}
end
end
module Command
def self.split(line)
line.scan(/(?:"")|(?:"(.*[^\\])")|(\w+)/).flatten.compact
end
end
class User < Async::WebSocket::Connection
def initialize(*)
super
@name = name
@room = nil
@inventory = []
end
attr_accessor :room
ANONYMOUS = "Anonymous"
def name
@name || ANONYMOUS
end
def send_message(value)
self.write(Protocol::WebSocket::TextMessage.generate(value))
end
def handle(message)
key, *arguments = Command.split(message.parse[:input])
case key
when "name"
@name = arguments.first
when "look"
self.send_message({room: @room.as_json})
else
if action = @room.actions[key]
action.call(self, *arguments)
else
@room.broadcast(message)
end
end
end
def notify(text)
self.send_message({notify: text})
self.flush
end
def close
if @room
@room.exit(self)
end
super
end
end
class Server
def initialize(app)
@app = app
@entrance = Room.new("Portal", "A vast entrance foyer with a flowing portal.")
@entrance.connect("forward", Room.new("Training Room"))
@entrance.connect("corridor", Room.new("Shop"))
end
def call(env)
Async::WebSocket::Adapters::Rack.open(env, handler: User) do |user|
@entrance.enter(user)
while message = user.read
user.handle(message)
end
ensure
# Console.error(self, $!) if $!
user.close
end or @app.call(env)
end
end
use Server
run lambda{|env| [200, {}, []]}