chunkedge_server/
resource_pack.rs

1use bevy_app::prelude::*;
2use bevy_ecs::prelude::*;
3use chunkedge_protocol::packets::play::{ResourcePackC2s, ResourcePackPushS2c};
4use chunkedge_protocol::text::Text;
5use chunkedge_protocol::{IntoTextComponent, WritePacket};
6use uuid::Uuid;
7
8use crate::client::Client;
9use crate::event_loop::{EventLoopPreUpdate, PacketEvent};
10
11pub struct ResourcePackPlugin;
12
13impl Plugin for ResourcePackPlugin {
14    fn build(&self, app: &mut App) {
15        app.add_event::<ResourcePackStatusEvent>()
16            .add_systems(EventLoopPreUpdate, handle_resource_pack_status);
17    }
18}
19
20#[derive(Event, Copy, Clone, PartialEq, Eq, Debug)]
21pub struct ResourcePackStatusEvent {
22    pub client: Entity,
23    pub status: ResourcePackC2s,
24}
25
26impl Client {
27    /// Requests that the client download and enable a resource pack.
28    ///
29    /// # Arguments
30    /// * `url` - The URL of the resource pack file.
31    /// * `hash` - The SHA-1 hash of the resource pack file. The value must be a
32    ///   40-character hexadecimal string.
33    /// * `forced` - Whether a client should be kicked from the server upon
34    ///   declining the pack (this is enforced client-side)
35    /// * `prompt_message` - A message to be displayed with the resource pack
36    ///   dialog.
37    /// # Returns
38    /// - a [UUID](Uuid) that can be used to identify the resource pack.
39    pub fn set_resource_pack(
40        &mut self,
41        url: &str,
42        hash: &str,
43        forced: bool,
44        prompt_message: Option<Text>,
45    ) -> Uuid {
46        let uuid = Uuid::new_v4();
47
48        self.write_packet(&ResourcePackPushS2c {
49            uuid,
50            url: url.into(),
51            hash: hash.into(),
52            forced,
53            prompt_message: prompt_message.map(|t| t.into_cow_text_component()),
54        });
55
56        uuid
57    }
58
59    /// Requests that the client download and enable a resource pack.
60    ///
61    /// # Arguments
62    /// * `uuid` - The UUID to identify the resource pack.
63    /// * `url` - The URL of the resource pack file.
64    /// * `hash` - The SHA-1 hash of the resource pack file. The value must be a
65    ///   40-character hexadecimal string.
66    /// * `forced` - Whether a client should be kicked from the server upon
67    ///   declining the pack (this is enforced client-side)
68    /// * `prompt_message` - A message to be displayed with the resource pack
69    ///   dialog.
70    pub fn set_resource_pack_with_uuid(
71        &mut self,
72        uuid: Uuid,
73        url: &str,
74        hash: &str,
75        forced: bool,
76        prompt_message: Option<Text>,
77    ) {
78        self.write_packet(&ResourcePackPushS2c {
79            uuid,
80            url: url.into(),
81            hash: hash.into(),
82            forced,
83            prompt_message: prompt_message.map(|t| t.into_cow_text_component()),
84        });
85    }
86}
87
88fn handle_resource_pack_status(
89    mut packets: EventReader<PacketEvent>,
90    mut events: EventWriter<ResourcePackStatusEvent>,
91) {
92    for packet in packets.read() {
93        if let Some(pkt) = packet.decode::<ResourcePackC2s>() {
94            events.send(ResourcePackStatusEvent {
95                client: packet.client,
96                status: pkt,
97            });
98        }
99    }
100}