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