Skip to main content

yog_api/
lib.rs

1//! Yog API — the single crate mod authors depend on.
2//!
3//! A facade that re-exports every Yog domain plus the central [`Registry`] hub.
4//! Add a new domain crate, re-export it here, and mods pick it up via
5//! `yog_api::*`. Items are available both flat (`yog_api::Registry`) and
6//! namespaced by domain (`yog_api::world::World`).
7
8mod interop;
9mod registry;
10
11pub use interop::Interop;
12pub use registry::{installed_mods, open_ui, server, CServer, Mod, ModInfo, Registry};
13pub use yog_gfx::{GfxContext, core as gfx_core, gl as gfx_gl, draw2d as gfx_draw2d};
14
15/// Stable C ABI — re-exported so mods don't need a direct `yog-abi` dependency.
16pub use yog_abi::{ABI_VERSION, YogApi};
17
18#[doc(hidden)]
19pub use std::os::raw::c_void as __c_void;
20
21/// Export a [`Mod`] as a dynamically loadable Yog mod.
22///
23/// Generates the two C-ABI entry points the runtime looks up:
24/// - `yog_abi_version() -> u32`  — version check before loading
25/// - `yog_mod_register(*const YogApi, *const c_char)` — registration entry point,
26///   receives the mod's `id` from its manifest
27///
28/// Put this once at the crate root of a `cdylib` mod:
29///
30/// ```ignore
31/// yog_api::export_mod!(MyMod);
32/// ```
33#[macro_export]
34macro_rules! export_mod {
35    ($mod_ty:ty) => {
36        #[no_mangle]
37        pub extern "C" fn yog_abi_version() -> u32 {
38            $crate::ABI_VERSION
39        }
40
41        #[no_mangle]
42        pub unsafe extern "C" fn yog_mod_register(
43            api: *const $crate::YogApi,
44            mod_id_ptr: *const ::std::os::raw::c_char,
45        ) {
46            // Parse mod_id from the C string passed by the runtime.
47            let mod_id: &str = if mod_id_ptr.is_null() {
48                "unknown"
49            } else {
50                match ::std::ffi::CStr::from_ptr(mod_id_ptr).to_str() {
51                    Ok(s) => s,
52                    Err(_) => "unknown",
53                }
54            };
55            // Store for interop use (yog_api::interop::current_mod_id()).
56            $crate::__set_current_mod_id(mod_id);
57
58            // Catch panics so they never unwind across this `extern "C"` boundary
59            // back into the runtime (which would be undefined behaviour).
60            let outcome = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
61                // SAFETY: the runtime passes a valid YogApi pointer, verified via
62                // yog_abi_version() and abi_version/size checks before this call.
63                let mut registry = unsafe { $crate::Registry::from_raw(api) };
64                <$mod_ty as $crate::Mod>::register(&mut registry);
65            }));
66            if outcome.is_err() {
67                $crate::error!("mod {} panicked during register", ::core::stringify!($mod_ty));
68            }
69        }
70    };
71}
72
73/// Internal: set by `export_mod!` before calling `Mod::register`.
74/// Used by `yog_api::interop::current_mod_id()` so `Interop::export` knows
75/// which mod is calling.
76#[doc(hidden)]
77pub fn __set_current_mod_id(id: &str) {
78    CURRENT_MOD_ID.with(|cell| cell.replace(Some(id.to_string())));
79}
80
81/// Internal: the current mod's id, set during `yog_mod_register`.
82#[doc(hidden)]
83pub fn __current_mod_id() -> Option<String> {
84    CURRENT_MOD_ID.with(|cell| cell.borrow().clone())
85}
86
87std::thread_local! {
88    static CURRENT_MOD_ID: std::cell::RefCell<Option<String>> = std::cell::RefCell::new(None);
89}
90
91pub use yog_command::CommandContext;
92pub use yog_core::{BlockPos, Server};
93pub use yog_event::{
94    AdvancementEvent, AttackEntityEvent, BlockBreakEvent, ChatEvent, ClientTickEvent,
95    ContainerCloseEvent, ContainerOpenEvent, CraftEvent, EntityDamageEvent, EntityDeathEvent,
96    EntityInteractEvent, EntitySpawnEvent, EventPhase, ExplosionEvent,
97    ItemPickupEvent, KeyPressEvent, PlaceBlockEvent, PlayerDeathEvent, PlayerJoinEvent,
98    PlayerLeaveEvent, PlayerMoveEvent, PlayerRespawnEvent, ProjectileHitEvent, ScreenEvent,
99    UseBlockEvent, UseItemEvent,
100};
101pub use yog_entity::Entity;
102pub use yog_network::{Packet, PacketEvent, PacketField};
103#[doc(inline)]
104pub use yog_network::packet;
105pub use yog_player::Player;
106pub use yog_registry::{BlockDef, FoodDef, FurnaceRecipe, ItemDef, ShapedRecipe, ShapelessRecipe, BookRecipe, ItemModifier, AdvancementReward, StartupGrant};
107pub use yog_config::Config;
108pub use yog_storage::{Storage, StorageScope, Value};
109pub use yog_world::World;
110pub use yog_book::{Book, BookCategory, BookEntry, BookPage, BookMacro, BookRegistry};
111pub use yog_book::{BookRenderer, BookFontRegistry};
112pub use yog_book::{text_page, text_page_titled, spotlight_page, crafting_page, smelting_page, image_page, entity_page, relations_page, pattern_page};
113pub use yog_ui::{UiRoot, LayoutNode, Rect, widget, Align, FlexDir, Dock, FocusStyle};
114pub use yog_inventory::{InventoryDef, SlotLayout};
115
116/// Logging macros (`yog_api::info!`, `warn!`, `error!`).
117pub use yog_logging::{error, info, warn};
118
119/// Core types and handles.
120pub mod core {
121    pub use yog_core::*;
122}
123
124/// Events and the subscription registry.
125pub mod event {
126    pub use yog_event::*;
127}
128
129/// World access (block get/set, dimensions).
130pub mod world {
131    pub use yog_world::*;
132}
133
134/// Entity access (teleport, position, health, ... by UUID).
135pub mod entity {
136    pub use yog_entity::*;
137}
138
139/// Player access (give item, teleport).
140pub mod player {
141    pub use yog_player::*;
142}
143
144/// Content registration (custom items / blocks / food).
145pub mod content {
146    pub use yog_registry::*;
147}
148
149/// Networking (raw-byte packets over channels).
150pub mod network {
151    pub use yog_network::*;
152}
153
154/// Commands.
155pub mod command {
156    pub use yog_command::*;
157}
158
159/// Persistent key-value storage for mod data.
160pub mod storage {
161    pub use yog_storage::*;
162}
163
164/// Mod configuration (typed key/value files).
165pub mod config {
166    pub use yog_config::*;
167}
168
169/// In-game book/documentation system (Patchouli-like).
170pub mod book {
171    pub use yog_book::*;
172}
173
174/// UI framework — flexbox layout + widgets on top of yog-gfx.
175pub mod ui {
176    pub use yog_ui::*;
177}
178
179/// Inventory framework — real Container/Menu screens (BlockEntity-backed),
180/// as opposed to `ui`'s HUD-drawn overlays. See `yog-inventory`'s DESIGN.md.
181pub mod inventory {
182    pub use yog_inventory::*;
183}