175 ), |
175 ), |
176 map( |
176 map( |
177 preceded(pair(tag_no_case("HEDGEHOGS"), spaces), u8_line), |
177 preceded(pair(tag_no_case("HEDGEHOGS"), spaces), u8_line), |
178 VoteType::HedgehogsPerTeam, |
178 VoteType::HedgehogsPerTeam, |
179 ), |
179 ), |
180 map( |
180 map(preceded(tag_no_case("MAP"), opt_space_arg), VoteType::Map), |
181 preceded(tag_no_case("MAP"), opt_space_arg), |
|
182 VoteType::Map, |
|
183 ), |
|
184 ))(input) |
181 ))(input) |
185 } |
182 } |
186 |
183 |
187 fn no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
184 fn no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
188 fn messagec<'a>( |
185 fn message<'a>( |
189 input: &'a [u8], |
|
190 name: &'a str, |
186 name: &'a str, |
191 msg: HwProtocolMessage, |
187 msg: HwProtocolMessage, |
192 ) -> HwResult<'a, HwProtocolMessage> { |
188 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
193 map(tag(name), |_| msg.clone())(input) |
189 move |i| map(tag(name), |_| msg.clone())(i) |
194 } |
190 } |
195 |
191 |
196 alt(( |
192 alt(( |
197 |i| messagec(i, "PING", Ping), |
193 message("PING", Ping), |
198 |i| messagec(i, "PONG", Pong), |
194 message("PONG", Pong), |
199 |i| messagec(i, "LIST", List), |
195 message("LIST", List), |
200 |i| messagec(i, "BANLIST", BanList), |
196 message("BANLIST", BanList), |
201 |i| messagec(i, "GET_SERVER_VAR", GetServerVar), |
197 message("GET_SERVER_VAR", GetServerVar), |
202 |i| messagec(i, "TOGGLE_READY", ToggleReady), |
198 message("TOGGLE_READY", ToggleReady), |
203 |i| messagec(i, "START_GAME", StartGame), |
199 message("START_GAME", StartGame), |
204 |i| messagec(i, "TOGGLE_RESTRICT_JOINS", ToggleRestrictJoin), |
200 message("TOGGLE_RESTRICT_JOINS", ToggleRestrictJoin), |
205 |i| messagec(i, "TOGGLE_RESTRICT_TEAMS", ToggleRestrictTeams), |
201 message("TOGGLE_RESTRICT_TEAMS", ToggleRestrictTeams), |
206 |i| messagec(i, "TOGGLE_REGISTERED_ONLY", ToggleRegisteredOnly), |
202 message("TOGGLE_REGISTERED_ONLY", ToggleRegisteredOnly), |
207 ))(input) |
203 ))(input) |
208 } |
204 } |
209 |
205 |
210 fn single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
206 fn single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
211 fn messagec<'a, T, F, G>( |
207 fn message<'a, T, F, G>( |
212 input: &'a [u8], |
|
213 name: &'a str, |
208 name: &'a str, |
214 parser: F, |
209 parser: F, |
215 constructor: G, |
210 constructor: G, |
216 ) -> HwResult<'a, HwProtocolMessage> |
211 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwProtocolMessage> |
217 where |
212 where |
218 F: Fn(&[u8]) -> HwResult<T>, |
213 F: Fn(&[u8]) -> HwResult<T>, |
219 G: Fn(T) -> HwProtocolMessage, |
214 G: Fn(T) -> HwProtocolMessage, |
220 { |
215 { |
221 map(preceded(tag(name), parser), constructor)(input) |
216 map(preceded(tag(name), parser), constructor) |
222 } |
217 } |
223 |
218 |
224 alt(( |
219 alt(( |
225 |i| messagec(i, "NICK\n", a_line, Nick), |
220 message("NICK\n", a_line, Nick), |
226 |i| messagec(i, "INFO\n", a_line, Info), |
221 message("INFO\n", a_line, Info), |
227 |i| messagec(i, "CHAT\n", a_line, Chat), |
222 message("CHAT\n", a_line, Chat), |
228 |i| messagec(i, "PART", opt_arg, Part), |
223 message("PART", opt_arg, Part), |
229 |i| messagec(i, "FOLLOW\n", a_line, Follow), |
224 message("FOLLOW\n", a_line, Follow), |
230 |i| messagec(i, "KICK\n", a_line, Kick), |
225 message("KICK\n", a_line, Kick), |
231 |i| messagec(i, "UNBAN\n", a_line, Unban), |
226 message("UNBAN\n", a_line, Unban), |
232 |i| messagec(i, "EM\n", a_line, EngineMessage), |
227 message("EM\n", a_line, EngineMessage), |
233 |i| messagec(i, "TEAMCHAT\n", a_line, TeamChat), |
228 message("TEAMCHAT\n", a_line, TeamChat), |
234 |i| messagec(i, "ROOM_NAME\n", a_line, RoomName), |
229 message("ROOM_NAME\n", a_line, RoomName), |
235 |i| messagec(i, "REMOVE_TEAM\n", a_line, RemoveTeam), |
230 message("REMOVE_TEAM\n", a_line, RemoveTeam), |
236 |i| messagec(i, "ROUNDFINISHED", opt_arg, |_| RoundFinished), |
231 message("ROUNDFINISHED", opt_arg, |_| RoundFinished), |
237 |i| messagec(i, "PROTO\n", u16_line, Proto), |
232 message("PROTO\n", u16_line, Proto), |
238 |i| messagec(i, "QUIT", opt_arg, Quit), |
233 message("QUIT", opt_arg, Quit), |
239 ))(input) |
234 ))(input) |
240 } |
235 } |
241 |
236 |
242 fn cmd_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
237 fn cmd_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
243 fn cmdc_no_arg<'a>( |
238 fn cmd_no_arg<'a>( |
244 input: &'a [u8], |
|
245 name: &'a str, |
239 name: &'a str, |
246 msg: HwProtocolMessage, |
240 msg: HwProtocolMessage, |
247 ) -> HwResult<'a, HwProtocolMessage> { |
241 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
248 map(tag_no_case(name), |_| msg.clone())(input) |
242 move |i| map(tag_no_case(name), |_| msg.clone())(i) |
249 } |
243 } |
250 |
244 |
251 fn cmdc_single_arg<'a, T, F, G>( |
245 fn cmd_single_arg<'a, T, F, G>( |
252 input: &'a [u8], |
|
253 name: &'a str, |
246 name: &'a str, |
254 parser: F, |
247 parser: F, |
255 constructor: G, |
248 constructor: G, |
256 ) -> HwResult<'a, HwProtocolMessage> |
249 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwProtocolMessage> |
257 where |
250 where |
258 F: Fn(&'a [u8]) -> HwResult<'a, T>, |
251 F: Fn(&'a [u8]) -> HwResult<'a, T>, |
259 G: Fn(T) -> HwProtocolMessage, |
252 G: Fn(T) -> HwProtocolMessage, |
260 { |
253 { |
261 map( |
254 map( |
262 preceded(pair(tag_no_case(name), spaces), parser), |
255 preceded(pair(tag_no_case(name), spaces), parser), |
263 constructor, |
256 constructor, |
264 )(input) |
257 ) |
265 } |
258 } |
266 |
259 |
267 fn cmd_no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
260 fn cmd_no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
268 alt(( |
261 alt(( |
269 |i| cmdc_no_arg(i, "STATS", Stats), |
262 cmd_no_arg("STATS", Stats), |
270 |i| cmdc_no_arg(i, "FIX", Fix), |
263 cmd_no_arg("FIX", Fix), |
271 |i| cmdc_no_arg(i, "UNFIX", Unfix), |
264 cmd_no_arg("UNFIX", Unfix), |
272 |i| cmdc_no_arg(i, "REGISTERED_ONLY", ToggleServerRegisteredOnly), |
265 cmd_no_arg("REGISTERED_ONLY", ToggleServerRegisteredOnly), |
273 |i| cmdc_no_arg(i, "SUPER_POWER", SuperPower), |
266 cmd_no_arg("SUPER_POWER", SuperPower), |
274 ))(input) |
267 ))(input) |
275 } |
268 } |
276 |
269 |
277 fn cmd_single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
270 fn cmd_single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
278 alt(( |
271 alt(( |
279 |i| cmdc_single_arg(i, "RESTART_SERVER", |i| tag("YES")(i), |_| RestartServer), |
272 cmd_single_arg("RESTART_SERVER", |i| tag("YES")(i), |_| RestartServer), |
280 |i| cmdc_single_arg(i, "DELEGATE", a_line, Delegate), |
273 cmd_single_arg("DELEGATE", a_line, Delegate), |
281 |i| cmdc_single_arg(i, "DELETE", a_line, Delete), |
274 cmd_single_arg("DELETE", a_line, Delete), |
282 |i| cmdc_single_arg(i, "SAVEROOM", a_line, SaveRoom), |
275 cmd_single_arg("SAVEROOM", a_line, SaveRoom), |
283 |i| cmdc_single_arg(i, "LOADROOM", a_line, LoadRoom), |
276 cmd_single_arg("LOADROOM", a_line, LoadRoom), |
284 |i| cmdc_single_arg(i, "GLOBAL", a_line, Global), |
277 cmd_single_arg("GLOBAL", a_line, Global), |
285 |i| cmdc_single_arg(i, "WATCH", u32_line, Watch), |
278 cmd_single_arg("WATCH", u32_line, Watch), |
286 |i| cmdc_single_arg(i, "VOTE", yes_no_line, Vote), |
279 cmd_single_arg("VOTE", yes_no_line, Vote), |
287 |i| cmdc_single_arg(i, "FORCE", yes_no_line, ForceVote), |
280 cmd_single_arg("FORCE", yes_no_line, ForceVote), |
288 |i| cmdc_single_arg(i, "INFO", a_line, Info), |
281 cmd_single_arg("INFO", a_line, Info), |
289 |i| cmdc_single_arg(i, "MAXTEAMS", u8_line, MaxTeams), |
282 cmd_single_arg("MAXTEAMS", u8_line, MaxTeams), |
290 |i| cmdc_single_arg(i, "CALLVOTE", voting, |v| CallVote(Some(v))), |
283 cmd_single_arg("CALLVOTE", voting, |v| CallVote(Some(v))), |
291 ))(input) |
284 ))(input) |
292 } |
285 } |
293 |
286 |
294 preceded( |
287 preceded( |
295 tag("CMD\n"), |
288 tag("CMD\n"), |
296 alt(( |
289 alt(( |
297 cmd_no_arg_message, |
290 cmd_no_arg_message, |
298 cmd_single_arg_message, |
291 cmd_single_arg_message, |
299 map(tag_no_case("CALLVOTE"), |_| CallVote(None)), |
292 map(tag_no_case("CALLVOTE"), |_| CallVote(None)), |
300 map( |
293 map(preceded(tag_no_case("GREETING"), opt_space_arg), Greeting), |
301 preceded(tag_no_case("GREETING"), opt_space_arg), |
|
302 Greeting, |
|
303 ), |
|
304 map(preceded(tag_no_case("PART"), opt_space_arg), Part), |
294 map(preceded(tag_no_case("PART"), opt_space_arg), Part), |
305 map(preceded(tag_no_case("QUIT"), opt_space_arg), Quit), |
295 map(preceded(tag_no_case("QUIT"), opt_space_arg), Quit), |
306 map( |
296 map( |
307 preceded( |
297 preceded( |
308 tag_no_case("SAVE"), |
298 tag_no_case("SAVE"), |
323 )), |
313 )), |
324 )(input) |
314 )(input) |
325 } |
315 } |
326 |
316 |
327 fn config_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
317 fn config_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
328 fn cfgc_single_arg<'a, T, F, G>( |
318 fn cfg_single_arg<'a, T, F, G>( |
329 input: &'a [u8], |
|
330 name: &'a str, |
319 name: &'a str, |
331 parser: F, |
320 parser: F, |
332 constructor: G, |
321 constructor: G, |
333 ) -> HwResult<'a, GameCfg> |
322 ) -> impl Fn(&'a [u8]) -> HwResult<'a, GameCfg> |
334 where |
323 where |
335 F: Fn(&[u8]) -> HwResult<T>, |
324 F: Fn(&[u8]) -> HwResult<T>, |
336 G: Fn(T) -> GameCfg, |
325 G: Fn(T) -> GameCfg, |
337 { |
326 { |
338 map(preceded(pair(tag(name), newline), parser), constructor)(input) |
327 map(preceded(pair(tag(name), newline), parser), constructor) |
339 } |
328 } |
340 |
329 |
341 let (i, cfg) = preceded( |
330 let (i, cfg) = preceded( |
342 tag("CFG\n"), |
331 tag("CFG\n"), |
343 alt(( |
332 alt(( |
344 |i| cfgc_single_arg(i, "THEME", a_line, GameCfg::Theme), |
333 cfg_single_arg("THEME", a_line, GameCfg::Theme), |
345 |i| cfgc_single_arg(i, "SCRIPT", a_line, GameCfg::Script), |
334 cfg_single_arg("SCRIPT", a_line, GameCfg::Script), |
346 |i| cfgc_single_arg(i, "MAP", a_line, GameCfg::MapType), |
335 cfg_single_arg("MAP", a_line, GameCfg::MapType), |
347 |i| cfgc_single_arg(i, "MAPGEN", u32_line, GameCfg::MapGenerator), |
336 cfg_single_arg("MAPGEN", u32_line, GameCfg::MapGenerator), |
348 |i| cfgc_single_arg(i, "MAZE_SIZE", u32_line, GameCfg::MazeSize), |
337 cfg_single_arg("MAZE_SIZE", u32_line, GameCfg::MazeSize), |
349 |i| cfgc_single_arg(i, "TEMPLATE", u32_line, GameCfg::Template), |
338 cfg_single_arg("TEMPLATE", u32_line, GameCfg::Template), |
350 |i| cfgc_single_arg(i, "FEATURE_SIZE", u32_line, GameCfg::FeatureSize), |
339 cfg_single_arg("FEATURE_SIZE", u32_line, GameCfg::FeatureSize), |
351 |i| cfgc_single_arg(i, "SEED", a_line, GameCfg::Seed), |
340 cfg_single_arg("SEED", a_line, GameCfg::Seed), |
352 |i| cfgc_single_arg(i, "DRAWNMAP", a_line, GameCfg::DrawnMap), |
341 cfg_single_arg("DRAWNMAP", a_line, GameCfg::DrawnMap), |
353 preceded(pair(tag("AMMO"), newline), |i| { |
342 preceded(pair(tag("AMMO"), newline), |i| { |
354 let (i, name) = a_line(i)?; |
343 let (i, name) = a_line(i)?; |
355 let (i, value) = opt_arg(i)?; |
344 let (i, value) = opt_arg(i)?; |
356 Ok((i, GameCfg::Ammo(name, value))) |
345 Ok((i, GameCfg::Ammo(name, value))) |
357 }), |
346 }), |