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