106 client_id: ClientId, |
106 client_id: ClientId, |
107 response: &mut super::Response, |
107 response: &mut super::Response, |
108 room_id: RoomId, |
108 room_id: RoomId, |
109 message: HWProtocolMessage, |
109 message: HWProtocolMessage, |
110 ) { |
110 ) { |
|
111 let client = &mut server.clients[client_id]; |
|
112 let room = &mut server.rooms[room_id]; |
|
113 |
111 use crate::protocol::messages::HWProtocolMessage::*; |
114 use crate::protocol::messages::HWProtocolMessage::*; |
112 match message { |
115 match message { |
113 Part(msg) => { |
116 Part(msg) => { |
114 if let (client, Some(room)) = server.client_and_room(client_id) { |
117 let msg = match msg { |
115 let msg = match msg { |
118 Some(s) => format!("part: {}", s), |
116 Some(s) => format!("part: {}", s), |
119 None => "part".to_string(), |
117 None => "part".to_string(), |
120 }; |
118 }; |
121 super::common::exit_room(server, client_id, response, &msg); |
119 super::common::exit_room(server, client_id, response, &msg); |
|
120 } |
|
121 } |
122 } |
122 Chat(msg) => { |
123 Chat(msg) => { |
123 let client = &mut server.clients[client_id]; |
|
124 response.add( |
124 response.add( |
125 ChatMsg { |
125 ChatMsg { |
126 nick: client.nick.clone(), |
126 nick: client.nick.clone(), |
127 msg, |
127 msg, |
128 } |
128 } |
129 .send_all() |
129 .send_all() |
130 .in_room(room_id), |
130 .in_room(room_id), |
131 ); |
131 ); |
132 } |
132 } |
133 Fix => { |
133 Fix => { |
134 if let (client, Some(room)) = server.client_and_room(client_id) { |
134 if client.is_admin() { |
135 if client.is_admin() { |
135 room.set_is_fixed(true); |
136 room.set_is_fixed(true); |
136 room.set_join_restriction(false); |
137 room.set_join_restriction(false); |
137 room.set_team_add_restriction(false); |
138 room.set_team_add_restriction(false); |
138 room.set_unregistered_players_restriction(true); |
139 room.set_unregistered_players_restriction(true); |
|
140 } |
|
141 } |
139 } |
142 } |
140 } |
143 Unfix => { |
141 Unfix => { |
144 if let (client, Some(room)) = server.client_and_room(client_id) { |
142 if client.is_admin() { |
145 if client.is_admin() { |
143 room.set_is_fixed(false); |
146 room.set_is_fixed(false) |
|
147 } |
|
148 } |
144 } |
149 } |
145 } |
150 Greeting(text) => { |
146 Greeting(text) => { |
151 if let (clienr, Some(room)) = server.client_and_room(client_id) { |
147 if client.is_admin() || client.is_master() && !room.is_fixed() { |
152 if clienr.is_admin() || clienr.is_master() && !room.is_fixed() { |
148 room.greeting = text; |
153 room.greeting = text |
|
154 } |
|
155 } |
149 } |
156 } |
150 } |
157 RoomName(new_name) => { |
151 RoomName(new_name) => { |
158 if is_name_illegal(&new_name) { |
152 if is_name_illegal(&new_name) { |
159 response.add(Warning("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()).send_self()); |
153 response.add(Warning("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()).send_self()); |
172 super::common::get_room_update(Some(old_name), room, Some(&client), response); |
166 super::common::get_room_update(Some(old_name), room, Some(&client), response); |
173 } |
167 } |
174 } |
168 } |
175 } |
169 } |
176 ToggleReady => { |
170 ToggleReady => { |
177 if let (client, Some(room)) = server.client_and_room(client_id) { |
171 let flags = if client.is_ready() { |
178 let flags = if client.is_ready() { |
172 room.ready_players_number -= 1; |
179 room.ready_players_number -= 1; |
173 "-r" |
180 "-r" |
174 } else { |
181 } else { |
175 room.ready_players_number += 1; |
182 room.ready_players_number += 1; |
176 "+r" |
183 "+r" |
177 }; |
184 }; |
178 |
185 |
179 let msg = if client.protocol_number < 38 { |
186 let msg = if client.protocol_number < 38 { |
180 LegacyReady(client.is_ready(), vec![client.nick.clone()]) |
187 LegacyReady(client.is_ready(), vec![client.nick.clone()]) |
181 } else { |
188 } else { |
182 ClientFlags(flags.to_string(), vec![client.nick.clone()]) |
189 ClientFlags(flags.to_string(), vec![client.nick.clone()]) |
183 }; |
190 }; |
184 response.add(msg.send_all().in_room(room.id)); |
191 response.add(msg.send_all().in_room(room.id)); |
185 client.set_is_ready(!client.is_ready()); |
192 client.set_is_ready(!client.is_ready()); |
186 |
193 |
187 if room.is_fixed() && room.ready_players_number == room.players_number { |
194 if room.is_fixed() && room.ready_players_number == room.players_number { |
188 super::common::start_game(server, room_id, response); |
195 super::common::start_game(server, room_id, response); |
|
196 } |
|
197 } |
189 } |
198 } |
190 } |
199 AddTeam(info) => { |
191 AddTeam(info) => { |
200 let client = &mut server.clients[client_id]; |
|
201 let room = &mut server.rooms[room_id]; |
|
202 if room.teams.len() >= room.team_limit as usize { |
192 if room.teams.len() >= room.team_limit as usize { |
203 response.add(Warning("Too many teams!".to_string()).send_self()); |
193 response.add(Warning("Too many teams!".to_string()).send_self()); |
204 } else if room.addable_hedgehogs() == 0 { |
194 } else if room.addable_hedgehogs() == 0 { |
205 response.add(Warning("Too many hedgehogs!".to_string()).send_self()); |
195 response.add(Warning("Too many hedgehogs!".to_string()).send_self()); |
206 } else if room.find_team(|t| t.name == info.name) != None { |
196 } else if room.find_team(|t| t.name == info.name) != None { |
245 None |
235 None |
246 }; |
236 }; |
247 super::common::get_room_update(None, room, room_master, response); |
237 super::common::get_room_update(None, room, room_master, response); |
248 } |
238 } |
249 } |
239 } |
250 RemoveTeam(name) => { |
240 RemoveTeam(name) => match room.find_team_owner(&name) { |
251 let client = &mut server.clients[client_id]; |
241 None => response.add( |
252 let room = &mut server.rooms[room_id]; |
242 Warning("Error: The team you tried to remove does not exist.".to_string()) |
253 match room.find_team_owner(&name) { |
243 .send_self(), |
254 None => response.add( |
244 ), |
255 Warning("Error: The team you tried to remove does not exist.".to_string()) |
245 Some((id, _)) if id != client_id => response |
256 .send_self(), |
246 .add(Warning("You can't remove a team you don't own.".to_string()).send_self()), |
257 ), |
247 Some((_, name)) => { |
258 Some((id, _)) if id != client_id => response |
248 client.teams_in_game -= 1; |
259 .add(Warning("You can't remove a team you don't own.".to_string()).send_self()), |
249 client.clan = room.find_team_color(client.id); |
260 Some((_, name)) => { |
250 super::common::remove_teams( |
261 client.teams_in_game -= 1; |
251 room, |
262 client.clan = room.find_team_color(client.id); |
252 vec![name.to_string()], |
263 super::common::remove_teams( |
253 client.is_in_game(), |
264 room, |
254 response, |
265 vec![name.to_string()], |
255 ); |
266 client.is_in_game(), |
256 |
267 response, |
257 match room.game_info { |
|
258 Some(ref info) if info.teams_in_game == 0 => { |
|
259 super::common::end_game(server, room_id, response) |
|
260 } |
|
261 _ => (), |
|
262 } |
|
263 } |
|
264 }, |
|
265 SetHedgehogsNumber(team_name, number) => { |
|
266 let addable_hedgehogs = room.addable_hedgehogs(); |
|
267 if let Some((_, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) { |
|
268 if !client.is_master() { |
|
269 response.add(Error("You're not the room master!".to_string()).send_self()); |
|
270 } else if number < 1 |
|
271 || number > MAX_HEDGEHOGS_PER_TEAM |
|
272 || number > addable_hedgehogs + team.hedgehogs_number |
|
273 { |
|
274 response |
|
275 .add(HedgehogsNumber(team.name.clone(), team.hedgehogs_number).send_self()); |
|
276 } else { |
|
277 team.hedgehogs_number = number; |
|
278 response.add( |
|
279 HedgehogsNumber(team.name.clone(), number) |
|
280 .send_all() |
|
281 .in_room(room_id) |
|
282 .but_self(), |
268 ); |
283 ); |
269 |
284 } |
270 match room.game_info { |
285 } else { |
271 Some(ref info) if info.teams_in_game == 0 => { |
286 response.add(Warning("No such team.".to_string()).send_self()); |
272 super::common::end_game(server, room_id, response) |
|
273 } |
|
274 _ => (), |
|
275 } |
|
276 } |
|
277 } |
|
278 } |
|
279 SetHedgehogsNumber(team_name, number) => { |
|
280 if let (client, Some(room)) = server.client_and_room(client_id) { |
|
281 let addable_hedgehogs = room.addable_hedgehogs(); |
|
282 if let Some((_, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) { |
|
283 if !client.is_master() { |
|
284 response.add(Error("You're not the room master!".to_string()).send_self()); |
|
285 } else if number < 1 |
|
286 || number > MAX_HEDGEHOGS_PER_TEAM |
|
287 || number > addable_hedgehogs + team.hedgehogs_number |
|
288 { |
|
289 response.add( |
|
290 HedgehogsNumber(team.name.clone(), team.hedgehogs_number).send_self(), |
|
291 ); |
|
292 } else { |
|
293 team.hedgehogs_number = number; |
|
294 response.add( |
|
295 HedgehogsNumber(team.name.clone(), number) |
|
296 .send_all() |
|
297 .in_room(room_id) |
|
298 .but_self(), |
|
299 ); |
|
300 } |
|
301 } else { |
|
302 response.add(Warning("No such team.".to_string()).send_self()); |
|
303 } |
|
304 } |
287 } |
305 } |
288 } |
306 SetTeamColor(team_name, color) => { |
289 SetTeamColor(team_name, color) => { |
307 if let (client, Some(room)) = server.client_and_room(client_id) { |
290 if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) { |
308 if let Some((owner, team)) = room.find_team_and_owner_mut(|t| t.name == team_name) { |
291 if !client.is_master() { |
309 if !client.is_master() { |
|
310 response.add(Error("You're not the room master!".to_string()).send_self()); |
|
311 } else { |
|
312 team.color = color; |
|
313 response.add( |
|
314 TeamColor(team.name.clone(), color) |
|
315 .send_all() |
|
316 .in_room(room_id) |
|
317 .but_self(), |
|
318 ); |
|
319 server.clients[owner].clan = Some(color); |
|
320 } |
|
321 } else { |
|
322 response.add(Warning("No such team.".to_string()).send_self()); |
|
323 } |
|
324 } |
|
325 } |
|
326 Cfg(cfg) => { |
|
327 if let (client, Some(room)) = server.client_and_room(client_id) { |
|
328 if room.is_fixed() { |
|
329 response.add(Warning("Access denied.".to_string()).send_self()); |
|
330 } else if !client.is_master() { |
|
331 response.add(Error("You're not the room master!".to_string()).send_self()); |
292 response.add(Error("You're not the room master!".to_string()).send_self()); |
332 } else { |
293 } else { |
333 let cfg = match cfg { |
294 team.color = color; |
334 GameCfg::Scheme(name, mut values) => { |
295 response.add( |
335 if client.protocol_number == 49 && values.len() >= 2 { |
296 TeamColor(team.name.clone(), color) |
336 let mut s = "X".repeat(50); |
297 .send_all() |
337 s.push_str(&values.pop().unwrap()); |
298 .in_room(room_id) |
338 values.push(s); |
299 .but_self(), |
339 } |
300 ); |
340 GameCfg::Scheme(name, values) |
301 server.clients[owner].clan = Some(color); |
|
302 } |
|
303 } else { |
|
304 response.add(Warning("No such team.".to_string()).send_self()); |
|
305 } |
|
306 } |
|
307 Cfg(cfg) => { |
|
308 if room.is_fixed() { |
|
309 response.add(Warning("Access denied.".to_string()).send_self()); |
|
310 } else if !client.is_master() { |
|
311 response.add(Error("You're not the room master!".to_string()).send_self()); |
|
312 } else { |
|
313 let cfg = match cfg { |
|
314 GameCfg::Scheme(name, mut values) => { |
|
315 if client.protocol_number == 49 && values.len() >= 2 { |
|
316 let mut s = "X".repeat(50); |
|
317 s.push_str(&values.pop().unwrap()); |
|
318 values.push(s); |
341 } |
319 } |
342 cfg => cfg, |
320 GameCfg::Scheme(name, values) |
343 }; |
321 } |
344 |
322 cfg => cfg, |
345 response.add(cfg.to_server_msg().send_all().in_room(room.id).but_self()); |
323 }; |
346 room.set_config(cfg); |
324 |
347 } |
325 response.add(cfg.to_server_msg().send_all().in_room(room.id).but_self()); |
|
326 room.set_config(cfg); |
348 } |
327 } |
349 } |
328 } |
350 Save(name, location) => { |
329 Save(name, location) => { |
351 response.add( |
330 response.add( |
352 server_chat(format!("Room config saved as {}", name)) |
331 server_chat(format!("Room config saved as {}", name)) |
353 .send_all() |
332 .send_all() |
354 .in_room(room_id), |
333 .in_room(room_id), |
355 ); |
334 ); |
356 server.rooms[room_id].save_config(name, location); |
335 room.save_config(name, location); |
357 } |
336 } |
358 SaveRoom(filename) => { |
337 SaveRoom(filename) => { |
359 if server.clients[client_id].is_admin() { |
338 if client.is_admin() { |
360 match server.rooms[room_id].get_saves() { |
339 match room.get_saves() { |
361 Ok(text) => match server.io.write_file(&filename, &text) { |
340 Ok(text) => match server.io.write_file(&filename, &text) { |
362 Ok(_) => response.add( |
341 Ok(_) => response.add( |
363 server_chat("Room configs saved successfully.".to_string()).send_self(), |
342 server_chat("Room configs saved successfully.".to_string()).send_self(), |
364 ), |
343 ), |
365 Err(e) => { |
344 Err(e) => { |
497 }, |
477 }, |
498 response, |
478 response, |
499 ); |
479 ); |
500 } |
480 } |
501 ForceVote(vote) => { |
481 ForceVote(vote) => { |
502 let is_forced = server.clients[client_id].is_admin(); |
482 let is_forced = client.is_admin(); |
503 super::common::submit_vote( |
483 super::common::submit_vote( |
504 server, |
484 server, |
505 coretypes::Vote { |
485 coretypes::Vote { |
506 is_pro: vote, |
486 is_pro: vote, |
507 is_forced, |
487 is_forced, |
508 }, |
488 }, |
509 response, |
489 response, |
510 ); |
490 ); |
511 } |
491 } |
512 ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => { |
492 ToggleRestrictJoin | ToggleRestrictTeams | ToggleRegisteredOnly => { |
513 let client = &server.clients[client_id]; |
|
514 let room = &mut server.rooms[room_id]; |
|
515 if client.is_master() { |
493 if client.is_master() { |
516 room.flags.toggle(room_message_flag(&message)); |
494 room.flags.toggle(room_message_flag(&message)); |
517 super::common::get_room_update(None, room, Some(&client), response); |
495 super::common::get_room_update(None, room, Some(&client), response); |
518 } |
496 } |
519 } |
497 } |
520 StartGame => { |
498 StartGame => { |
521 super::common::start_game(server, room_id, response); |
499 super::common::start_game(server, room_id, response); |
522 } |
500 } |
523 EngineMessage(em) => { |
501 EngineMessage(em) => { |
524 if let (c, Some(r)) = server.client_and_room(client_id) { |
502 if client.teams_in_game > 0 { |
525 if c.teams_in_game > 0 { |
503 let decoding = decode(&em[..]).unwrap(); |
526 let decoding = decode(&em[..]).unwrap(); |
504 let messages = by_msg(&decoding); |
527 let messages = by_msg(&decoding); |
505 let valid = messages.filter(|m| is_msg_valid(m, &client.team_indices)); |
528 let valid = messages.filter(|m| is_msg_valid(m, &c.team_indices)); |
506 let non_empty = valid.clone().filter(|m| !is_msg_empty(m)); |
529 let non_empty = valid.clone().filter(|m| !is_msg_empty(m)); |
507 let sync_msg = valid.clone().filter(|m| is_msg_timed(m)).last().map(|m| { |
530 let sync_msg = valid.clone().filter(|m| is_msg_timed(m)).last().map(|m| { |
508 if is_msg_empty(m) { |
531 if is_msg_empty(m) { |
509 Some(encode(m)) |
532 Some(encode(m)) |
510 } else { |
533 } else { |
511 None |
534 None |
512 } |
535 } |
513 }); |
536 }); |
514 |
537 |
515 let em_response = encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>()); |
538 let em_response = |
516 if !em_response.is_empty() { |
539 encode(&valid.flat_map(|msg| msg).cloned().collect::<Vec<_>>()); |
517 response.add( |
540 if !em_response.is_empty() { |
518 ForwardEngineMessage(vec![em_response]) |
541 response.add( |
519 .send_all() |
542 ForwardEngineMessage(vec![em_response]) |
520 .in_room(room.id) |
543 .send_all() |
521 .but_self(), |
544 .in_room(r.id) |
522 ); |
545 .but_self(), |
523 } |
546 ); |
524 let em_log = encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>()); |
547 } |
525 if let Some(ref mut info) = room.game_info { |
548 let em_log = |
526 if !em_log.is_empty() { |
549 encode(&non_empty.flat_map(|msg| msg).cloned().collect::<Vec<_>>()); |
527 info.msg_log.push(em_log); |
550 if let Some(ref mut info) = r.game_info { |
528 } |
551 if !em_log.is_empty() { |
529 if let Some(msg) = sync_msg { |
552 info.msg_log.push(em_log); |
530 info.sync_msg = msg; |
553 } |
|
554 if let Some(msg) = sync_msg { |
|
555 info.sync_msg = msg; |
|
556 } |
|
557 } |
531 } |
558 } |
532 } |
559 } |
533 } |
560 } |
534 } |
561 RoundFinished => { |
535 RoundFinished => { |
562 let mut game_ended = false; |
536 let mut game_ended = false; |
563 let client = &mut server.clients[client_id]; |
|
564 if client.is_in_game() { |
537 if client.is_in_game() { |
565 let room = &mut server.rooms[room_id]; |
|
566 |
|
567 client.set_is_in_game(false); |
538 client.set_is_in_game(false); |
568 response.add( |
539 response.add( |
569 ClientFlags("-g".to_string(), vec![client.nick.clone()]) |
540 ClientFlags("-g".to_string(), vec![client.nick.clone()]) |
570 .send_all() |
541 .send_all() |
571 .in_room(room.id), |
542 .in_room(room.id), |