1 use super::{ |
1 use super::{ |
2 client::HwClient, |
2 client::HwClient, |
3 indexslab::IndexSlab, |
3 indexslab::IndexSlab, |
4 room::HwRoom, |
4 room::HwRoom, |
5 types::{ClientId, RoomId}, |
5 types::{ClientId, RoomId, ServerVar}, |
6 }; |
6 }; |
7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils}; |
7 use crate::{protocol::messages::HwProtocolMessage::Greeting, utils}; |
8 |
8 |
|
9 use crate::core::server::JoinRoomError::WrongProtocol; |
9 use bitflags::*; |
10 use bitflags::*; |
10 use log::*; |
11 use log::*; |
11 use slab; |
12 use slab; |
12 use std::{borrow::BorrowMut, iter, num::NonZeroU16}; |
13 use std::{borrow::BorrowMut, collections::HashSet, iter, num::NonZeroU16}; |
13 |
14 |
14 type Slab<T> = slab::Slab<T>; |
15 type Slab<T> = slab::Slab<T>; |
|
16 |
|
17 pub enum CreateRoomError { |
|
18 InvalidName, |
|
19 AlreadyExists, |
|
20 } |
|
21 |
|
22 pub enum JoinRoomError { |
|
23 DoesntExist, |
|
24 WrongProtocol, |
|
25 Full, |
|
26 Restricted, |
|
27 } |
|
28 |
|
29 pub struct AccessError(); |
15 |
30 |
16 pub struct HwAnteClient { |
31 pub struct HwAnteClient { |
17 pub nick: Option<String>, |
32 pub nick: Option<String>, |
18 pub protocol_number: Option<NonZeroU16>, |
33 pub protocol_number: Option<NonZeroU16>, |
19 pub server_salt: String, |
34 pub server_salt: String, |
113 &self.greetings.for_latest_protocol |
128 &self.greetings.for_latest_protocol |
114 } |
129 } |
115 } |
130 } |
116 |
131 |
117 #[inline] |
132 #[inline] |
|
133 pub fn get_client_nick(&self, client_id: ClientId) -> &str { |
|
134 &self.clients[client_id].nick |
|
135 } |
|
136 |
|
137 #[inline] |
118 pub fn create_room( |
138 pub fn create_room( |
119 &mut self, |
139 &mut self, |
120 creator_id: ClientId, |
140 creator_id: ClientId, |
121 name: String, |
141 name: String, |
122 password: Option<String>, |
142 password: Option<String>, |
123 ) -> RoomId { |
143 ) -> Result<(&HwClient, &HwRoom), CreateRoomError> { |
124 create_room( |
144 use CreateRoomError::*; |
125 &mut self.clients[creator_id], |
145 if utils::is_name_illegal(&name) { |
126 &mut self.rooms, |
146 Err(InvalidName) |
127 name, |
147 } else if self.has_room(&name) { |
128 password, |
148 Err(AlreadyExists) |
129 ) |
149 } else { |
130 } |
150 Ok(create_room( |
131 |
151 &mut self.clients[creator_id], |
132 #[inline] |
152 &mut self.rooms, |
133 pub fn move_to_room(&mut self, client_id: ClientId, room_id: RoomId) { |
153 name, |
134 move_to_room(&mut self.clients[client_id], &mut self.rooms[room_id]) |
154 password, |
135 } |
155 )) |
136 |
156 } |
|
157 } |
|
158 |
|
159 pub fn join_room( |
|
160 &mut self, |
|
161 client_id: ClientId, |
|
162 room_id: RoomId, |
|
163 ) -> Result<(&HwClient, &HwRoom, impl Iterator<Item = &HwClient> + Clone), JoinRoomError> { |
|
164 use JoinRoomError::*; |
|
165 let room = &mut self.rooms[room_id]; |
|
166 let client = &mut self.clients[client_id]; |
|
167 |
|
168 if client.protocol_number != room.protocol_number { |
|
169 Err(WrongProtocol) |
|
170 } else if room.is_join_restricted() { |
|
171 Err(Restricted) |
|
172 } else if room.players_number == u8::max_value() { |
|
173 Err(Full) |
|
174 } else { |
|
175 move_to_room(client, room); |
|
176 let room_id = room.id; |
|
177 Ok(( |
|
178 &self.clients[client_id], |
|
179 &self.rooms[room_id], |
|
180 self.clients.iter().map(|(_, c)| c), |
|
181 )) |
|
182 } |
|
183 } |
|
184 |
|
185 #[inline] |
|
186 pub fn join_room_by_name( |
|
187 &mut self, |
|
188 client_id: ClientId, |
|
189 room_name: &str, |
|
190 ) -> Result<(&HwClient, &HwRoom, impl Iterator<Item = &HwClient> + Clone), JoinRoomError> { |
|
191 use JoinRoomError::*; |
|
192 let room = self.rooms.iter().find(|(_, r)| r.name == room_name); |
|
193 if let Some((_, room)) = room { |
|
194 let room_id = room.id; |
|
195 self.join_room(client_id, room_id) |
|
196 } else { |
|
197 Err(DoesntExist) |
|
198 } |
|
199 } |
|
200 |
|
201 #[inline] |
|
202 pub fn set_var(&mut self, client_id: ClientId, var: ServerVar) -> Result<(), AccessError> { |
|
203 if self.clients[client_id].is_admin() { |
|
204 match var { |
|
205 ServerVar::MOTDNew(msg) => self.greetings.for_latest_protocol = msg, |
|
206 ServerVar::MOTDOld(msg) => self.greetings.for_old_protocols = msg, |
|
207 ServerVar::LatestProto(n) => self.latest_protocol = n, |
|
208 } |
|
209 Ok(()) |
|
210 } else { |
|
211 Err(AccessError()) |
|
212 } |
|
213 } |
|
214 |
|
215 #[inline] |
|
216 pub fn get_vars(&self, client_id: ClientId) -> Result<[ServerVar; 3], AccessError> { |
|
217 if self.clients[client_id].is_admin() { |
|
218 Ok([ |
|
219 ServerVar::MOTDNew(self.greetings.for_latest_protocol.clone()), |
|
220 ServerVar::MOTDOld(self.greetings.for_old_protocols.clone()), |
|
221 ServerVar::LatestProto(self.latest_protocol), |
|
222 ]) |
|
223 } else { |
|
224 Err(AccessError()) |
|
225 } |
|
226 } |
|
227 |
|
228 pub fn get_used_protocols(&self, client_id: ClientId) -> Result<Vec<u16>, AccessError> { |
|
229 if self.clients[client_id].is_admin() { |
|
230 let mut protocols: HashSet<_> = self |
|
231 .clients |
|
232 .iter() |
|
233 .map(|(_, c)| c.protocol_number) |
|
234 .chain(self.rooms.iter().map(|(_, r)| r.protocol_number)) |
|
235 .collect(); |
|
236 let mut protocols: Vec<_> = protocols.drain().collect(); |
|
237 protocols.sort(); |
|
238 Ok(protocols) |
|
239 } else { |
|
240 Err(AccessError()) |
|
241 } |
|
242 } |
|
243 |
|
244 #[inline] |
137 pub fn has_room(&self, name: &str) -> bool { |
245 pub fn has_room(&self, name: &str) -> bool { |
138 self.find_room(name).is_some() |
246 self.find_room(name).is_some() |
139 } |
247 } |
140 |
248 |
|
249 #[inline] |
141 pub fn find_room(&self, name: &str) -> Option<&HwRoom> { |
250 pub fn find_room(&self, name: &str) -> Option<&HwRoom> { |
142 self.rooms |
251 self.rooms |
143 .iter() |
252 .iter() |
144 .find_map(|(_, r)| Some(r).filter(|r| r.name == name)) |
253 .find_map(|(_, r)| Some(r).filter(|r| r.name == name)) |
145 } |
254 } |
232 let entry = rooms.vacant_entry(); |
341 let entry = rooms.vacant_entry(); |
233 let room = HwRoom::new(entry.key()); |
342 let room = HwRoom::new(entry.key()); |
234 entry.insert(room) |
343 entry.insert(room) |
235 } |
344 } |
236 |
345 |
237 fn create_room( |
346 fn create_room<'a, 'b>( |
238 client: &mut HwClient, |
347 client: &'a mut HwClient, |
239 rooms: &mut Slab<HwRoom>, |
348 rooms: &'b mut Slab<HwRoom>, |
240 name: String, |
349 name: String, |
241 password: Option<String>, |
350 password: Option<String>, |
242 ) -> RoomId { |
351 ) -> (&'a HwClient, &'b HwRoom) { |
243 let room = allocate_room(rooms); |
352 let room = allocate_room(rooms); |
244 |
353 |
245 room.master_id = Some(client.id); |
354 room.master_id = Some(client.id); |
246 room.name = name; |
355 room.name = name; |
247 room.password = password; |
356 room.password = password; |