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