1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
//! Arbitrary data sent by the server that gets temporarily stored on the
//! client.
use std::collections::HashMap;
use azalea_protocol::packets::{
config,
game::{self},
login,
};
use azalea_registry::identifier::Identifier;
use bevy_app::{App, Plugin};
use bevy_ecs::{
component::Component,
entity::Entity,
event::EntityEvent,
observer::On,
system::{Commands, Query},
};
use tracing::warn;
use crate::{
InConfigState, InGameState,
packet::{
config::SendConfigPacketEvent,
game::SendGamePacketEvent,
login::{InLoginState, SendLoginPacketEvent},
},
};
pub struct CookiesPlugin;
impl Plugin for CookiesPlugin {
fn build(&self, app: &mut App) {
app.add_observer(handle_request_cookie)
.add_observer(handle_store_cookie);
}
}
/// A component that holds arbitrary data sent by the server, that our client
/// temporarily stores and persists across transfers.
#[derive(Component, Default)]
pub struct ServerCookies {
pub map: HashMap<Identifier, Vec<u8>>,
}
#[derive(EntityEvent)]
pub struct RequestCookieEvent {
pub entity: Entity,
pub key: Identifier,
}
#[derive(EntityEvent)]
pub struct StoreCookieEvent {
pub entity: Entity,
pub key: Identifier,
pub payload: Vec<u8>,
}
#[allow(clippy::type_complexity)]
pub fn handle_request_cookie(
request_cookie: On<RequestCookieEvent>,
mut commands: Commands,
query: Query<(
Option<&ServerCookies>,
Option<&InGameState>,
Option<&InConfigState>,
Option<&InLoginState>,
)>,
) {
let Ok((server_cookies, in_game_state, in_config_state, in_login_state)) =
query.get(request_cookie.entity)
else {
return;
};
let key = request_cookie.key.clone();
let payload = server_cookies.and_then(|c| c.map.get(&key)).cloned();
if in_game_state.is_some() {
commands.trigger(SendGamePacketEvent::new(
request_cookie.entity,
game::ServerboundCookieResponse { key, payload },
));
} else if in_config_state.is_some() {
commands.trigger(SendConfigPacketEvent::new(
request_cookie.entity,
config::ServerboundCookieResponse { key, payload },
));
} else if in_login_state.is_some() {
commands.trigger(SendLoginPacketEvent::new(
request_cookie.entity,
login::ServerboundCookieResponse { key, payload },
));
} else {
warn!("got RequestCookieEvent while in an unknown state")
}
}
pub fn handle_store_cookie(
store_cookie: On<StoreCookieEvent>,
mut query: Query<&mut ServerCookies>,
) {
if let Ok(mut server_cookies) = query.get_mut(store_cookie.entity) {
server_cookies
.map
.insert(store_cookie.key.clone(), store_cookie.payload.clone());
} else {
warn!("got StoreCookieEvent for a client without ServerCookies")
}
}
|