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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
function dump(x, idt)
local p = {}
local idt = idt or 0
for k, v in pairs(x) do
local s
if type(v) == "table" then
s = dump(v, idt+1)
elseif type(v) == "string" then
s = ("\"%s\""):format(v)
else
s = tostring(v)
end
table.insert(p, ("%s%s = %s"):format((" "):rep(4*(idt+1)), k, s))
end
return ("{\n%s\n%s}"):format(table.concat(p, ", \n"), (" "):rep(4*idt))
end
local client = require("client")
local server = require("server")
local main_menu = require("main_menu")
local ui = require("ui")
local color = ui.color
local clt
local dialog = {}
local last_status, last_info
local function show(dg, ...)
dialog.active = dg
if dg.show then
dg:show(...)
end
end
local function connect(invite)
local c, err = client.join(invite)
if err then
show(dialog.error, "Invalid invite")
else
clt = c
end
end
local function disconnect(msg)
client.close(clt)
clt = nil
last_status = nil
if msg then
show(dialog.error, msg)
else
show(dialog.main_menu, msg)
end
end
local function select_player(name, create)
client.select_player(clt, name, create)
show(dialog.loading, "Joining Lobby...")
end
local function update_client()
client.update(clt)
local status = client.status(clt)
if status == "timeout_match" then
disconnect("Failed to connect to match server (match server down?)")
elseif status == "fail_match" then
disconnect("Game not found (invalid invite?)")
elseif status == "timeout_server" then
disconnect("Failed to connect to server (NAT punch failure?)")
elseif status == "fail_server" then
disconnect("Incorrect secret (invalid invite?)")
elseif status == "disco" then
disconnect("Lost connection to server (Server shut down?)")
elseif status ~= last_status then
if status == "active" then
show(dialog.loading, "Waiting for info...")
elseif status == "wait_match" then
show(dialog.loading, "Waiting for match server...")
elseif status == "wait_server" then
show(dialog.loading, "Waiting for server...")
end
end
if not clt then return end
if clt.player_error then
show(dialog.error, clt.player_error, dialog.select_player)
clt.player_error = nil
elseif clt.player and (not in_lobby or (in_lobby and last_info ~= clt.info)) then
show(dialog.lobby)
elseif not clt.player and last_info ~= clt.info and (not last_info or dialog.active == dialog.select_player) then
show(dialog.select_player)
end
last_info = clt.info
last_status = status
end
local function create_dialog_box(title, elem, width)
return ui.new(ui.center_y(ui.stack_x(
ui.flex(1),
ui.flex(width or 2, main_menu.box(title, elem)),
ui.flex(1)
)))
end
local function create_info_box(title, action_name, action, show)
local box = main_menu.box(title, ui.button(action_name, action))
local dg = ui.new(ui.center_x(ui.center_y(box)))
function dg.set_title(self, x)
box.box_title.text:set(x)
end
dg.show = show
return dg
end
local function create_loading()
return create_info_box("Loading...", "Cancel",
function() disconnect() end,
function(self, msg)
self:set_title(msg)
end
)
end
local function create_error()
local back_menu
return create_info_box("Error", "Back",
function()
show(back_menu or dialog.main_menu)
end,
function(self, msg, back)
self:set_title(msg)
back_menu = back
end
)
end
local function create_player_indicator(player, text_size)
local name = player.name
if clt and clt.player == player.name then
name = name .. " [YOU]"
end
local text = ui.text(name, text_size, color(0x000000))
local status_size = text.text:getHeight()-10
return ui.stack_x(
ui.center_y({
fill = player.active and color(0x23cf3a) or color(0xc21b3a),
size = { x = status_size, y = status_size }
}),
ui.pad_x(10),
text
)
end
local function create_select_player()
local contents = {}
local dg = create_dialog_box("Select Player", contents)
dg.show = function()
local stack = ui.stack_y()
for _, p in ipairs(clt.info.players) do
local button = ui.button_elem(create_player_indicator(p, 25), function()
if not p.active then
select_player(p.name, false)
end
end)
button.line = nil
if p.active then
button.fill_normal = color(0x122194)
button.fill_hover = color(0x122194)
else
button.fill_normal = color(0x223ebd)
button.fill_hover = color(0x2d95d6)
end
table.insert(stack, button)
end
local create = ui.button("+", function()
show(dialog.create_player)
end)
create.line = nil
create.fill_normal = color(0x7e1dbf)
create.fill_hover = color(0x9540cf)
table.insert(stack, create)
contents[1] = stack
end
return dg
end
local function create_create_player()
local input = ui.input("Player name")
return create_dialog_box("Create Player", ui.stack_y(
input,
ui.pad_y(10),
ui.pad_x(10,
ui.button("Back", function()
show(dialog.select_player)
end),
ui.flex(1, ui.button("Create", function()
if input.input_value ~= "" then
select_player(input.input_value, true)
end
end))
)
))
end
local function create_lobby()
local player_list = {}
local dg = create_dialog_box("Lobby", ui.stack_y(
player_list,
ui.center_x(ui.button("Disconnect", function()
disconnect()
end))
), 3)
function dg.show(self)
local players = ui.stack_y()
for _, p in ipairs(clt.info.players) do
table.insert(players, create_player_indicator(p, 20))
end
player_list[1] = players
end
return dg
end
function love.load()
love.graphics.setBackgroundColor(color(0xffffff))
love.window.setTitle("RAINBOW SIX: PANOPTICON")
dialog.main_menu = main_menu.create({ join_game = connect })
dialog.loading = create_loading()
dialog.error = create_error()
dialog.create_player = create_create_player()
dialog.select_player = create_select_player()
dialog.lobby = create_lobby()
show(dialog.main_menu)
end
function love.mousepressed(x, y, button)
if dialog.active then
ui.mousepressed(dialog.active, x, y, button)
end
end
function love.mousereleased(x, y, button)
if dialog.active then
ui.mousereleased(dialog.active, x, y, button)
end
end
function love.textinput(text)
if dialog.active then
ui.textinput(dialog.active, text)
end
end
function love.keypressed(key)
if dialog.active then
ui.keypressed(dialog.active, key)
end
end
function love.update()
if clt then
update_client()
end
end
function love.draw()
if dialog.active then
ui.update(dialog.active)
ui.render(dialog.active)
end
end
function love.quit()
print("shutting down")
if clt then
client.close(clt)
end
end
|