bancho_packets/
server.rs

1use crate::*;
2
3packet_struct!(
4    PacketId::BANCHO_USER_LOGIN_REPLY,
5    /// #5: BANCHO_USER_LOGIN_REPLY
6    LoginReply { login_result: LoginResult }
7);
8
9impl From<LoginResult> for LoginReply {
10    fn from(login_result: LoginResult) -> Self {
11        Self { login_result }
12    }
13}
14
15impl LoginReply {
16    #[inline]
17    pub fn success(user_id: i32) -> Self {
18        Self::new(LoginResult::Success(user_id))
19    }
20
21    #[inline]
22    pub fn failed_invalid_credentials() -> Self {
23        Self::new(LoginFailedReason::InvalidCredentials.into())
24    }
25
26    #[inline]
27    pub fn failed_outdated_client() -> Self {
28        Self::new(LoginFailedReason::OutdatedClient.into())
29    }
30
31    #[inline]
32    pub fn failed_user_banned() -> Self {
33        Self::new(LoginFailedReason::UserBanned.into())
34    }
35
36    #[inline]
37    pub fn failed_multiaccount_detected() -> Self {
38        Self::new(LoginFailedReason::MultiaccountDetected.into())
39    }
40
41    #[inline]
42    pub fn failed_server_error() -> Self {
43        Self::new(LoginFailedReason::ServerError.into())
44    }
45
46    #[inline]
47    pub fn failed_cutting_edge_multiplayer() -> Self {
48        Self::new(LoginFailedReason::CuttingEdgeMultiplayer.into())
49    }
50
51    #[inline]
52    pub fn failed_account_password_rest() -> Self {
53        Self::new(LoginFailedReason::AccountPasswordRest.into())
54    }
55
56    #[inline]
57    pub fn failed_verification_required() -> Self {
58        Self::new(LoginFailedReason::VerificationRequired.into())
59    }
60}
61
62packet_struct!(
63    PacketId::BANCHO_SEND_MESSAGE,
64    /// #7: BANCHO_SEND_MESSAGE
65    SendMessage<'a> {
66        sender: CowStr<'a>,
67        content: CowStr<'a>,
68        target: CowStr<'a>,
69        sender_id: i32,
70    }
71);
72
73packet_struct!(
74    PacketId::BANCHO_PONG,
75    /// #8: BANCHO_PONG
76    Pong {}
77);
78
79packet_struct!(
80    PacketId::BANCHO_HANDLE_IRC_CHANGE_USERNAME,
81    /// #9: BANCHO_HANDLE_IRC_CHANGE_USERNAME
82    ChangeUsername<'a> {
83        username_old: CowStr<'a>,
84        username_new: CowStr<'a>,
85    },
86    fn into_packet_data(self) -> Vec<u8> {
87        packet!(
88            Self::ID,
89            format!("{}>>>>{}", self.username_old, self.username_new)
90        )
91    }
92);
93
94packet_struct!(
95    PacketId::BANCHO_USER_STATS,
96    /// #11: BANCHO_USER_STATS
97    UserStats<'a> {
98        user_id: i32,
99        online_status: u8,
100        description: CowStr<'a>,
101        beatmap_md5: CowStr<'a>,
102        mods: u32,
103        mode: u8,
104        beatmap_id: i32,
105        ranked_score: i64,
106        accuracy: f32,
107        playcount: i32,
108        total_score: i64,
109        rank: i32,
110        pp: i16,
111    },
112    fn into_packet_data(self) -> Vec<u8> {
113        packet!(
114            Self::ID,
115            self.user_id,
116            self.online_status,
117            self.description,
118            self.beatmap_md5,
119            self.mods,
120            self.mode,
121            self.beatmap_id,
122            self.ranked_score,
123            self.accuracy / 100f32,
124            self.playcount,
125            self.total_score,
126            self.rank,
127            self.pp
128        )
129    }
130);
131
132packet_struct!(
133    PacketId::BANCHO_USER_LOGOUT,
134    /// #12: BANCHO_USER_LOGOUT
135    UserLogout { user_id: i32 },
136    fn into_packet_data(self) -> Vec<u8> {
137        packet!(Self::ID, self.user_id, 0_u8)
138    }
139);
140
141packet_struct!(
142    PacketId::BANCHO_SPECTATOR_JOINED,
143    /// #13: BANCHO_SPECTATOR_JOINED
144    SpectatorJoined { user_id: i32 }
145);
146
147packet_struct!(
148    PacketId::BANCHO_SPECTATOR_LEFT,
149    /// #14: BANCHO_SPECTATOR_LEFT
150    SpectatorLeft { user_id: i32 }
151);
152
153packet_struct!(
154    PacketId::BANCHO_SPECTATE_FRAMES,
155    /// #15: BANCHO_SPECTATE_FRAMES
156    SpectatorFrames { data: Vec<u8> }
157);
158
159packet_struct!(
160    PacketId::BANCHO_VERSION_UPDATE,
161    /// #19: BANCHO_VERSION_UPDATE
162    VersionUpdate {}
163);
164
165packet_struct!(
166    PacketId::BANCHO_SPECTATOR_CANT_SPECTATE,
167    /// #22: BANCHO_SPECTATOR_CANT_SPECTATE
168    SpectatorCantSpectate { user_id: i32 }
169);
170
171packet_struct!(
172    PacketId::BANCHO_GET_ATTENTION,
173    /// #23: BANCHO_GET_ATTENTION
174    GetAttention {}
175);
176
177packet_struct!(
178    PacketId::BANCHO_NOTIFICATION,
179    /// #24: BANCHO_NOTIFICATION
180    Notification<'a> { msg: CowStr<'a> }
181);
182
183packet_struct!(
184    PacketId::BANCHO_UPDATE_MATCH,
185    /// #26: BANCHO_UPDATE_MATCH
186    UpdateMatch { match_data: MatchData },
187    fn into_packet_data(self) -> Vec<u8> {
188        let data = MatchUpdate { data: self.match_data, send_password: false };
189        packet!(Self::ID, data)
190    }
191);
192
193packet_struct!(
194    PacketId::BANCHO_NEW_MATCH,
195    /// #27: BANCHO_NEW_MATCH
196    NewMatch { match_data: MatchData }
197);
198
199packet_struct!(
200    PacketId::BANCHO_DISBAND_MATCH,
201    /// #28: BANCHO_DISBAND_MATCH
202    DisbandMatch { match_id: i32 }
203);
204
205packet_struct!(
206    PacketId::BANCHO_TOGGLE_BLOCK_NON_FRIEND_DMS,
207    /// #34: BANCHO_TOGGLE_BLOCK_NON_FRIEND_DMS
208    ToggleBlockNonFriendPm {}
209);
210
211packet_struct!(
212    PacketId::BANCHO_MATCH_JOIN_SUCCESS,
213    /// #36: BANCHO_MATCH_JOIN_SUCCESS
214    MatchJoinSuccess { match_data: MatchData }
215);
216
217packet_struct!(
218    PacketId::BANCHO_MATCH_JOIN_FAIL,
219    /// #37: BANCHO_MATCH_JOIN_FAIL
220    MatchJoinFail {}
221);
222
223packet_struct!(
224    PacketId::BANCHO_FELLOW_SPECTATOR_JOINED,
225    /// #42: BANCHO_FELLOW_SPECTATOR_JOINED
226    FellowSpectatorJoined { user_id: i32 }
227);
228
229packet_struct!(
230    PacketId::BANCHO_FELLOW_SPECTATOR_LEFT,
231    /// #43: BANCHO_FELLOW_SPECTATOR_LEFT
232    FellowSpectatorLeft { user_id: i32 }
233);
234
235packet_struct!(
236    PacketId::BANCHO_MATCH_START,
237    /// #46: BANCHO_MATCH_START
238    MatchStart { match_data: MatchData }
239);
240
241packet_struct!(
242    PacketId::BANCHO_MATCH_SCORE_UPDATE,
243    /// #48: BANCHO_MATCH_SCORE_UPDATE
244    MatchScoreUpdate { scoreframe: ScoreFrame }
245);
246
247packet_struct!(
248    PacketId::BANCHO_MATCH_TRANSFER_HOST,
249    /// #50: BANCHO_MATCH_TRANSFER_HOST
250    MatchTransferHost {}
251);
252
253packet_struct!(
254    PacketId::BANCHO_MATCH_ALL_PLAYERS_LOADED,
255    /// #53: BANCHO_MATCH_ALL_PLAYERS_LOADED
256    MatchAllPlayerLoaded {}
257);
258
259packet_struct!(
260    PacketId::BANCHO_MATCH_PLAYER_FAILED,
261    /// #57: BANCHO_MATCH_PLAYER_FAILED
262    MatchPlayerFailed { slot_id: i32 }
263);
264
265packet_struct!(
266    PacketId::BANCHO_MATCH_COMPLETE,
267    /// #58: BANCHO_MATCH_COMPLETE
268    MatchComplete {}
269);
270
271packet_struct!(
272    PacketId::BANCHO_MATCH_SKIP,
273    /// #61: BANCHO_MATCH_SKIP
274    MatchSkip {}
275);
276
277packet_struct!(
278    PacketId::BANCHO_CHANNEL_JOIN_SUCCESS,
279    /// #64: BANCHO_CHANNEL_JOIN_SUCCESS
280    ChannelJoin<'a> { channel_name: CowStr<'a> }
281);
282
283packet_struct!(
284    PacketId::BANCHO_CHANNEL_INFO,
285    /// #65: BANCHO_CHANNEL_INFO
286    ChannelInfo<'a> {
287        name: CowStr<'a>,
288        title: CowStr<'a>,
289        player_count: i16,
290    }
291);
292
293packet_struct!(
294    PacketId::BANCHO_CHANNEL_KICK,
295    /// #66: BANCHO_CHANNEL_KICK
296    ChannelKick<'a> {
297        channel_name: CowStr<'a>
298    }
299);
300
301packet_struct!(
302    PacketId::BANCHO_CHANNEL_AUTO_JOIN,
303    /// #67: BANCHO_CHANNEL_AUTO_JOIN
304    ChannelAutoJoin<'a> {
305        name: CowStr<'a>,
306        title: CowStr<'a>,
307        player_count: i16,
308    }
309);
310
311packet_struct!(
312    PacketId::BANCHO_BEATMAP_INFO_REPLY,
313    /// #69: BANCHO_BEATMAP_INFO_REPLY
314    /// UNUSED
315    BeatmapInfoReply {},
316    fn into_packet_data(self) -> Vec<u8> {
317        unimplemented!()
318    }
319);
320
321packet_struct!(
322    PacketId::BANCHO_PRIVILEGES,
323    /// #71: BANCHO_PRIVILEGES
324    BanchoPrivileges { privileges: i32 }
325);
326
327packet_struct!(
328    PacketId::BANCHO_FRIENDS_LIST,
329    /// #72: BANCHO_FRIENDS_LIST
330    FriendsList<'a> { friends: &'a [i32] }
331);
332
333packet_struct!(
334    PacketId::BANCHO_PROTOCOL_VERSION,
335    /// #75: BANCHO_PROTOCOL_VERSION
336    ProtocolVersion { version: i32 }
337);
338
339packet_struct!(
340    PacketId::BANCHO_MAIN_MENU_ICON,
341    /// #76: BANCHO_MAIN_MENU_ICON
342    MainMenuIcon<'a> {
343        image_url: CowStr<'a>,
344        link_url: CowStr<'a>
345    },
346    fn into_packet_data(self) -> Vec<u8> {
347        packet!(
348            Self::ID,
349            format!("{}|{}", self.image_url, self.link_url)
350        )
351    }
352);
353
354packet_struct!(
355    PacketId::BANCHO_MONITOR,
356    /// #80: BANCHO_MONITOR
357    /// DEPRECATED
358    Monitor {}
359);
360
361packet_struct!(
362    PacketId::BANCHO_MATCH_PLAYER_SKIPPED,
363    /// #81: BANCHO_MATCH_PLAYER_SKIPPED
364    MatchPlayerSkipped { slot_id: i32 }
365);
366
367packet_struct!(
368    PacketId::BANCHO_USER_PRESENCE,
369    /// #83: BANCHO_USER_PRESENCE
370    UserPresence<'a> {
371        user_id: i32,
372        username: CowStr<'a>,
373        utc_offset: u8,
374        country_code: u8,
375        bancho_priv: i32,
376        longitude: f32,
377        latitude: f32,
378        rank: i32,
379    },
380    fn into_packet_data(self) -> Vec<u8> {
381        packet!(
382            Self::ID,
383            self.user_id,
384            self.username,
385            self.utc_offset + 24,
386            self.country_code,
387            self.bancho_priv as u8,
388            self.longitude,
389            self.latitude,
390            self.rank
391        )
392    }
393);
394
395packet_struct!(
396    PacketId::BANCHO_RESTART,
397    /// #86: BANCHO_RESTART
398    BanchoRestart { millis: i32 }
399);
400
401packet_struct!(
402    PacketId::BANCHO_MATCH_INVITE,
403    /// #88: BANCHO_MATCH_INVITE
404    MatchInvite<'a> {
405        welcome: CowStr<'a>,
406        match_id: i32,
407        match_password: Option<CowStr<'a>>,
408    },
409    fn into_packet_data(self) -> Vec<u8> {
410        let data = format!(
411            "{} osump://{}/{}.",
412            self.welcome,
413            self.match_id,
414            self.match_password.unwrap_or(Cow::Borrowed(""))
415        );
416        packet!(
417            Self::ID,
418            data
419        )
420    }
421);
422
423packet_struct!(
424    PacketId::BANCHO_CHANNEL_INFO_END,
425    /// #89: BANCHO_CHANNEL_INFO_END
426    ChannelInfoEnd {}
427);
428
429packet_struct!(
430    PacketId::BANCHO_MATCH_CHANGE_PASSWORD,
431    /// #91: BANCHO_MATCH_CHANGE_PASSWORD
432    MatchChangePassword<'a> {
433        password: CowStr<'a>
434    }
435);
436
437packet_struct!(
438    PacketId::BANCHO_SILENCE_END,
439    /// #92: BANCHO_SILENCE_END
440    SilenceEnd { duration: i32 }
441);
442
443packet_struct!(
444    PacketId::BANCHO_USER_SILENCED,
445    /// #94: BANCHO_USER_SILENCED
446    UserSilenced { user_id: i32 }
447);
448
449packet_struct!(
450    PacketId::BANCHO_USER_PRESENCE_SINGLE,
451    /// #95: BANCHO_USER_PRESENCE_SINGLE
452    UserPresenceSingle { user_id: i32 }
453);
454
455packet_struct!(
456    PacketId::BANCHO_USER_PRESENCE_BUNDLE,
457    /// #96: BANCHO_USER_PRESENCE_BUNDLE
458    UserPresenceBundle<'a> { player_ids: &'a [i32] }
459);
460
461packet_struct!(
462    PacketId::BANCHO_USER_DM_BLOCKED,
463    /// #100: BANCHO_USER_DM_BLOCKED
464    UserDmBlocked<'a> {
465        target: CowStr<'a>
466    },
467    fn into_packet_data(self) -> Vec<u8> {
468        packet!(
469            PacketId::BANCHO_USER_DM_BLOCKED,
470            "", "", self.target, 0_i32
471        )
472    }
473);
474
475packet_struct!(
476    PacketId::BANCHO_TARGET_IS_SILENCED,
477    /// #101: BANCHO_TARGET_IS_SILENCED
478    TargetSilenced<'a> {
479        target: CowStr<'a>
480    },
481    fn into_packet_data(self) -> Vec<u8> {
482        packet!(
483            PacketId::BANCHO_USER_DM_BLOCKED,
484            "", "", self.target, 0_i32
485        )
486    }
487);
488
489packet_struct!(
490    PacketId::BANCHO_VERSION_UPDATE_FORCED,
491    /// #102: BANCHO_VERSION_UPDATE_FORCED
492    VersionUpdateForced {}
493);
494
495packet_struct!(
496    PacketId::BANCHO_SWITCH_SERVER,
497    /// #103: BANCHO_SWITCH_SERVER
498    SwitchServer { time: i32 }
499);
500
501packet_struct!(
502    PacketId::BANCHO_ACCOUNT_RESTRICTED,
503    /// #104: BANCHO_ACCOUNT_RESTRICTED
504    AccountRestricted {}
505);
506
507packet_struct!(
508    PacketId::BANCHO_RTX,
509    /// #105: BANCHO_RTX
510    /// DEPRECATED
511    Rtx<'a> {
512        msg: CowStr<'a>
513    }
514);
515
516packet_struct!(
517    PacketId::BANCHO_MATCH_ABORT,
518    /// #106: BANCHO_MATCH_ABORT
519    MatchAbort {}
520);
521
522packet_struct!(
523    PacketId::BANCHO_SWITCH_TOURNAMENT_SERVER,
524    /// #107: BANCHO_SWITCH_TOURNAMENT_SERVER
525    SwitchTournamentServer<'a> {
526        ip: CowStr<'a>
527    }
528);