author | unc0rr |
Mon, 10 Dec 2018 22:44:46 +0100 | |
changeset 14436 | 06672690d71b |
parent 14413 | gameServer2/src/server/handlers/inroom.rs@e335b3120f59 |
child 14478 | 98ef2913ec73 |
permissions | -rw-r--r-- |
12147 | 1 |
use mio; |
2 |
||
13666 | 3 |
use crate::{ |
4 |
server::{ |
|
13709
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
5 |
coretypes::{ |
13775 | 6 |
ClientId, RoomId, Voting, VoteType, GameCfg, |
13709
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
7 |
MAX_HEDGEHOGS_PER_TEAM |
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
8 |
}, |
14395 | 9 |
core::HWServer, |
13666 | 10 |
room::{HWRoom, RoomFlags}, |
11 |
actions::{Action, Action::*} |
|
12 |
}, |
|
13 |
protocol::messages::{ |
|
14 |
HWProtocolMessage, |
|
15 |
HWServerMessage::*, |
|
16 |
server_chat |
|
17 |
}, |
|
18 |
utils::is_name_illegal |
|
13416 | 19 |
}; |
13529 | 20 |
use std::{ |
14413 | 21 |
mem::swap |
13529 | 22 |
}; |
13423 | 23 |
use base64::{encode, decode}; |
13492 | 24 |
use super::common::rnd_reply; |
13810 | 25 |
use log::*; |
13423 | 26 |
|
27 |
#[derive(Clone)] |
|
28 |
struct ByMsg<'a> { |
|
29 |
messages: &'a[u8] |
|
30 |
} |
|
31 |
||
32 |
impl <'a> Iterator for ByMsg<'a> { |
|
33 |
type Item = &'a[u8]; |
|
34 |
||
35 |
fn next(&mut self) -> Option<<Self as Iterator>::Item> { |
|
36 |
if let Some(size) = self.messages.get(0) { |
|
37 |
let (msg, next) = self.messages.split_at(*size as usize + 1); |
|
38 |
self.messages = next; |
|
39 |
Some(msg) |
|
40 |
} else { |
|
41 |
None |
|
42 |
} |
|
43 |
} |
|
44 |
} |
|
45 |
||
13500 | 46 |
fn by_msg(source: &[u8]) -> ByMsg { |
47 |
ByMsg {messages: source} |
|
13423 | 48 |
} |
49 |
||
50 |
const VALID_MESSAGES: &[u8] = |
|
51 |
b"M#+LlRrUuDdZzAaSjJ,NpPwtgfhbc12345\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A"; |
|
52 |
const NON_TIMED_MESSAGES: &[u8] = b"M#hb"; |
|
53 |
||
13429 | 54 |
#[cfg(canhazslicepatterns)] |
13423 | 55 |
fn is_msg_valid(msg: &[u8], team_indices: &[u8]) -> bool { |
13424 | 56 |
match msg { |
57 |
[size, typ, body..] => VALID_MESSAGES.contains(typ) |
|
58 |
&& match body { |
|
13709
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
59 |
[1...MAX_HEDGEHOGS_PER_TEAM, team, ..] if *typ == b'h' => |
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
60 |
team_indices.contains(team), |
13423 | 61 |
_ => *typ != b'h' |
13424 | 62 |
}, |
63 |
_ => false |
|
13423 | 64 |
} |
65 |
} |
|
66 |
||
13666 | 67 |
fn is_msg_valid(msg: &[u8], _team_indices: &[u8]) -> bool { |
13429 | 68 |
if let Some(typ) = msg.get(1) { |
69 |
VALID_MESSAGES.contains(typ) |
|
70 |
} else { |
|
71 |
false |
|
72 |
} |
|
73 |
} |
|
74 |
||
13423 | 75 |
fn is_msg_empty(msg: &[u8]) -> bool { |
13429 | 76 |
msg.get(1).filter(|t| **t == b'+').is_some() |
13423 | 77 |
} |
12147 | 78 |
|
13443 | 79 |
fn is_msg_timed(msg: &[u8]) -> bool { |
80 |
msg.get(1).filter(|t| !NON_TIMED_MESSAGES.contains(t)).is_some() |
|
81 |
} |
|
82 |
||
13460 | 83 |
fn voting_description(kind: &VoteType) -> String { |
84 |
format!("New voting started: {}", match kind { |
|
85 |
VoteType::Kick(nick) => format!("kick {}", nick), |
|
86 |
VoteType::Map(name) => format!("map {}", name.as_ref().unwrap()), |
|
87 |
VoteType::Pause => "pause".to_string(), |
|
88 |
VoteType::NewSeed => "new seed".to_string(), |
|
89 |
VoteType::HedgehogsPerTeam(number) => format!("hedgehogs per team: {}", number) |
|
90 |
}) |
|
91 |
} |
|
92 |
||
13494 | 93 |
fn room_message_flag(msg: &HWProtocolMessage) -> RoomFlags { |
13666 | 94 |
use crate::protocol::messages::HWProtocolMessage::*; |
13494 | 95 |
match msg { |
96 |
ToggleRestrictJoin => RoomFlags::RESTRICTED_JOIN, |
|
97 |
ToggleRestrictTeams => RoomFlags::RESTRICTED_TEAM_ADD, |
|
98 |
ToggleRegisteredOnly => RoomFlags::RESTRICTED_UNREGISTERED_PLAYERS, |
|
99 |
_ => RoomFlags::empty() |
|
100 |
} |
|
101 |
} |
|
102 |
||
13492 | 103 |
pub fn handle(server: &mut HWServer, client_id: ClientId, room_id: RoomId, message: HWProtocolMessage) { |
13666 | 104 |
use crate::protocol::messages::HWProtocolMessage::*; |
12147 | 105 |
match message { |
13419 | 106 |
Part(None) => server.react(client_id, vec![ |
13416 | 107 |
MoveToLobby("part".to_string())]), |
13419 | 108 |
Part(Some(msg)) => server.react(client_id, vec![ |
13416 | 109 |
MoveToLobby(format!("part: {}", msg))]), |
110 |
Chat(msg) => { |
|
13419 | 111 |
let actions = { |
112 |
let c = &mut server.clients[client_id]; |
|
13500 | 113 |
let chat_msg = ChatMsg {nick: c.nick.clone(), msg}; |
13492 | 114 |
vec![chat_msg.send_all().in_room(room_id).but_self().action()] |
13419 | 115 |
}; |
116 |
server.react(client_id, actions); |
|
13416 | 117 |
}, |
13447 | 118 |
Fix => { |
119 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
13494 | 120 |
if c.is_admin() { r.set_is_fixed(true) } |
13447 | 121 |
} |
122 |
} |
|
123 |
Unfix => { |
|
124 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
13494 | 125 |
if c.is_admin() { r.set_is_fixed(false) } |
13447 | 126 |
} |
127 |
} |
|
128 |
Greeting(text) => { |
|
129 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
13494 | 130 |
if c.is_admin() || c.is_master() && !r.is_fixed() { |
13447 | 131 |
r.greeting = text |
132 |
} |
|
133 |
} |
|
134 |
} |
|
13416 | 135 |
RoomName(new_name) => { |
136 |
let actions = |
|
137 |
if is_name_illegal(&new_name) { |
|
138 |
vec![Warn("Illegal room name! A room name must be between 1-40 characters long, must not have a trailing or leading space and must not have any of these characters: $()*+?[]^{|}".to_string())] |
|
13520 | 139 |
} else if server.rooms[room_id].is_fixed() { |
13447 | 140 |
vec![Warn("Access denied.".to_string())] |
13416 | 141 |
} else if server.has_room(&new_name) { |
142 |
vec![Warn("A room with the same name already exists.".to_string())] |
|
143 |
} else { |
|
144 |
let mut old_name = new_name.clone(); |
|
13520 | 145 |
swap(&mut server.rooms[room_id].name, &mut old_name); |
146 |
vec![SendRoomUpdate(Some(old_name))] |
|
13416 | 147 |
}; |
13419 | 148 |
server.react(client_id, actions); |
149 |
}, |
|
150 |
ToggleReady => { |
|
13666 | 151 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
13486 | 152 |
let flags = if c.is_ready() { |
13419 | 153 |
r.ready_players_number -= 1; |
154 |
"-r" |
|
155 |
} else { |
|
156 |
r.ready_players_number += 1; |
|
157 |
"+r" |
|
158 |
}; |
|
13775 | 159 |
|
160 |
let msg = if c.protocol_number < 38 { |
|
161 |
LegacyReady(c.is_ready(), vec![c.nick.clone()]) |
|
162 |
} else { |
|
163 |
ClientFlags(flags.to_string(), vec![c.nick.clone()]) |
|
164 |
}; |
|
165 |
||
166 |
let mut v = vec![msg.send_all().in_room(r.id).action()]; |
|
167 |
||
13494 | 168 |
if r.is_fixed() && r.ready_players_number == r.players_number { |
13447 | 169 |
v.push(StartRoomGame(r.id)) |
170 |
} |
|
13775 | 171 |
|
172 |
c.set_is_ready(!c.is_ready()); |
|
13666 | 173 |
server.react(client_id, v); |
174 |
} |
|
13416 | 175 |
} |
13422 | 176 |
AddTeam(info) => { |
13419 | 177 |
let mut actions = Vec::new(); |
178 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
179 |
if r.teams.len() >= r.team_limit as usize { |
|
180 |
actions.push(Warn("Too many teams!".to_string())) |
|
181 |
} else if r.addable_hedgehogs() == 0 { |
|
182 |
actions.push(Warn("Too many hedgehogs!".to_string())) |
|
183 |
} else if r.find_team(|t| t.name == info.name) != None { |
|
184 |
actions.push(Warn("There's already a team with same name in the list.".to_string())) |
|
13423 | 185 |
} else if r.game_info.is_some() { |
13419 | 186 |
actions.push(Warn("Joining not possible: Round is in progress.".to_string())) |
13494 | 187 |
} else if r.is_team_add_restricted() { |
188 |
actions.push(Warn("This room currently does not allow adding new teams.".to_string())); |
|
13419 | 189 |
} else { |
13775 | 190 |
let team = r.add_team(c.id, *info, c.protocol_number < 42); |
13419 | 191 |
c.teams_in_game += 1; |
192 |
c.clan = Some(team.color); |
|
193 |
actions.push(TeamAccepted(team.name.clone()) |
|
194 |
.send_self().action()); |
|
195 |
actions.push(TeamAdd(HWRoom::team_info(&c, team)) |
|
196 |
.send_all().in_room(room_id).but_self().action()); |
|
197 |
actions.push(TeamColor(team.name.clone(), team.color) |
|
198 |
.send_all().in_room(room_id).action()); |
|
199 |
actions.push(HedgehogsNumber(team.name.clone(), team.hedgehogs_number) |
|
200 |
.send_all().in_room(room_id).action()); |
|
201 |
actions.push(SendRoomUpdate(None)); |
|
202 |
} |
|
203 |
} |
|
204 |
server.react(client_id, actions); |
|
205 |
}, |
|
206 |
RemoveTeam(name) => { |
|
207 |
let mut actions = Vec::new(); |
|
208 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
209 |
match r.find_team_owner(&name) { |
|
210 |
None => |
|
211 |
actions.push(Warn("Error: The team you tried to remove does not exist.".to_string())), |
|
212 |
Some((id, _)) if id != client_id => |
|
213 |
actions.push(Warn("You can't remove a team you don't own.".to_string())), |
|
214 |
Some((_, name)) => { |
|
215 |
c.teams_in_game -= 1; |
|
216 |
c.clan = r.find_team_color(c.id); |
|
217 |
actions.push(Action::RemoveTeam(name.to_string())); |
|
218 |
} |
|
219 |
} |
|
220 |
}; |
|
221 |
server.react(client_id, actions); |
|
222 |
}, |
|
223 |
SetHedgehogsNumber(team_name, number) => { |
|
13666 | 224 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
13419 | 225 |
let addable_hedgehogs = r.addable_hedgehogs(); |
13666 | 226 |
let actions = if let Some((_, team)) = r.find_team_and_owner_mut(|t| t.name == team_name) { |
13486 | 227 |
if !c.is_master() { |
13419 | 228 |
vec![ProtocolError("You're not the room master!".to_string())] |
13709
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
229 |
} else if number < 1 || number > MAX_HEDGEHOGS_PER_TEAM |
13419 | 230 |
|| number > addable_hedgehogs + team.hedgehogs_number { |
231 |
vec![HedgehogsNumber(team.name.clone(), team.hedgehogs_number) |
|
232 |
.send_self().action()] |
|
233 |
} else { |
|
234 |
team.hedgehogs_number = number; |
|
235 |
vec![HedgehogsNumber(team.name.clone(), number) |
|
236 |
.send_all().in_room(room_id).but_self().action()] |
|
237 |
} |
|
238 |
} else { |
|
239 |
vec![(Warn("No such team.".to_string()))] |
|
13666 | 240 |
}; |
241 |
server.react(client_id, actions); |
|
242 |
} |
|
13419 | 243 |
}, |
244 |
SetTeamColor(team_name, color) => { |
|
13666 | 245 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
246 |
let mut owner_id = None; |
|
247 |
let actions = if let Some((owner, team)) = r.find_team_and_owner_mut(|t| t.name == team_name) { |
|
13486 | 248 |
if !c.is_master() { |
13419 | 249 |
vec![ProtocolError("You're not the room master!".to_string())] |
250 |
} else if false { |
|
251 |
Vec::new() |
|
252 |
} else { |
|
253 |
owner_id = Some(owner); |
|
254 |
team.color = color; |
|
255 |
vec![TeamColor(team.name.clone(), color) |
|
256 |
.send_all().in_room(room_id).but_self().action()] |
|
257 |
} |
|
258 |
} else { |
|
259 |
vec![(Warn("No such team.".to_string()))] |
|
13666 | 260 |
}; |
13419 | 261 |
|
13666 | 262 |
if let Some(id) = owner_id { |
263 |
server.clients[id].clan = Some(color); |
|
264 |
} |
|
13419 | 265 |
|
13666 | 266 |
server.react(client_id, actions); |
267 |
}; |
|
13422 | 268 |
}, |
269 |
Cfg(cfg) => { |
|
13666 | 270 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
271 |
let actions = if r.is_fixed() { |
|
13447 | 272 |
vec![Warn("Access denied.".to_string())] |
13486 | 273 |
} else if !c.is_master() { |
13422 | 274 |
vec![ProtocolError("You're not the room master!".to_string())] |
275 |
} else { |
|
13775 | 276 |
let cfg = match cfg { |
277 |
GameCfg::Scheme(name, mut values) => { |
|
278 |
if c.protocol_number == 49 && values.len() >= 2 { |
|
279 |
let mut s = "X".repeat(50); |
|
280 |
s.push_str(&values.pop().unwrap()); |
|
281 |
values.push(s); |
|
282 |
} |
|
283 |
GameCfg::Scheme(name, values) |
|
284 |
} |
|
285 |
cfg => cfg |
|
286 |
}; |
|
287 |
||
13439 | 288 |
let v = vec![cfg.to_server_msg() |
289 |
.send_all().in_room(r.id).but_self().action()]; |
|
290 |
r.set_config(cfg); |
|
291 |
v |
|
13666 | 292 |
}; |
293 |
server.react(client_id, actions); |
|
294 |
} |
|
13419 | 295 |
} |
13528 | 296 |
Save(name, location) => { |
297 |
let actions = vec![server_chat(format!("Room config saved as {}", name)) |
|
298 |
.send_all().in_room(room_id).action()]; |
|
299 |
server.rooms[room_id].save_config(name, location); |
|
300 |
server.react(client_id, actions); |
|
301 |
} |
|
13529 | 302 |
SaveRoom(filename) => { |
13666 | 303 |
if server.clients[client_id].is_admin() { |
304 |
let actions = match server.rooms[room_id].get_saves() { |
|
14413 | 305 |
Ok(text) => match server.io.write_file(&filename, &text) { |
13529 | 306 |
Ok(_) => vec![server_chat("Room configs saved successfully.".to_string()) |
307 |
.send_self().action()], |
|
308 |
Err(e) => { |
|
309 |
warn!("Error while writing the config file \"{}\": {}", filename, e); |
|
310 |
vec![Warn("Unable to save the room configs.".to_string())] |
|
311 |
} |
|
312 |
} |
|
313 |
Err(e) => { |
|
314 |
warn!("Error while serializing the room configs: {}", e); |
|
315 |
vec![Warn("Unable to serialize the room configs.".to_string())] |
|
316 |
} |
|
13666 | 317 |
}; |
318 |
server.react(client_id, actions); |
|
319 |
} |
|
13529 | 320 |
} |
321 |
LoadRoom(filename) => { |
|
13666 | 322 |
if server.clients[client_id].is_admin() { |
14413 | 323 |
let actions = match server.io.read_file(&filename) { |
13529 | 324 |
Ok(text) => match server.rooms[room_id].set_saves(&text) { |
325 |
Ok(_) => vec![server_chat("Room configs loaded successfully.".to_string()) |
|
326 |
.send_self().action()], |
|
327 |
Err(e) => { |
|
328 |
warn!("Error while deserializing the room configs: {}", e); |
|
329 |
vec![Warn("Unable to deserialize the room configs.".to_string())] |
|
330 |
} |
|
331 |
} |
|
332 |
Err(e) => { |
|
333 |
warn!("Error while reading the config file \"{}\": {}", filename, e); |
|
334 |
vec![Warn("Unable to load the room configs.".to_string())] |
|
335 |
} |
|
13666 | 336 |
}; |
337 |
server.react(client_id, actions); |
|
338 |
} |
|
13529 | 339 |
} |
13528 | 340 |
Delete(name) => { |
341 |
let actions = if !server.rooms[room_id].delete_config(&name) { |
|
342 |
vec![Warn(format!("Save doesn't exist: {}", name))] |
|
343 |
} else { |
|
344 |
vec![server_chat(format!("Room config {} has been deleted", name)) |
|
345 |
.send_all().in_room(room_id).action()] |
|
346 |
}; |
|
347 |
server.react(client_id, actions); |
|
348 |
} |
|
13450 | 349 |
CallVote(None) => { |
350 |
server.react(client_id, vec![ |
|
13521 | 351 |
server_chat("Available callvote commands: kick <nickname>, map <name>, pause, newseed, hedgehogs <number>".to_string()) |
13450 | 352 |
.send_self().action()]) |
353 |
} |
|
354 |
CallVote(Some(kind)) => { |
|
13492 | 355 |
let is_in_game = server.rooms[room_id].game_info.is_some(); |
13450 | 356 |
let error = match &kind { |
357 |
VoteType::Kick(nick) => { |
|
358 |
if server.find_client(&nick).filter(|c| c.room_id == Some(room_id)).is_some() { |
|
359 |
None |
|
360 |
} else { |
|
13521 | 361 |
Some("/callvote kick: No such user!".to_string()) |
13450 | 362 |
} |
363 |
}, |
|
364 |
VoteType::Map(None) => { |
|
13521 | 365 |
let names: Vec<_> = server.rooms[room_id].saves.keys().cloned().collect(); |
366 |
if names.is_empty() { |
|
367 |
Some("/callvote map: No maps saved in this room!".to_string()) |
|
368 |
} else { |
|
369 |
Some(format!("Available maps: {}", names.join(", "))) |
|
370 |
} |
|
13450 | 371 |
}, |
372 |
VoteType::Map(Some(name)) => { |
|
13521 | 373 |
if server.rooms[room_id].saves.get(&name[..]).is_some() { |
13530 | 374 |
None |
13521 | 375 |
} else { |
13530 | 376 |
Some("/callvote map: No such map!".to_string()) |
13521 | 377 |
} |
13450 | 378 |
}, |
379 |
VoteType::Pause => { |
|
380 |
if is_in_game { |
|
381 |
None |
|
382 |
} else { |
|
13521 | 383 |
Some("/callvote pause: No game in progress!".to_string()) |
13450 | 384 |
} |
385 |
}, |
|
386 |
VoteType::NewSeed => { |
|
387 |
None |
|
388 |
}, |
|
389 |
VoteType::HedgehogsPerTeam(number) => { |
|
390 |
match number { |
|
13709
e335daaa77a9
Add hogs per team named constant that absolutely no one asked for
alfadur
parents:
13666
diff
changeset
|
391 |
1...MAX_HEDGEHOGS_PER_TEAM => None, |
13521 | 392 |
_ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()) |
13450 | 393 |
} |
394 |
}, |
|
395 |
}; |
|
396 |
match error { |
|
397 |
None => { |
|
13460 | 398 |
let msg = voting_description(&kind); |
13450 | 399 |
let voting = Voting::new(kind, server.room_clients(client_id)); |
13520 | 400 |
server.rooms[room_id].voting = Some(voting); |
13450 | 401 |
server.react(client_id, vec![ |
13521 | 402 |
server_chat(msg).send_all().in_room(room_id).action(), |
13450 | 403 |
AddVote{ vote: true, is_forced: false}]); |
404 |
} |
|
405 |
Some(msg) => { |
|
406 |
server.react(client_id, vec![ |
|
407 |
server_chat(msg).send_self().action()]) |
|
408 |
} |
|
409 |
} |
|
410 |
} |
|
411 |
Vote(vote) => { |
|
13520 | 412 |
server.react(client_id, vec![AddVote{ vote, is_forced: false }]); |
13450 | 413 |
} |
414 |
ForceVote(vote) => { |
|
13520 | 415 |
let is_forced = server.clients[client_id].is_admin(); |
416 |
server.react(client_id, vec![AddVote{ vote, is_forced }]); |
|
13450 | 417 |
} |
13494 | 418 |
ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => { |
419 |
if server.clients[client_id].is_master() { |
|
420 |
server.rooms[room_id].flags.toggle(room_message_flag(&message)); |
|
421 |
} |
|
422 |
server.react(client_id, vec![SendRoomUpdate(None)]); |
|
423 |
} |
|
13423 | 424 |
StartGame => { |
13520 | 425 |
server.react(client_id, vec![StartRoomGame(room_id)]); |
13423 | 426 |
} |
427 |
EngineMessage(em) => { |
|
428 |
let mut actions = Vec::new(); |
|
429 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
430 |
if c.teams_in_game > 0 { |
|
431 |
let decoding = decode(&em[..]).unwrap(); |
|
432 |
let messages = by_msg(&decoding); |
|
13443 | 433 |
let valid = messages.filter(|m| is_msg_valid(m, &c.team_indices)); |
434 |
let non_empty = valid.clone().filter(|m| !is_msg_empty(m)); |
|
435 |
let sync_msg = valid.clone().filter(|m| is_msg_timed(m)) |
|
436 |
.last().map(|m| if is_msg_empty(m) {Some(encode(m))} else {None}); |
|
13423 | 437 |
|
438 |
let em_response = encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>()); |
|
439 |
if !em_response.is_empty() { |
|
13428 | 440 |
actions.push(ForwardEngineMessage(vec![em_response]) |
13423 | 441 |
.send_all().in_room(r.id).but_self().action()); |
442 |
} |
|
13427 | 443 |
let em_log = encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>()); |
444 |
if let Some(ref mut info) = r.game_info { |
|
13429 | 445 |
if !em_log.is_empty() { |
13428 | 446 |
info.msg_log.push(em_log); |
447 |
} |
|
13443 | 448 |
if let Some(msg) = sync_msg { |
449 |
info.sync_msg = msg; |
|
13427 | 450 |
} |
451 |
} |
|
13423 | 452 |
} |
453 |
} |
|
454 |
server.react(client_id, actions) |
|
455 |
} |
|
456 |
RoundFinished => { |
|
457 |
let mut actions = Vec::new(); |
|
458 |
if let (c, Some(r)) = server.client_and_room(client_id) { |
|
13486 | 459 |
if c.is_in_game() { |
460 |
c.set_is_in_game(false); |
|
13423 | 461 |
actions.push(ClientFlags("-g".to_string(), vec![c.nick.clone()]). |
462 |
send_all().in_room(r.id).action()); |
|
13426 | 463 |
if r.game_info.is_some() { |
464 |
for team in r.client_teams(c.id) { |
|
465 |
actions.push(SendTeamRemovalMessage(team.name.clone())); |
|
466 |
} |
|
13423 | 467 |
} |
468 |
} |
|
469 |
} |
|
470 |
server.react(client_id, actions) |
|
13444
914f9b970f4d
Implement server-side logic for Rnd
Marcin Mielniczuk <marmistrz.dev@zoho.eu>
parents:
13443
diff
changeset
|
471 |
}, |
13445
d3c86ade3d4d
Send the rnd reply to the room only.
Marcin Mielniczuk <marmistrz.dev@zoho.eu>
parents:
13444
diff
changeset
|
472 |
Rnd(v) => { |
13492 | 473 |
let result = rnd_reply(&v); |
474 |
let mut echo = vec!["/rnd".to_string()]; |
|
475 |
echo.extend(v.into_iter()); |
|
476 |
let chat_msg = ChatMsg { |
|
477 |
nick: server.clients[client_id].nick.clone(), |
|
478 |
msg: echo.join(" ") |
|
479 |
}; |
|
480 |
server.react(client_id, vec![ |
|
481 |
chat_msg.send_all().in_room(room_id).action(), |
|
482 |
result.send_all().in_room(room_id).action()]) |
|
13445
d3c86ade3d4d
Send the rnd reply to the room only.
Marcin Mielniczuk <marmistrz.dev@zoho.eu>
parents:
13444
diff
changeset
|
483 |
}, |
13419 | 484 |
_ => warn!("Unimplemented!") |
12147 | 485 |
} |
486 |
} |