|
1 use mio; |
|
2 |
|
3 use super::common::rnd_reply; |
|
4 use crate::{ |
|
5 protocol::messages::{ |
|
6 add_flags, remove_flags, server_chat, HWProtocolMessage, HWServerMessage::*, |
|
7 ProtocolFlags as Flags, |
|
8 }, |
|
9 core::{ |
|
10 client::HWClient, |
|
11 server::HWServer, |
|
12 types::{ClientId, ServerVar}, |
|
13 }, |
|
14 utils::is_name_illegal, |
|
15 }; |
|
16 use log::*; |
|
17 use std::{collections::HashSet, convert::identity}; |
|
18 |
|
19 pub fn handle( |
|
20 server: &mut HWServer, |
|
21 client_id: ClientId, |
|
22 response: &mut super::Response, |
|
23 message: HWProtocolMessage, |
|
24 ) { |
|
25 use crate::protocol::messages::HWProtocolMessage::*; |
|
26 match message { |
|
27 CreateRoom(name, password) => { |
|
28 if is_name_illegal(&name) { |
|
29 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()); |
|
30 } else if server.has_room(&name) { |
|
31 response.add( |
|
32 Warning("A room with the same name already exists.".to_string()).send_self(), |
|
33 ); |
|
34 } else { |
|
35 let flags_msg = ClientFlags( |
|
36 add_flags(&[Flags::RoomMaster, Flags::Ready]), |
|
37 vec![server.clients[client_id].nick.clone()], |
|
38 ); |
|
39 |
|
40 let room_id = server.create_room(client_id, name, password); |
|
41 let room = &server.rooms[room_id]; |
|
42 let client = &server.clients[client_id]; |
|
43 |
|
44 response.add( |
|
45 RoomAdd(room.info(Some(&client))) |
|
46 .send_all() |
|
47 .with_protocol(room.protocol_number), |
|
48 ); |
|
49 response.add(RoomJoined(vec![client.nick.clone()]).send_self()); |
|
50 response.add(flags_msg.send_self()); |
|
51 |
|
52 response.add( |
|
53 ClientFlags(add_flags(&[Flags::InRoom]), vec![client.nick.clone()]).send_self(), |
|
54 ); |
|
55 }; |
|
56 } |
|
57 Chat(msg) => { |
|
58 response.add( |
|
59 ChatMsg { |
|
60 nick: server.clients[client_id].nick.clone(), |
|
61 msg, |
|
62 } |
|
63 .send_all() |
|
64 .in_lobby() |
|
65 .but_self(), |
|
66 ); |
|
67 } |
|
68 JoinRoom(name, _password) => { |
|
69 let room = server.rooms.iter().find(|(_, r)| r.name == name); |
|
70 let room_id = room.map(|(_, r)| r.id); |
|
71 |
|
72 let client = &mut server.clients[client_id]; |
|
73 |
|
74 if let Some((_, room)) = room { |
|
75 if client.protocol_number != room.protocol_number { |
|
76 response.add( |
|
77 Warning("Room version incompatible to your Hedgewars version!".to_string()) |
|
78 .send_self(), |
|
79 ); |
|
80 } else if room.is_join_restricted() { |
|
81 response.add( |
|
82 Warning( |
|
83 "Access denied. This room currently doesn't allow joining.".to_string(), |
|
84 ) |
|
85 .send_self(), |
|
86 ); |
|
87 } else if room.players_number == u8::max_value() { |
|
88 response.add(Warning("This room is already full".to_string()).send_self()); |
|
89 } else if let Some(room_id) = room_id { |
|
90 super::common::enter_room(server, client_id, room_id, response); |
|
91 } |
|
92 } else { |
|
93 response.add(Warning("No such room.".to_string()).send_self()); |
|
94 } |
|
95 } |
|
96 Follow(nick) => { |
|
97 if let Some(HWClient { |
|
98 room_id: Some(room_id), |
|
99 .. |
|
100 }) = server.find_client(&nick) |
|
101 { |
|
102 let room = &server.rooms[*room_id]; |
|
103 response.add(Joining(room.name.clone()).send_self()); |
|
104 super::common::enter_room(server, client_id, *room_id, response); |
|
105 } |
|
106 } |
|
107 SetServerVar(var) => { |
|
108 if !server.clients[client_id].is_admin() { |
|
109 response.add(Warning("Access denied.".to_string()).send_self()); |
|
110 } else { |
|
111 match var { |
|
112 ServerVar::MOTDNew(msg) => server.greetings.for_latest_protocol = msg, |
|
113 ServerVar::MOTDOld(msg) => server.greetings.for_old_protocols = msg, |
|
114 ServerVar::LatestProto(n) => server.latest_protocol = n, |
|
115 } |
|
116 } |
|
117 } |
|
118 GetServerVar => { |
|
119 if !server.clients[client_id].is_admin() { |
|
120 response.add(Warning("Access denied.".to_string()).send_self()); |
|
121 } else { |
|
122 let vars: Vec<_> = [ |
|
123 ServerVar::MOTDNew(server.greetings.for_latest_protocol.clone()), |
|
124 ServerVar::MOTDOld(server.greetings.for_old_protocols.clone()), |
|
125 ServerVar::LatestProto(server.latest_protocol), |
|
126 ] |
|
127 .iter() |
|
128 .flat_map(|v| v.to_protocol()) |
|
129 .collect(); |
|
130 response.add(ServerVars(vars).send_self()); |
|
131 } |
|
132 } |
|
133 Rnd(v) => { |
|
134 response.add(rnd_reply(&v).send_self()); |
|
135 } |
|
136 Stats => { |
|
137 let mut protocols: HashSet<_> = server |
|
138 .clients |
|
139 .iter() |
|
140 .map(|(_, c)| c.protocol_number) |
|
141 .chain(server.rooms.iter().map(|(_, r)| r.protocol_number)) |
|
142 .collect(); |
|
143 let mut protocols: Vec<_> = protocols.drain().collect(); |
|
144 protocols.sort(); |
|
145 |
|
146 let mut html = Vec::with_capacity(protocols.len() + 2); |
|
147 |
|
148 html.push("<table>".to_string()); |
|
149 for protocol in protocols { |
|
150 html.push(format!( |
|
151 "<tr><td>{}</td><td>{}</td><td>{}</td></tr>", |
|
152 super::utils::protocol_version_string(protocol), |
|
153 server.protocol_clients(protocol).count(), |
|
154 server.protocol_rooms(protocol).count() |
|
155 )); |
|
156 } |
|
157 html.push("</table>".to_string()); |
|
158 |
|
159 response.add(Warning(html.join("")).send_self()); |
|
160 } |
|
161 List => warn!("Deprecated LIST message received"), |
|
162 _ => warn!("Incorrect command in lobby state"), |
|
163 } |
|
164 } |