339 if !nicks.is_empty() { |
342 if !nicks.is_empty() { |
340 response.add(ClientFlags(add_flags(&[Flags::Ready]), nicks).send(to_client)); |
343 response.add(ClientFlags(add_flags(&[Flags::Ready]), nicks).send(to_client)); |
341 } |
344 } |
342 } |
345 } |
343 |
346 |
344 pub fn apply_voting_result( |
347 pub fn check_vote( |
345 server: &mut HwServer, |
348 server: &HwServer, |
|
349 room: &HwRoom, |
|
350 kind: &VoteType, |
|
351 response: &mut Response, |
|
352 ) -> bool { |
|
353 let error = match &kind { |
|
354 VoteType::Kick(nick) => { |
|
355 if server |
|
356 .find_client(&nick) |
|
357 .filter(|c| c.room_id == Some(room.id)) |
|
358 .is_some() |
|
359 { |
|
360 None |
|
361 } else { |
|
362 Some("/callvote kick: No such user!".to_string()) |
|
363 } |
|
364 } |
|
365 VoteType::Map(None) => { |
|
366 let names: Vec<_> = room.saves.keys().cloned().collect(); |
|
367 if names.is_empty() { |
|
368 Some("/callvote map: No maps saved in this room!".to_string()) |
|
369 } else { |
|
370 Some(format!("Available maps: {}", names.join(", "))) |
|
371 } |
|
372 } |
|
373 VoteType::Map(Some(name)) => { |
|
374 if room.saves.get(&name[..]).is_some() { |
|
375 None |
|
376 } else { |
|
377 Some("/callvote map: No such map!".to_string()) |
|
378 } |
|
379 } |
|
380 VoteType::Pause => { |
|
381 if room.game_info.is_some() { |
|
382 None |
|
383 } else { |
|
384 Some("/callvote pause: No game in progress!".to_string()) |
|
385 } |
|
386 } |
|
387 VoteType::NewSeed => None, |
|
388 VoteType::HedgehogsPerTeam(number) => match number { |
|
389 1..=MAX_HEDGEHOGS_PER_TEAM => None, |
|
390 _ => Some("/callvote hedgehogs: Specify number from 1 to 8.".to_string()), |
|
391 }, |
|
392 }; |
|
393 |
|
394 match error { |
|
395 None => true, |
|
396 Some(msg) => { |
|
397 response.add(server_chat(msg).send_self()); |
|
398 false |
|
399 } |
|
400 } |
|
401 } |
|
402 |
|
403 pub fn get_vote_data( |
346 room_id: RoomId, |
404 room_id: RoomId, |
347 response: &mut Response, |
405 result: &Result<VoteResult, VoteError>, |
348 kind: VoteType, |
406 response: &mut Response, |
349 ) { |
407 ) { |
350 match kind { |
408 match result { |
351 VoteType::Kick(nick) => { |
409 Ok(VoteResult::Submitted) => { |
352 if let Some(kicked_client) = server.find_client(&nick) { |
410 response.add(server_chat("Your vote has been counted.".to_string()).send_self()) |
353 let kicked_id = kicked_client.id; |
411 } |
354 if kicked_client.room_id == Some(room_id) { |
412 Ok(VoteResult::Succeeded(_)) | Ok(VoteResult::Failed) => response.add( |
355 if let Some(mut room_control) = server.get_room_control(kicked_client.id) { |
413 server_chat("Voting closed.".to_string()) |
|
414 .send_all() |
|
415 .in_room(room_id), |
|
416 ), |
|
417 Err(VoteError::NoVoting) => { |
|
418 response.add(server_chat("There's no voting going on.".to_string()).send_self()) |
|
419 } |
|
420 Err(VoteError::AlreadyVoted) => { |
|
421 response.add(server_chat("You already have voted.".to_string()).send_self()) |
|
422 } |
|
423 } |
|
424 } |
|
425 |
|
426 pub fn handle_vote( |
|
427 mut room_control: HwRoomControl, |
|
428 result: Result<VoteResult, VoteError>, |
|
429 response: &mut super::Response, |
|
430 ) { |
|
431 let room_id = room_control.room().id; |
|
432 super::common::get_vote_data(room_control.room().id, &result, response); |
|
433 |
|
434 if let Ok(VoteResult::Succeeded(kind)) = result { |
|
435 match kind { |
|
436 VoteType::Kick(nick) => { |
|
437 if let Some(kicked_client) = room_control.server().find_client(&nick) { |
|
438 let kicked_id = kicked_client.id; |
|
439 if let Some(mut room_control) = room_control.change_client(kicked_id) { |
356 response.add(Kicked.send(kicked_id)); |
440 response.add(Kicked.send(kicked_id)); |
357 let result = room_control.leave_room(); |
441 let result = room_control.leave_room(); |
358 get_room_leave_result( |
442 super::common::get_room_leave_result( |
359 room_control.server(), |
443 room_control.server(), |
360 room_control.room(), |
444 room_control.room(), |
361 "kicked", |
445 "kicked", |
362 result, |
446 result, |
363 response, |
447 response, |
364 ); |
448 ); |
365 } |
449 } |
366 } |
450 } |
367 } |
451 } |
368 } |
452 VoteType::Map(None) => (), |
369 VoteType::Map(None) => (), |
453 VoteType::Map(Some(name)) => { |
370 VoteType::Map(Some(name)) => { |
454 if let Some(location) = room_control.load_config(&name) { |
371 if let Some(location) = server.room_mut(room_id).load_config(&name) { |
455 let msg = server_chat(location.to_string()); |
372 response.add( |
456 let room = room_control.room(); |
373 server_chat(location.to_string()) |
457 response.add(msg.send_all().in_room(room.id)); |
374 .send_all() |
458 |
375 .in_room(room_id), |
459 let room_master = room.master_id.map(|id| room_control.server().client(id)); |
376 ); |
460 |
377 let room = &server.room(room_id); |
461 super::common::get_room_update(None, room, room_master, response); |
378 let room_master = if let Some(id) = room.master_id { |
462 |
379 Some(server.client(id)) |
463 for client_id in room_control.server().room_clients(room.id) { |
380 } else { |
464 super::common::get_room_config(room, client_id, response); |
381 None |
|
382 }; |
|
383 get_room_update(None, room, room_master, response); |
|
384 |
|
385 for client in server.iter_clients() { |
|
386 if client.room_id == Some(room_id) { |
|
387 super::common::get_room_config(server.room(room_id), client.id, response); |
|
388 } |
465 } |
389 } |
466 } |
390 } |
467 } |
391 } |
468 VoteType::Pause => { |
392 VoteType::Pause => { |
469 if room_control.toggle_pause() { |
393 if let Some(ref mut info) = server.room_mut(room_id).game_info { |
470 response.add( |
394 info.is_paused = !info.is_paused; |
471 server_chat("Pause toggled.".to_string()) |
395 response.add( |
472 .send_all() |
396 server_chat("Pause toggled.".to_string()) |
473 .in_room(room_id), |
397 .send_all() |
474 ); |
398 .in_room(room_id), |
475 response.add( |
|
476 ForwardEngineMessage(vec![to_engine_msg(once(b'I'))]) |
|
477 .send_all() |
|
478 .in_room(room_id), |
|
479 ); |
|
480 } |
|
481 } |
|
482 VoteType::NewSeed => { |
|
483 let seed = thread_rng().gen_range(0, 1_000_000_000).to_string(); |
|
484 let cfg = GameCfg::Seed(seed); |
|
485 response.add(cfg.to_server_msg().send_all().in_room(room_id)); |
|
486 room_control.set_config(cfg); |
|
487 } |
|
488 VoteType::HedgehogsPerTeam(number) => { |
|
489 let nicks = room_control.set_hedgehogs_number(number); |
|
490 response.extend( |
|
491 nicks |
|
492 .into_iter() |
|
493 .map(|n| HedgehogsNumber(n, number).send_all().in_room(room_id)), |
399 ); |
494 ); |
400 response.add( |
|
401 ForwardEngineMessage(vec![to_engine_msg(once(b'I'))]) |
|
402 .send_all() |
|
403 .in_room(room_id), |
|
404 ); |
|
405 } |
|
406 } |
|
407 VoteType::NewSeed => { |
|
408 let seed = thread_rng().gen_range(0, 1_000_000_000).to_string(); |
|
409 let cfg = GameCfg::Seed(seed); |
|
410 response.add(cfg.to_server_msg().send_all().in_room(room_id)); |
|
411 server.room_mut(room_id).set_config(cfg); |
|
412 } |
|
413 VoteType::HedgehogsPerTeam(number) => { |
|
414 let r = server.room_mut(room_id); |
|
415 let nicks = r.set_hedgehogs_number(number); |
|
416 |
|
417 response.extend( |
|
418 nicks |
|
419 .into_iter() |
|
420 .map(|n| HedgehogsNumber(n, number).send_all().in_room(room_id)), |
|
421 ); |
|
422 } |
|
423 } |
|
424 } |
|
425 |
|
426 fn add_vote(room: &mut HwRoom, response: &mut Response, vote: Vote) -> Option<bool> { |
|
427 let client_id = response.client_id; |
|
428 let mut result = None; |
|
429 |
|
430 if let Some(ref mut voting) = room.voting { |
|
431 if vote.is_forced || voting.votes.iter().all(|(id, _)| client_id != *id) { |
|
432 response.add(server_chat("Your vote has been counted.".to_string()).send_self()); |
|
433 voting.votes.push((client_id, vote.is_pro)); |
|
434 let i = voting.votes.iter(); |
|
435 let pro = i.clone().filter(|(_, v)| *v).count(); |
|
436 let contra = i.filter(|(_, v)| !*v).count(); |
|
437 let success_quota = voting.voters.len() / 2 + 1; |
|
438 if vote.is_forced && vote.is_pro || pro >= success_quota { |
|
439 result = Some(true); |
|
440 } else if vote.is_forced && !vote.is_pro || contra > voting.voters.len() - success_quota |
|
441 { |
|
442 result = Some(false); |
|
443 } |
|
444 } else { |
|
445 response.add(server_chat("You already have voted.".to_string()).send_self()); |
|
446 } |
|
447 } else { |
|
448 response.add(server_chat("There's no voting going on.".to_string()).send_self()); |
|
449 } |
|
450 |
|
451 result |
|
452 } |
|
453 |
|
454 pub fn submit_vote(server: &mut HwServer, vote: Vote, response: &mut Response) { |
|
455 let client_id = response.client_id; |
|
456 let client = server.client(client_id); |
|
457 |
|
458 if let Some(room_id) = client.room_id { |
|
459 let room = server.room_mut(room_id); |
|
460 |
|
461 if let Some(res) = add_vote(room, response, vote) { |
|
462 response.add( |
|
463 server_chat("Voting closed.".to_string()) |
|
464 .send_all() |
|
465 .in_room(room.id), |
|
466 ); |
|
467 let voting = replace(&mut room.voting, None).unwrap(); |
|
468 if res { |
|
469 apply_voting_result(server, room_id, response, voting.kind); |
|
470 } |
495 } |
471 } |
496 } |
472 } |
497 } |
473 } |
498 } |
474 |
499 |