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::net::actions,
59    crate::particle::actions,
60    crate::player::actions,
61    crate::scoreboard::actions,
62    crate::sound::actions,
63    crate::tag::actions,
64    crate::ui::actions,
65    crate::world::actions,
66];
67
68macro_rules! services {
69    ($($ty:path => $address:expr, $reply:ty $(, key = $key:ident)?;)*) => {
70        $(impl Service for $ty {
71            const ADDRESS: &'static str = $address;
72            const KEY: Option<&'static str> = key!($($key)?);
73            type Reply = $reply;
74
75            fn key(&self) -> Option<&str> {
76                key_value!(self, $($key)?)
77            }
78
79            fn address(&self) -> crate::Address {
80                static AT: crate::Cached = crate::Cached::new();
81                crate::address::of(&AT, $address, self.key())
82            }
83        })*
84
85        /// The services the runtime, the mods or the host's own code provide.
86        fn listed() -> Vec<ServiceInfo> {
87            vec![$(ServiceInfo {
88                domain: branch($address, ids::service::PREFIX),
89                name: last_segment(stringify!($ty)),
90                address: $address,
91                key: key!($($key)?),
92                shape: <$ty as Schema>::shape(),
93                reply: <$reply as Schema>::shape(),
94                host: None,
95            }),*]
96        }
97    };
98}
99
100/// Every service, domain by domain: the listed ones, then the actions.
101pub fn services() -> Vec<ServiceInfo> {
102    let mut all = listed();
103    for actions in ACTIONS {
104        all.extend(actions());
105    }
106    all
107}
108
109services! {
110    block::Insert => ids::service_block::INSERT, bool, key = block_id;
111    item::Text => ids::service_item::TEXT, Option<item::Shown>, key = item;
112    item::Picture => ids::service_item::PICTURE, Option<[f32; 2]>, key = item;
113    bus::Descriptor => ids::service_bus::DECLARE, bool;
114    bus::Describe => ids::service_bus::DESCRIBE, Option<bus::Descriptor>;
115    bus::List => ids::service_bus::LIST, Vec<String>;
116    bus::Find => ids::service_bus::FIND, Vec<String>;
117    content::Register => ids::service_content::REGISTER, bool;
118    command::CommandSpec => ids::service_command::DECLARE, bool;
119    command::Declared => ids::service_command::DECLARED, Vec<command::CommandSpec>;
120    menu::MenuEntry => ids::service_menu::DECLARE, bool;
121    menu::Declared => ids::service_menu::DECLARED, Vec<menu::MenuEntry>;
122    key_binding::KeyBindingSpec => ids::service_key_binding::DECLARE, bool;
123    key_binding::Declared => ids::service_key_binding::DECLARED, Vec<key_binding::CategorizedBinding>;
124    entity::Data => ids::service_entity::DATA, Option<entity::DataValue>;
125    entity::SetData => ids::service_entity::SET_DATA, bool;
126    entity::SetDimensions => ids::service_entity::SET_DIMENSIONS, bool;
127    client::EntityData => ids::service_client::ENTITY_DATA, Option<entity::DataValue>;
128    game::Mods => ids::service_game::MODS, Vec<game::ModInfo>;
129    game::ModLoaded => ids::service_game::MOD_LOADED, bool;
130    mirror::Declare => ids::service_mirror::DECLARE, mirror::Declared;
131    mirror::Release => ids::service_mirror::RELEASE, bool;
132    mirror::Provide => ids::service_mirror::PROVIDE, Option<yog_data::Diagnostic>;
133    mirror::Touch => ids::service_mirror::TOUCH, bool;
134    mirror::Keys => ids::service_mirror::KEYS, Vec<u32>;
135}