Skip to main content

yog_event/
service.rs

1//! Services on the bus: whoever provides an address (the host, the runtime,
2//! a Yog mod, a Java mod) answers calls to it with a reply.
3
4use yog_data::{Schema, Shape};
5use yog_ids as ids;
6
7use crate::message::{Message, branch, last_segment};
8use crate::{
9    block, bus, client, command, content, entity, game, item, key_binding, media, menu, mirror,
10};
11
12/// A call the bus carries: its payload is `Self`, its answer a [`Service::Reply`].
13pub trait Service: Message {
14    /// Where it's provided.
15    const ADDRESS: &'static str;
16    /// The field whose value picks the provider's branch (`block_id`: each
17    /// block answers its own), if it's keyed — see [`crate::keyed`].
18    const KEY: Option<&'static str>;
19    /// What the provider answers.
20    type Reply: Schema;
21
22    /// The key field's value, if it's keyed.
23    fn key(&self) -> Option<&str>;
24
25    /// Where this call goes: the address, or its branch for the key.
26    fn target(&self) -> String {
27        crate::message::target(Self::ADDRESS, self.key())
28    }
29
30    /// [`Service::target`]'s number — the type's own address cached.
31    fn address(&self) -> crate::Address;
32}
33
34/// A service's descriptor: its domain and name, address and shapes.
35pub struct ServiceInfo {
36    /// Its place in the tree: `block`, `world`…
37    pub domain: &'static str,
38    pub name: &'static str,
39    pub address: &'static str,
40    pub key: Option<&'static str>,
41    pub shape: Shape,
42    pub reply: Shape,
43    /// The Java host's method answering it (`NativeBridge.<host>`), for an action.
44    pub host: Option<&'static str>,
45}
46
47/// Each domain's actions.
48const ACTIONS: &[fn() -> Vec<ServiceInfo>] = &[
49    crate::advancement::actions,
50    crate::block::actions,
51    crate::bossbar::actions,
52    crate::chat::actions,
53    crate::client::actions,
54    crate::client::local::actions,
55    crate::client::control::actions,
56    crate::entity::actions,
57    crate::game::actions,
58    crate::item::actions,
59    crate::jvm::actions,
60    crate::nanite::actions,
61    crate::net::actions,
62    crate::particle::actions,
63    crate::player::actions,
64    crate::scoreboard::actions,
65    crate::sound::actions,
66    crate::tag::actions,
67    crate::ui::actions,
68    crate::world::actions,
69];
70
71macro_rules! services {
72    ($($ty:path => $address:expr, $reply:ty $(, key = $key:ident)?;)*) => {
73        $(impl Service for $ty {
74            const ADDRESS: &'static str = $address;
75            const KEY: Option<&'static str> = key!($($key)?);
76            type Reply = $reply;
77
78            fn key(&self) -> Option<&str> {
79                key_value!(self, $($key)?)
80            }
81
82            fn address(&self) -> crate::Address {
83                static AT: crate::Cached = crate::Cached::new();
84                crate::address::of(&AT, $address, self.key())
85            }
86        })*
87
88        /// The services the runtime, the mods or the host's own code provide.
89        fn listed() -> Vec<ServiceInfo> {
90            vec![$(ServiceInfo {
91                domain: branch($address, ids::service::PREFIX),
92                name: last_segment(stringify!($ty)),
93                address: $address,
94                key: key!($($key)?),
95                shape: <$ty as Schema>::shape(),
96                reply: <$reply as Schema>::shape(),
97                host: None,
98            }),*]
99        }
100    };
101}
102
103/// Every service, domain by domain: the listed ones, then the actions.
104pub fn services() -> Vec<ServiceInfo> {
105    let mut all = listed();
106    for actions in ACTIONS {
107        all.extend(actions());
108    }
109    all
110}
111
112services! {
113    block::Insert => ids::service_block::INSERT, bool, key = block_id;
114    item::Text => ids::service_item::TEXT, Option<item::Shown>, key = item;
115    item::Picture => ids::service_item::PICTURE, Option<[f32; 2]>, key = item;
116    bus::Descriptor => ids::service_bus::DECLARE, bool;
117    bus::Describe => ids::service_bus::DESCRIBE, Option<bus::Descriptor>;
118    bus::List => ids::service_bus::LIST, Vec<String>;
119    bus::Find => ids::service_bus::FIND, Vec<String>;
120    content::Register => ids::service_content::REGISTER, bool;
121    command::CommandSpec => ids::service_command::DECLARE, bool;
122    command::Declared => ids::service_command::DECLARED, Vec<command::CommandSpec>;
123    menu::MenuEntry => ids::service_menu::DECLARE, bool;
124    menu::Declared => ids::service_menu::DECLARED, Vec<menu::MenuEntry>;
125    key_binding::KeyBindingSpec => ids::service_key_binding::DECLARE, bool;
126    key_binding::Declared => ids::service_key_binding::DECLARED, Vec<key_binding::CategorizedBinding>;
127    entity::Data => ids::service_entity::DATA, Option<entity::DataValue>;
128    entity::SetData => ids::service_entity::SET_DATA, bool;
129    entity::SetDimensions => ids::service_entity::SET_DIMENSIONS, bool;
130    client::EntityData => ids::service_client::ENTITY_DATA, Option<entity::DataValue>;
131    game::Mods => ids::service_game::MODS, Vec<game::ModInfo>;
132    game::ModLoaded => ids::service_game::MOD_LOADED, bool;
133    mirror::Declare => ids::service_mirror::DECLARE, mirror::Declared;
134    mirror::Release => ids::service_mirror::RELEASE, bool;
135    mirror::Provide => ids::service_mirror::PROVIDE, Option<yog_data::Diagnostic>;
136    mirror::Touch => ids::service_mirror::TOUCH, bool;
137    mirror::Keys => ids::service_mirror::KEYS, Vec<u32>;
138    media::Png => ids::service_media::PNG, media::PngBytes;
139}