Skip to main content

yog_abi/
lib.rs

1//! Yog stable C ABI — the ONLY types that cross the mod/runtime boundary.
2//!
3//! Rules this file must never break:
4//!  - Every type is `#[repr(C)]`.
5//!  - No Rust trait objects, no generics, no std types in public structs.
6//!  - New fields are appended only at the END of structs; increment `ABI_MINOR`.
7//!  - ABI_MAJOR bumps only when an existing field is removed or reordered.
8//!
9//! Mods and the runtime are compiled independently; the runtime loads a mod
10//! only when its `ABI_VERSION` is exactly the runtime's.
11
12use std::os::raw::c_void;
13
14// ── Version ──────────────────────────────────────────────────────────────────
15
16pub const ABI_MAJOR: u32 = 1;
17pub const ABI_MINOR: u32 = 4;
18/// `ABI_MAJOR * 10_000 + ABI_MINOR`.  Checked at mod load time.
19pub const ABI_VERSION: u32 = ABI_MAJOR * 10_000 + ABI_MINOR;
20
21// ── Primitive types ───────────────────────────────────────────────────────────
22
23/// Borrowed UTF-8 byte slice passed to a function. NOT null-terminated.
24/// Valid only for the duration of the call that provides it — never store.
25#[repr(C)]
26#[derive(Copy, Clone)]
27pub struct YogStr {
28    pub ptr: *const u8,
29    pub len: u32,
30}
31
32impl YogStr {
33    pub const EMPTY: Self = Self {
34        ptr: std::ptr::null(),
35        len: 0,
36    };
37
38    /// Borrow `s` — not `FromStr`, which can't return a borrowing value.
39    #[allow(clippy::should_implement_trait)]
40    #[inline]
41    pub fn from_str(s: &str) -> Self {
42        Self {
43            ptr: s.as_ptr(),
44            len: s.len() as u32,
45        }
46    }
47
48    #[inline]
49    pub fn is_empty(self) -> bool {
50        self.len == 0 || self.ptr.is_null()
51    }
52
53    /// # Safety
54    ///
55    /// `ptr` must be valid UTF-8 of `len` bytes for at least the duration of
56    /// the call that provided this `YogStr`.
57    #[inline]
58    pub unsafe fn as_str<'a>(self) -> &'a str {
59        unsafe {
60            if self.ptr.is_null() || self.len == 0 {
61                return "";
62            }
63            std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.ptr, self.len as usize))
64        }
65    }
66}
67
68/// Heap-allocated UTF-8 string owned by the RUNTIME.
69/// `ptr == null` encodes `None` / "not found".
70/// When `ptr` is non-null the caller MUST free it via `YogServer::free_str`.
71#[repr(C)]
72#[derive(Copy, Clone)]
73pub struct YogOwnedStr {
74    pub ptr: *mut u8,
75    pub len: u32,
76}
77
78impl YogOwnedStr {
79    pub const NONE: Self = Self {
80        ptr: std::ptr::null_mut(),
81        len: 0,
82    };
83
84    /// Allocate a new `YogOwnedStr` from a Rust `String`.
85    pub fn from_string(s: String) -> Self {
86        let len = s.len() as u32;
87        let ptr = Box::into_raw(s.into_bytes().into_boxed_slice()) as *mut u8;
88        Self { ptr, len }
89    }
90
91    #[inline]
92    pub fn is_none(self) -> bool {
93        self.ptr.is_null()
94    }
95}
96
97/// Integer 3-D block position.
98#[repr(C)]
99#[derive(Copy, Clone)]
100pub struct YogBlockPos {
101    pub x: i32,
102    pub y: i32,
103    pub z: i32,
104}
105
106/// Float 3-D vector (position, velocity, …).
107#[repr(C)]
108#[derive(Copy, Clone)]
109pub struct YogVec3 {
110    pub x: f64,
111    pub y: f64,
112    pub z: f64,
113}
114
115// ── Event structs (Java → Rust) ───────────────────────────────────────────────
116
117#[repr(C)]
118pub struct YogBlockBreakEvent {
119    pub player: YogStr,
120    pub block: YogStr,
121    pub pos: YogBlockPos,
122    /// Dimension the block was broken in, e.g. `minecraft:overworld`.
123    pub dimension: YogStr,
124}
125
126#[repr(C)]
127pub struct YogChatEvent {
128    pub player: YogStr,
129    pub message: YogStr,
130    pub dimension: YogStr,
131}
132
133/// Shared by player_join and player_leave.
134#[repr(C)]
135pub struct YogPlayerEvent {
136    pub player: YogStr,
137    pub uuid: YogStr,
138    pub dimension: YogStr,
139}
140
141#[repr(C)]
142pub struct YogUseItemEvent {
143    pub player: YogStr,
144    pub item: YogStr,
145    /// ABI minor 25: whether the player was sneaking (shift) during use.
146    pub sneaking: bool,
147    pub dimension: YogStr,
148}
149
150#[repr(C)]
151pub struct YogUseBlockEvent {
152    pub player: YogStr,
153    pub block: YogStr,
154    pub pos: YogBlockPos,
155    pub dimension: YogStr,
156}
157
158#[repr(C)]
159pub struct YogAttackEntityEvent {
160    pub player: YogStr,
161    pub target_type: YogStr,
162    pub target_uuid: YogStr,
163    pub dimension: YogStr,
164}
165
166#[repr(C)]
167pub struct YogEntityDamageEvent {
168    pub entity_type: YogStr,
169    pub uuid: YogStr,
170    pub amount: f32,
171    pub source: YogStr,
172    pub dimension: YogStr,
173}
174
175#[repr(C)]
176pub struct YogEntityDeathEvent {
177    pub entity_type: YogStr,
178    pub uuid: YogStr,
179    pub source: YogStr,
180    pub dimension: YogStr,
181}
182
183#[repr(C)]
184pub struct YogEntitySpawnEvent {
185    pub entity_type: YogStr,
186    pub uuid: YogStr,
187    pub dimension: YogStr,
188}
189
190/// Fired when a player dies (Pre: before death is processed; Post: after death).
191/// Pre phase — return false to prevent death (keep entity alive at 0.5 HP).
192#[repr(C)]
193pub struct YogPlayerDeathEvent {
194    pub player: YogStr,
195    pub uuid: YogStr,
196    /// Damage source identifier, e.g. `"player"`, `"fall"`.
197    pub source: YogStr,
198    pub dimension: YogStr,
199}
200
201/// Fired when a player respawns after death.
202#[repr(C)]
203pub struct YogPlayerRespawnEvent {
204    pub player: YogStr,
205    pub uuid: YogStr,
206    /// True if respawning at a bed or anchor, false at world spawn.
207    pub at_anchor: bool,
208    /// Dimension respawned into (may differ from where the player died).
209    pub dimension: YogStr,
210}
211
212/// Fired when a player earns an advancement (Post only).
213#[repr(C)]
214pub struct YogAdvancementEvent {
215    pub player: YogStr,
216    pub uuid: YogStr,
217    /// Namespaced id, e.g. `"minecraft:story/mine_stone"`.
218    pub advancement: YogStr,
219    pub dimension: YogStr,
220}
221
222/// Fired when a player right-clicks (interacts with) an entity (Pre: before; Post: after).
223/// Pre phase — return false to cancel the interaction.
224#[repr(C)]
225pub struct YogEntityInteractEvent {
226    pub player: YogStr,
227    pub player_uuid: YogStr,
228    pub entity_type: YogStr,
229    pub entity_uuid: YogStr,
230    /// `"main_hand"` or `"off_hand"`.
231    pub hand: YogStr,
232    pub dimension: YogStr,
233}
234
235/// Fired when a player takes a crafted item from a crafting output slot (Post only).
236#[repr(C)]
237pub struct YogCraftEvent {
238    pub player: YogStr,
239    pub player_uuid: YogStr,
240    pub result_item: YogStr,
241    pub result_count: u32,
242    pub dimension: YogStr,
243}
244
245/// Fired when an explosion occurs in a world (Pre: before block destruction; Post: after).
246/// Pre phase — return false to cancel the explosion (block and entity damage suppressed).
247#[repr(C)]
248pub struct YogExplosionEvent {
249    pub dimension: YogStr,
250    pub x: f64,
251    pub y: f64,
252    pub z: f64,
253    pub power: f32,
254    /// UUID of the entity that caused the explosion, or empty if world/tnt.
255    pub cause_uuid: YogStr,
256}
257
258// ── ABI minor 9–10 event structs ──────────────────────────────────────────────
259
260/// Fired when a player picks up an item entity (Pre: cancellable; Post: informational).
261#[repr(C)]
262pub struct YogItemPickupEvent {
263    pub player: YogStr,
264    pub player_uuid: YogStr,
265    /// Registry id of the item, e.g. `"minecraft:diamond"`.
266    pub item_id: YogStr,
267    pub item_count: u32,
268    /// UUID of the item entity that was picked up.
269    pub entity_uuid: YogStr,
270    pub dimension: YogStr,
271}
272
273/// Fired when a player sends a movement packet (Post only; very high frequency).
274#[repr(C)]
275pub struct YogPlayerMoveEvent {
276    pub player: YogStr,
277    pub player_uuid: YogStr,
278    pub x: f64,
279    pub y: f64,
280    pub z: f64,
281    pub yaw: f32,
282    pub pitch: f32,
283    pub dimension: YogStr,
284}
285
286/// Fired when a player opens a container screen (Pre: cancellable; Post: informational).
287/// `container_type` is the screen handler registry id, e.g. `"minecraft:chest"`.
288/// Empty string if the type is not in the registry (e.g. the player inventory).
289#[repr(C)]
290pub struct YogContainerOpenEvent {
291    pub player: YogStr,
292    pub player_uuid: YogStr,
293    pub container_type: YogStr,
294    pub dimension: YogStr,
295}
296
297/// Fired when a player closes a container screen (Post only).
298#[repr(C)]
299pub struct YogContainerCloseEvent {
300    pub player: YogStr,
301    pub player_uuid: YogStr,
302    pub dimension: YogStr,
303}
304
305/// Fired when a persistent projectile (arrow, trident) hits a target (Pre: cancellable).
306/// Pre phase — return false to cancel the hit (projectile passes through).
307#[repr(C)]
308pub struct YogProjectileHitEvent {
309    /// Registry id of the projectile, e.g. `"minecraft:arrow"`.
310    pub projectile_type: YogStr,
311    pub projectile_uuid: YogStr,
312    /// UUID of the entity that shot/threw this projectile, or empty.
313    pub shooter_uuid: YogStr,
314    /// `"block"` or `"entity"`.
315    pub hit_type: YogStr,
316    /// UUID of the entity that was hit (empty for block hits).
317    pub hit_entity_uuid: YogStr,
318    pub x: f64,
319    pub y: f64,
320    pub z: f64,
321    pub dimension: YogStr,
322}
323
324/// Fired when a player places a block (Pre: before placement; Post: after).
325#[repr(C)]
326pub struct YogPlaceBlockEvent {
327    pub player: YogStr,
328    pub block: YogStr,
329    pub pos: YogBlockPos,
330    pub dimension: YogStr,
331}
332
333#[repr(C)]
334pub struct YogPacketEvent {
335    pub channel: YogStr,
336    pub player: YogStr, // empty string on client-received packets
337    pub payload: *const u8,
338    pub payload_len: u32,
339}
340
341#[repr(C)]
342pub struct YogCommandEvent {
343    pub name: YogStr,
344    pub args: YogStr,
345    pub source: YogStr,
346    pub uuid: YogStr,
347    /// Empty for console-run commands (no world).
348    pub dimension: YogStr,
349}
350
351/// A startup grant definition — items/books to give on first join.
352#[repr(C)]
353pub struct YogStartupGrantDef {
354    pub id: YogStr,
355    pub items: YogStr,   // '|'-separated item ids
356    pub book: YogStr,    // empty = none
357    pub command: YogStr, // empty = none
358}
359
360// ── Content definition structs (mod → runtime) ────────────────────────────────
361
362#[repr(C)]
363pub struct YogItemDef {
364    pub id: YogStr,
365    pub max_stack: u32,
366    pub name: YogStr,    // empty = no override
367    pub tooltip: YogStr, // empty = none
368    pub max_damage: u32,
369    pub fire_resistant: bool,
370    pub fuel_ticks: u32,
371    pub food_nutrition: u32, // 0 = not a food item
372    pub food_saturation: f32,
373    pub food_always_eat: bool,
374}
375
376#[repr(C)]
377pub struct YogBlockDef {
378    pub id: YogStr,
379    pub hardness: f32,
380    pub resistance: f32,
381    pub name: YogStr,
382    pub light_level: u8,
383    pub sound: YogStr, // empty = default stone sound
384    pub requires_tool: bool,
385    pub no_collision: bool,
386    pub slipperiness: f32,
387    /// Bounding box in pixels: `[x1, y1, z1, x2, y2, z2]`. All zeros = full cube.
388    pub shape: [f32; 6],
389    /// Fence/pipe-style dynamic arm growth toward compatible neighbors — see
390    /// `yog_registry::BlockDef::connects_to_neighbors`.
391    pub connects: bool,
392    /// Comma-joined connection compatibility tags — see
393    /// `yog_registry::BlockDef::connect_groups`. Empty = no tags.
394    pub connect_groups: YogStr,
395    /// Id of a `YogInventoryDef` (registered via `register_inventory`) this
396    /// block is backed by — empty = no inventory (plain block, as before).
397    /// See `yog_inventory`'s DESIGN.md.
398    pub inventory_id: YogStr,
399    /// ABI minor 3: gives off redstone power (`Server::set_redstone_output`).
400    pub redstone_source: bool,
401}
402
403/// An inventory-backed screen definition — see `yog_inventory::InventoryDef`.
404#[repr(C)]
405pub struct YogInventoryDef {
406    pub id: YogStr,
407    pub slot_count: u32,
408    /// `"x:y,x:y,..."` — one pair per slot, in slot-index order. Empty =
409    /// use the default vanilla-style grid (see `yog_inventory::InventoryDef::default_grid`).
410    pub layout: YogStr,
411    pub include_player_inventory: bool,
412    pub player_inv_x: f32,
413    pub player_inv_y: f32,
414    /// Empty = default vanilla-style panel texture.
415    pub background_texture: YogStr,
416    pub title: YogStr,
417    /// Screen size to center the container on — `0.0` (either field) means
418    /// "use the vanilla default (176×166)". Set this to whatever a custom
419    /// `on_ui_render` overlay actually occupies so the real vanilla `Slot`s
420    /// (positioned by `layout`/`player_inv_x/y` relative to `guiLeft`/`guiTop`)
421    /// land under the matching decoration the overlay draws, instead of the
422    /// two disagreeing about where the container's top-left corner is.
423    pub background_w: f32,
424    pub background_h: f32,
425}
426
427// ── ABI minor 10 client event structs ─────────────────────────────────────────
428
429/// Key press / release / repeat from the keyboard (client-side only).
430#[repr(C)]
431#[derive(Copy, Clone)]
432pub struct YogKeyPressEvent {
433    /// GLFW key code (e.g. `GLFW_KEY_E = 69`).
434    pub key_code: i32,
435    pub scan_code: i32,
436    /// 0 = release, 1 = press, 2 = repeat.
437    pub action: i32,
438    /// Modifier bitmask: 1=shift, 2=ctrl, 4=alt, 8=super.
439    pub modifiers: i32,
440}
441
442// ── Handler function-pointer types ────────────────────────────────────────────
443//
444// All event handlers receive a `phase: u8` argument:
445//   0 = Pre  — fires before the action; return value matters (false = cancel).
446//   1 = Post — fires after the action; return value is ignored.
447//
448// This unified signature lets one registered closure handle both phases.
449//
450// Client-side handlers (minor 10) do NOT receive a `YogServer*` — they run on
451// the render thread and have no server context.
452
453pub type YogBlockBreakFn =
454    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogBlockBreakEvent, u8) -> bool;
455pub type YogChatFn =
456    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogChatEvent, u8) -> bool;
457pub type YogPlayerFn =
458    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogPlayerEvent, u8) -> bool;
459pub type YogUseItemFn =
460    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogUseItemEvent, u8) -> bool;
461pub type YogUseBlockFn =
462    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogUseBlockEvent, u8) -> bool;
463pub type YogAttackEntityFn =
464    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogAttackEntityEvent, u8) -> bool;
465pub type YogEntityDamageFn =
466    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogEntityDamageEvent, u8) -> bool;
467pub type YogEntityDeathFn =
468    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogEntityDeathEvent, u8) -> bool;
469pub type YogEntitySpawnFn =
470    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogEntitySpawnEvent, u8) -> bool;
471pub type YogPlaceBlockFn =
472    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogPlaceBlockEvent, u8) -> bool;
473pub type YogPlayerDeathFn =
474    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogPlayerDeathEvent, u8) -> bool;
475pub type YogPlayerRespawnFn =
476    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogPlayerRespawnEvent, u8) -> bool;
477pub type YogAdvancementFn =
478    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogAdvancementEvent, u8) -> bool;
479pub type YogEntityInteractFn =
480    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogEntityInteractEvent, u8) -> bool;
481pub type YogCraftFn =
482    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogCraftEvent, u8) -> bool;
483pub type YogExplosionFn =
484    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogExplosionEvent, u8) -> bool;
485pub type YogItemPickupFn =
486    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogItemPickupEvent, u8) -> bool;
487pub type YogPlayerMoveFn =
488    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogPlayerMoveEvent, u8) -> bool;
489pub type YogContainerOpenFn =
490    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogContainerOpenEvent, u8) -> bool;
491pub type YogContainerCloseFn =
492    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogContainerCloseEvent, u8) -> bool;
493pub type YogProjectileHitFn =
494    unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogProjectileHitEvent, u8) -> bool;
495
496/// Packet events — always Post, no phase.
497pub type YogPacketFn = unsafe extern "C" fn(*mut c_void, *const YogServer, *const YogPacketEvent);
498/// Server lifecycle / tick — no event struct, always fires.
499pub type YogServerFn = unsafe extern "C" fn(*mut c_void, *const YogServer);
500/// Command handler.
501pub type YogCommandFn = unsafe extern "C" fn(
502    ud: *mut c_void,
503    srv: *const YogServer,
504    ev: *const YogCommandEvent,
505    reply_buf: *mut u8,
506    reply_cap: u32,
507    reply_len: *mut u32,
508);
509/// Scheduler handler (once or repeating).
510pub type YogScheduledFn = unsafe extern "C" fn(*mut c_void, *const YogServer);
511
512// ── ABI minor 10 — client-side function pointer types ────────────────────────
513
514/// Client tick — no event, no server context.
515pub type YogClientFn = unsafe extern "C" fn(ud: *mut c_void);
516/// UI event for a `register_ui` screen. `event_id` is one of
517/// `click:X:Y`, `drag:X:Y`, `release:X:Y`, `scroll:DY` and (ABI minor 33)
518/// `key:KEY:MODS` — a GLFW key code pressed or repeating, with GLFW modifier
519/// bits — and `char:CODEPOINT` — a typed character (Unicode scalar value).
520/// Call `YogApi::ui_consume_event` while handling `key:`/`char:` to stop the
521/// host's default handling of that key (Esc closing the screen, ...).
522pub type YogUIEventFn = unsafe extern "C" fn(ud: *mut c_void, ui_id: YogStr, event_id: YogStr);
523/// HUD render — `gfx` is the graphics context for this frame; only valid for
524/// the call duration.  `draw2d_*` functions in `gfx` work here.
525pub type YogHudRenderFn = unsafe extern "C" fn(ud: *mut c_void, gfx: *const YogGfxApi);
526/// World render — `gfx` contains `view_proj` and `camera_pos` for 3D rendering.
527/// Valid only for the call duration.
528pub type YogWorldRenderFn = unsafe extern "C" fn(ud: *mut c_void, gfx: *const YogGfxApi);
529/// Key press — return `false` to cancel (prevent Minecraft from processing the key).
530pub type YogKeyPressFn = unsafe extern "C" fn(ud: *mut c_void, ev: *const YogKeyPressEvent) -> bool;
531/// Screen event — `screen_class` is the simple class name (e.g. `"InventoryScreen"`).
532/// For `on_screen_open` return `false` to prevent the screen from opening.
533pub type YogScreenFn = unsafe extern "C" fn(ud: *mut c_void, screen_class: YogStr) -> bool;
534
535// ── ABI minor 14 — low-level GPU pipeline ────────────────────────────────────
536
537/// Low-level GPU context passed to render handlers.
538///
539/// Provides direct access to the OpenGL pipeline: buffer objects, vertex arrays,
540/// shader programs, textures, draw calls, and render state.
541///
542/// The per-frame fields (`screen_w/h`, `delta_tick`, `view_proj`, `camera_pos`)
543/// are filled by the runtime before calling the handler; the function pointers
544/// point to statically-allocated implementations.
545///
546/// Valid only for the duration of the render callback — never store the pointer.
547/// GPU resource **handles** (`u32`) may be stored between frames.
548///
549/// Colors are `0xAARRGGBB` (Minecraft convention).
550#[repr(C)]
551#[derive(Copy, Clone)]
552pub struct YogGfxApi {
553    // ── Per-frame context ─────────────────────────────────────────────────────
554    /// GUI-pixel screen width.
555    pub screen_w: i32,
556    /// GUI-pixel screen height.
557    pub screen_h: i32,
558    /// Partial-tick interpolation factor (0.0–1.0).
559    pub delta_tick: f32,
560    /// GUI scale factor: physical pixels per GUI pixel (e.g. 2.0 for 2× GUI scale).
561    /// Useful for converting GUI-pixel coordinates to physical pixels for OpenGL calls.
562    pub scale_factor: f32,
563    /// View-projection matrix in camera-relative space (column-major, 16 × f32).
564    /// All zeros during `on_hud_render`; filled during `on_world_render`.
565    pub view_proj: [f32; 16],
566    /// Camera world-space position.  All zeros during `on_hud_render`.
567    pub camera_pos: [f32; 3],
568    /// Local player world-space position (eye height).  All zeros during `on_hud_render`.
569    /// Differs from `camera_pos` in third-person view.
570    pub player_pos: [f32; 3],
571    pub _pad1: f32,
572
573    // ── GPU buffers ───────────────────────────────────────────────────────────
574    /// Allocate a new GPU buffer (VBO / EBO). Returns 0 on failure.
575    pub buf_create: unsafe extern "C" fn() -> u32,
576    /// Delete a buffer created by `buf_create`.
577    pub buf_delete: unsafe extern "C" fn(handle: u32),
578    /// Upload `len` bytes from `bytes` into `handle`.
579    /// `dynamic`: hints frequent updates (`GL_DYNAMIC_DRAW` vs `GL_STATIC_DRAW`).
580    pub buf_data: unsafe extern "C" fn(handle: u32, bytes: *const u8, len: u32, dynamic: bool),
581    /// Overwrite `len` bytes at `offset` in `handle`.
582    pub buf_subdata: unsafe extern "C" fn(handle: u32, offset: u32, bytes: *const u8, len: u32),
583
584    // ── Vertex arrays ─────────────────────────────────────────────────────────
585    /// Create a vertex array object. Returns 0 on failure.
586    pub vao_create: unsafe extern "C" fn() -> u32,
587    /// Delete a VAO created by `vao_create`.
588    pub vao_delete: unsafe extern "C" fn(handle: u32),
589    /// Declare one vertex attribute in `vao`, sourced from `vbo`.
590    /// `dtype`: 0=f32, 1=u8, 2=i32, 3=u32.
591    pub vao_attrib: unsafe extern "C" fn(
592        vao: u32,
593        vbo: u32,
594        index: u32,
595        components: u8,
596        dtype: u8,
597        normalized: bool,
598        stride: u32,
599        offset: u32,
600    ),
601    /// Bind an index buffer (EBO) to `vao`.
602    pub vao_set_ebo: unsafe extern "C" fn(vao: u32, ebo: u32),
603
604    // ── Shader programs ───────────────────────────────────────────────────────
605    /// Compile + link `vert_src` / `frag_src` (GLSL 150 core).
606    /// Writes the program handle to `*out`. Returns false and logs on error.
607    pub prog_create: unsafe extern "C" fn(vert: YogStr, frag: YogStr, out: *mut u32) -> bool,
608    /// Delete a shader program.
609    pub prog_delete: unsafe extern "C" fn(handle: u32),
610    pub prog_uniform_1i: unsafe extern "C" fn(prog: u32, name: YogStr, v: i32),
611    pub prog_uniform_1f: unsafe extern "C" fn(prog: u32, name: YogStr, v: f32),
612    pub prog_uniform_2f: unsafe extern "C" fn(prog: u32, name: YogStr, x: f32, y: f32),
613    pub prog_uniform_3f: unsafe extern "C" fn(prog: u32, name: YogStr, x: f32, y: f32, z: f32),
614    pub prog_uniform_4f:
615        unsafe extern "C" fn(prog: u32, name: YogStr, x: f32, y: f32, z: f32, w: f32),
616    /// Set a mat4 uniform from 16 column-major floats.
617    pub prog_uniform_mat4: unsafe extern "C" fn(prog: u32, name: YogStr, col_major: *const f32),
618
619    // ── Textures ──────────────────────────────────────────────────────────────
620    /// Upload RGBA8 pixel data as a new texture.
621    /// `linear`: `GL_LINEAR` if true, `GL_NEAREST` if false.
622    pub tex_create: unsafe extern "C" fn(w: u32, h: u32, rgba: *const u8, linear: bool) -> u32,
623    /// Delete a texture created by `tex_create`.
624    pub tex_delete: unsafe extern "C" fn(handle: u32),
625    /// Bind `handle` to texture unit `unit` (0–7).
626    pub tex_bind: unsafe extern "C" fn(unit: u32, handle: u32),
627    /// Return the GL texture handle Minecraft uses for a namespaced resource
628    /// (e.g. `"minecraft:textures/gui/icons.png"`). Returns 0 if not found.
629    /// Do **not** delete handles obtained this way — Minecraft owns them.
630    pub tex_from_mc: unsafe extern "C" fn(id: YogStr) -> u32,
631
632    // ── Draw calls ────────────────────────────────────────────────────────────
633    /// Draw `count` primitives from `vao`, using shader `prog`.
634    /// `mode`: 0=Triangles, 1=Lines, 2=LineStrip, 3=TriangleStrip, 4=TriangleFan.
635    pub draw_arrays: unsafe extern "C" fn(vao: u32, prog: u32, mode: u8, first: u32, count: u32),
636    /// Draw indexed primitives.  `ebo` must be bound to `vao` via `vao_set_ebo`.
637    /// `u32_idx`: `true` for `u32` indices, `false` for `u16` indices.
638    pub draw_elements:
639        unsafe extern "C" fn(vao: u32, ebo: u32, prog: u32, mode: u8, count: u32, u32_idx: bool),
640
641    // ── Render state ──────────────────────────────────────────────────────────
642    /// Enable/disable blending. `src`/`dst` are raw GL blend factor enum values.
643    pub set_blend: unsafe extern "C" fn(enabled: bool, src: u32, dst: u32),
644    /// Enable/disable depth testing and depth writes.
645    pub set_depth: unsafe extern "C" fn(test: bool, write: bool),
646    /// Enable scissor clipping (GUI-pixel rectangle).
647    pub set_scissor: unsafe extern "C" fn(x: i32, y: i32, w: i32, h: i32),
648    /// Disable scissor clipping.
649    pub clear_scissor: unsafe extern "C" fn(),
650    /// Set the GL viewport (physical pixel coordinates).
651    pub set_viewport: unsafe extern "C" fn(x: i32, y: i32, w: i32, h: i32),
652
653    // ── 2D convenience (HUD-render only — uses MC's DrawContext) ─────────────
654    /// Filled rectangle. Only valid during `on_hud_render`.
655    pub draw2d_rect: unsafe extern "C" fn(x1: f32, y1: f32, x2: f32, y2: f32, color: u32),
656    /// Vertical-gradient rectangle. Only valid during `on_hud_render`.
657    pub draw2d_gradient:
658        unsafe extern "C" fn(x1: f32, y1: f32, x2: f32, y2: f32, top: u32, bottom: u32),
659    /// MC text renderer string. Only valid during `on_hud_render`.
660    pub draw2d_text: unsafe extern "C" fn(text: YogStr, x: f32, y: f32, color: u32, shadow: bool),
661
662    // ── appended in ABI minor 21 ──────────────────────────────────────────────
663    /// Render an item stack (3D block models included) via MC's item renderer,
664    /// like Patchouli's `renderItemStack`. `id` is a registry item id
665    /// ("minecraft:crafting_table"); `size` is the on-screen size in GUI px
666    /// (16 = inventory size). Only valid during `on_hud_render`.
667    pub draw2d_item: unsafe extern "C" fn(id: YogStr, x: f32, y: f32, size: f32),
668
669    // ── appended in ABI minor 33 ──────────────────────────────────────────────
670    /// `draw2d_text` in the font `font` — a font id such as
671    /// `"minecraft:default"`, `"minecraft:uniform"`, `"minecraft:alt"` or a
672    /// resource-pack font (`"mymod:fancy"`); empty = the default font. Only
673    /// valid during a render callback.
674    pub draw2d_text_font:
675        unsafe extern "C" fn(text: YogStr, font: YogStr, x: f32, y: f32, color: u32, shadow: bool),
676    /// Width in GUI pixels of `text` drawn in `font` (empty = default), as the
677    /// host's text renderer measures it. Callable from the render thread at
678    /// any time (render callbacks and UI event handlers); the pointer stays
679    /// valid for the life of the process.
680    pub text_width: unsafe extern "C" fn(text: YogStr, font: YogStr) -> f32,
681
682    // ── appended in ABI minor 34 ──────────────────────────────────────────────
683    /// Draw the image `source` — a Yog image source (`item:apple`,
684    /// `block:stone`, `sprite:button`, `mymod:gui/logo`, ...; see
685    /// `yog_gfx::image`), resolved by the host for its Minecraft version —
686    /// scaled into `(x, y, w, h)` (GUI pixels, nearest-neighbour). `(u, v,
687    /// uw, vh)` is the part of the image to draw, in the image's own pixels;
688    /// `uw <= 0` or `vh <= 0` = the whole image (items and sprites are
689    /// always whole). `tint` multiplies the colors (`0xAARRGGBB`;
690    /// `0xFFFFFFFF` = none; items ignore it). Only valid during a render
691    /// callback.
692    pub draw2d_image: unsafe extern "C" fn(
693        source: YogStr,
694        x: f32,
695        y: f32,
696        w: f32,
697        h: f32,
698        u: f32,
699        v: f32,
700        uw: f32,
701        vh: f32,
702        tint: u32,
703    ),
704    /// Natural size in GUI pixels of the image `source` (16×16 for items, a
705    /// texture's pixel size, ...) into `*w`/`*h`. `false` (outputs untouched)
706    /// when the source can't be resolved. Callable from the render thread at
707    /// any time; the pointer stays valid for the life of the process.
708    pub image_size: unsafe extern "C" fn(source: YogStr, w: *mut f32, h: *mut f32) -> bool,
709
710    // ── ABI 1.4 ──────────────────────────────────────────────────────────────
711    /// Draws the SVG document `data` scaled into `(x, y, w, h)` GUI pixels
712    /// (rasterized by the host at the screen's resolution, cached).
713    pub draw2d_svg: unsafe extern "C" fn(data: YogStr, x: f32, y: f32, w: f32, h: f32),
714    /// Draws a living entity of type `entity` (`minecraft:zombie`) standing
715    /// in `(x, y, w, h)` GUI pixels, as big as fits, turned `yaw` degrees
716    /// (0 = facing the viewer) and tilted `pitch` degrees.
717    pub draw2d_entity:
718        unsafe extern "C" fn(entity: YogStr, x: f32, y: f32, w: f32, h: f32, yaw: f32, pitch: f32),
719}
720
721unsafe impl Send for YogGfxApi {}
722unsafe impl Sync for YogGfxApi {}
723
724// ── Server action table (runtime → mod direction is wrong; it's mod → runtime) ─
725
726/// All Minecraft-mutating calls available inside a handler.
727///
728/// `ctx` is an opaque pointer to the runtime's JNI state.  Every function takes
729/// it as its first argument.  The pointer is valid for the lifetime of the process.
730///
731/// Strings **returned** by functions in this table are heap-allocated by the
732/// runtime and must be freed with `free_str` after the caller has read them.
733#[repr(C)]
734pub struct YogServer {
735    pub ctx: *mut c_void,
736    pub abi_version: u32,
737    /// `sizeof(YogServer)` at build time — allows mods compiled against an older
738    /// table to detect and skip fields they don't know about.
739    pub size: u32,
740
741    /// Free a string returned by any function in this table.
742    pub free_str: unsafe extern "C" fn(ptr: *mut u8, len: u32),
743
744    // ── chat ─────────────────────────────────────────────────────────────────
745    pub broadcast: unsafe extern "C" fn(ctx: *mut c_void, msg: YogStr),
746
747    // ── world ────────────────────────────────────────────────────────────────
748    pub get_block:
749        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos) -> YogOwnedStr,
750    pub set_block: unsafe extern "C" fn(
751        ctx: *mut c_void,
752        dim: YogStr,
753        pos: YogBlockPos,
754        block: YogStr,
755    ) -> bool,
756    pub world_time: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, out: *mut i64) -> bool,
757    pub set_time: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, time: i64) -> bool,
758    pub is_raining: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr) -> bool,
759    pub set_weather:
760        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, raining: bool, dur: i32) -> bool,
761
762    // ── player ───────────────────────────────────────────────────────────────
763    pub give_item:
764        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, item: YogStr, count: u32) -> bool,
765    pub player_teleport:
766        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, pos: YogVec3) -> bool,
767    pub send_to_player: unsafe extern "C" fn(
768        ctx: *mut c_void,
769        player: YogStr,
770        channel: YogStr,
771        data: *const u8,
772        len: u32,
773    ) -> bool,
774    pub send_to_server:
775        unsafe extern "C" fn(ctx: *mut c_void, channel: YogStr, data: *const u8, len: u32) -> bool,
776    pub kick_player: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, reason: YogStr) -> bool,
777    pub set_gamemode: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, mode: YogStr) -> bool,
778    pub send_title: unsafe extern "C" fn(
779        ctx: *mut c_void,
780        player: YogStr,
781        title: YogStr,
782        sub: YogStr,
783        fi: i32,
784        stay: i32,
785        fo: i32,
786    ) -> bool,
787    pub send_actionbar: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, msg: YogStr) -> bool,
788    pub play_sound: unsafe extern "C" fn(
789        ctx: *mut c_void,
790        dim: YogStr,
791        pos: YogVec3,
792        sound: YogStr,
793        vol: f32,
794        pitch: f32,
795    ) -> bool,
796    pub play_sound_player: unsafe extern "C" fn(
797        ctx: *mut c_void,
798        player: YogStr,
799        sound: YogStr,
800        vol: f32,
801        pitch: f32,
802    ) -> bool,
803
804    // ── entity ───────────────────────────────────────────────────────────────
805    pub entity_teleport: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, pos: YogVec3) -> bool,
806    pub entity_position:
807        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, out: *mut YogVec3) -> bool,
808    pub entity_health: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, out: *mut f32) -> bool,
809    pub entity_set_health: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, hp: f32) -> bool,
810    pub entity_kill: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr) -> bool,
811    pub spawn_entity: unsafe extern "C" fn(
812        ctx: *mut c_void,
813        type_id: YogStr,
814        dim: YogStr,
815        pos: YogVec3,
816    ) -> YogOwnedStr,
817    pub entity_add_effect: unsafe extern "C" fn(
818        ctx: *mut c_void,
819        uuid: YogStr,
820        fx: YogStr,
821        dur: i32,
822        amp: u8,
823        particles: bool,
824    ) -> bool,
825    pub entity_remove_effect:
826        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, fx: YogStr) -> bool,
827    pub entity_clear_effects: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr) -> bool,
828    pub entity_velocity:
829        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, out: *mut YogVec3) -> bool,
830    pub entity_set_velocity:
831        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, vel: YogVec3) -> bool,
832    pub entity_add_velocity:
833        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, vel: YogVec3) -> bool,
834
835    // ── tags & loot ──────────────────────────────────────────────────────────
836    pub has_item_tag: unsafe extern "C" fn(ctx: *mut c_void, item: YogStr, tag: YogStr) -> bool,
837    pub has_block_tag: unsafe extern "C" fn(ctx: *mut c_void, block: YogStr, tag: YogStr) -> bool,
838    pub drop_loot:
839        unsafe extern "C" fn(ctx: *mut c_void, table: YogStr, dim: YogStr, pos: YogVec3) -> bool,
840
841    // ── scoreboard ───────────────────────────────────────────────────────────
842    pub scoreboard_get:
843        unsafe extern "C" fn(ctx: *mut c_void, obj: YogStr, player: YogStr, out: *mut i32) -> bool,
844    pub scoreboard_set:
845        unsafe extern "C" fn(ctx: *mut c_void, obj: YogStr, player: YogStr, score: i32) -> bool,
846    pub scoreboard_add: unsafe extern "C" fn(
847        ctx: *mut c_void,
848        obj: YogStr,
849        player: YogStr,
850        delta: i32,
851        out: *mut i32,
852    ) -> bool,
853
854    // ── boss bar ─────────────────────────────────────────────────────────────
855    pub bossbar_create: unsafe extern "C" fn(
856        ctx: *mut c_void,
857        id: YogStr,
858        title: YogStr,
859        color: YogStr,
860        style: YogStr,
861    ) -> bool,
862    pub bossbar_remove: unsafe extern "C" fn(ctx: *mut c_void, id: YogStr) -> bool,
863    pub bossbar_set_title:
864        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, title: YogStr) -> bool,
865    pub bossbar_set_progress:
866        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, progress: f32) -> bool,
867    pub bossbar_set_color:
868        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, color: YogStr) -> bool,
869    pub bossbar_add_player:
870        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, player: YogStr) -> bool,
871    pub bossbar_remove_player:
872        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, player: YogStr) -> bool,
873    pub bossbar_set_visible:
874        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, visible: bool) -> bool,
875
876    // ── misc ─────────────────────────────────────────────────────────────────
877    pub game_dir: unsafe extern "C" fn(ctx: *mut c_void) -> YogOwnedStr,
878
879    // ── player query (ABI minor 4) ────────────────────────────────────────────
880    /// Newline-separated list of online player names, or NONE if server not up.
881    pub online_players: unsafe extern "C" fn(ctx: *mut c_void) -> YogOwnedStr,
882
883    // ── block entity (NBT, ABI minor 3) ──────────────────────────────────────
884    /// SNBT string of the block entity at `pos`, or NONE if there is none.
885    pub get_block_nbt:
886        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos) -> YogOwnedStr,
887    /// Write SNBT into the block entity at `pos`. Returns false if no block entity exists.
888    pub set_block_nbt:
889        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos, snbt: YogStr) -> bool,
890
891    // ── inventory (ABI minor 3) ───────────────────────────────────────────────
892    /// Tab/newline-encoded inventory: one line per occupied slot, `slot\titem_id\tcount`.
893    pub player_inventory: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr) -> YogOwnedStr,
894    /// Set (or clear when count==0) a specific inventory slot.
895    pub player_set_slot: unsafe extern "C" fn(
896        ctx: *mut c_void,
897        player: YogStr,
898        slot: u32,
899        item_id: YogStr,
900        count: u32,
901    ) -> bool,
902
903    // ── inventory-backed block slots (ABI minor 25, yog-inventory) ──────────
904    /// `"item_id\tcount\tsnbt"` for the given slot of the block container
905    /// at `pos`, or NONE if the slot is empty / there's no container there.
906    pub get_inventory_slot: unsafe extern "C" fn(
907        ctx: *mut c_void,
908        dim: YogStr,
909        pos: YogBlockPos,
910        slot: u32,
911    ) -> YogOwnedStr,
912    /// Set (or clear when count==0) a slot of the block container at `pos`;
913    /// `item_id` may carry the item's SNBT after a tab. Returns false if
914    /// there's no container there.
915    pub set_inventory_slot: unsafe extern "C" fn(
916        ctx: *mut c_void,
917        dim: YogStr,
918        pos: YogBlockPos,
919        slot: u32,
920        item_id: YogStr,
921        count: u32,
922    ) -> bool,
923
924    // ── cross-dimension teleport (ABI minor 3) ────────────────────────────────
925    pub player_teleport_dim:
926        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, dim: YogStr, pos: YogVec3) -> bool,
927    pub entity_teleport_dim:
928        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, dim: YogStr, pos: YogVec3) -> bool,
929
930    // ── entity counting ───────────────────────────────────────────────────────
931    /// Count loaded instances of `entity_type` in `dimension`. Returns -1 on error.
932    pub world_entity_count:
933        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, entity_type: YogStr) -> i32,
934
935    // ── entity NBT (ABI minor 6) ──────────────────────────────────────────────
936    /// SNBT of the entity's persistent data, or NONE if entity not found.
937    pub entity_get_nbt: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr) -> YogOwnedStr,
938    /// Merge SNBT data into the entity. Returns false if entity not found.
939    pub entity_set_nbt: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, snbt: YogStr) -> bool,
940
941    // ── particles (ABI minor 6) ───────────────────────────────────────────────
942    /// Spawn `count` particles at `pos` in `dim`.
943    /// `dx/dy/dz` control spread, `speed` controls particle speed.
944    /// Returns false if the dimension or particle type is unknown.
945    pub spawn_particles: unsafe extern "C" fn(
946        ctx: *mut c_void,
947        dim: YogStr,
948        pos: YogVec3,
949        particle_type: YogStr,
950        count: i32,
951        dx: f64,
952        dy: f64,
953        dz: f64,
954        speed: f64,
955    ) -> bool,
956
957    // ── attributes (ABI minor 7) ──────────────────────────────────────────────
958    /// Get the base value of an attribute on a living entity.
959    /// `attribute_id` is a registry id, e.g. `"minecraft:generic.max_health"`.
960    /// Returns `f64::NAN` if entity or attribute is not found.
961    pub entity_attribute_get:
962        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, attribute_id: YogStr) -> f64,
963    /// Set the base value of an attribute. Returns false if entity or attribute is not found.
964    pub entity_attribute_set: unsafe extern "C" fn(
965        ctx: *mut c_void,
966        uuid: YogStr,
967        attribute_id: YogStr,
968        value: f64,
969    ) -> bool,
970
971    // ── held item NBT (ABI minor 11) ─────────────────────────────────────────
972    /// SNBT of the item currently held in the player's main hand.
973    /// Returns NONE if the player is offline or holding air.
974    pub get_held_item_nbt: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr) -> YogOwnedStr,
975    /// Merge `snbt` data into the NBT of the player's held main-hand item in-place.
976    /// Returns false if the player is offline or holding air.
977    pub set_held_item_nbt:
978        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, snbt: YogStr) -> bool,
979
980    // ── item stack query (ABI minor 12) ──────────────────────────────────────
981    /// SNBT of the item in the player's off hand, or NONE if offline / holding air.
982    pub get_offhand_item_nbt: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr) -> YogOwnedStr,
983    /// Merge `snbt` into the NBT of the player's off-hand item.
984    /// Returns false if offline or holding air.
985    pub set_offhand_item_nbt:
986        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, snbt: YogStr) -> bool,
987    /// Full item stack at inventory `slot`: tab-separated `item_id\tcount\tsnbt`.
988    /// `snbt` is `{}` when the item has no NBT. Returns NONE if offline or slot empty.
989    pub get_slot_item:
990        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, slot: u32) -> YogOwnedStr,
991    /// Replace inventory `slot` with an item stack. `snbt` may be empty to clear NBT.
992    /// Pass `count == 0` to clear the slot (ignores `item_id` and `snbt`).
993    pub set_slot_item: unsafe extern "C" fn(
994        ctx: *mut c_void,
995        player: YogStr,
996        slot: u32,
997        item_id: YogStr,
998        count: u32,
999        snbt: YogStr,
1000    ) -> bool,
1001
1002    // ── entity rotation (ABI minor 25) ───────────────────────────────────────
1003    /// Yaw and pitch (degrees) of an entity by UUID. Returns false if the
1004    /// entity does not exist. `out` receives x=yaw, y=pitch, z=0.
1005    pub entity_rotation:
1006        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, out: *mut YogVec3) -> bool,
1007
1008    // ── world queries & effects (ABI minor 1) ────────────────────────────────
1009    // Records come back as one tab-separated line; `yog_core`'s `EntityInfo`,
1010    // `BlockHit`, `BlockInfo` and `PlayerInfo` document and decode them.
1011    /// `EntityInfo` line of a loaded entity, or NONE.
1012    pub entity_info: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr) -> YogOwnedStr,
1013    /// Newline-separated uuids of the entities touching the box.
1014    pub entities_in_box: unsafe extern "C" fn(
1015        ctx: *mut c_void,
1016        dim: YogStr,
1017        min: YogVec3,
1018        max: YogVec3,
1019    ) -> YogOwnedStr,
1020    /// `BlockHit` line of the first block on the segment, or NONE.
1021    pub raycast_block: unsafe extern "C" fn(
1022        ctx: *mut c_void,
1023        dim: YogStr,
1024        from: YogVec3,
1025        to: YogVec3,
1026    ) -> YogOwnedStr,
1027    /// Uuid of the nearest entity on the segment (not `exclude`), or NONE.
1028    pub raycast_entity: unsafe extern "C" fn(
1029        ctx: *mut c_void,
1030        dim: YogStr,
1031        from: YogVec3,
1032        to: YogVec3,
1033        exclude: YogStr,
1034    ) -> YogOwnedStr,
1035    /// `BlockInfo` line of the block at `pos`, or NONE.
1036    pub block_info:
1037        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos) -> YogOwnedStr,
1038    pub break_block: unsafe extern "C" fn(
1039        ctx: *mut c_void,
1040        dim: YogStr,
1041        pos: YogBlockPos,
1042        drop: bool,
1043        breaker: YogStr,
1044    ) -> bool,
1045    pub place_block_from_slot: unsafe extern "C" fn(
1046        ctx: *mut c_void,
1047        player: YogStr,
1048        slot: u32,
1049        dim: YogStr,
1050        pos: YogBlockPos,
1051    ) -> bool,
1052    pub bonemeal: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos) -> bool,
1053    pub explode: unsafe extern "C" fn(
1054        ctx: *mut c_void,
1055        dim: YogStr,
1056        pos: YogVec3,
1057        power: f32,
1058        fire: bool,
1059        source: YogStr,
1060    ) -> bool,
1061    /// `json` is a JSON text component (the `/tellraw` format).
1062    pub tellraw: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, json: YogStr) -> bool,
1063    pub entity_damage: unsafe extern "C" fn(
1064        ctx: *mut c_void,
1065        uuid: YogStr,
1066        amount: f32,
1067        damage_type: YogStr,
1068        attacker: YogStr,
1069    ) -> bool,
1070    pub entity_set_fire_ticks:
1071        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, ticks: i32) -> bool,
1072    pub player_add_xp: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, amount: i32) -> bool,
1073    pub player_set_may_fly:
1074        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, may_fly: bool) -> bool,
1075    /// `PlayerInfo` line of an online player, or NONE.
1076    pub player_info: unsafe extern "C" fn(ctx: *mut c_void, player: YogStr) -> YogOwnedStr,
1077    /// Uuid of the dropped item entity, or NONE.
1078    pub spawn_item: unsafe extern "C" fn(
1079        ctx: *mut c_void,
1080        dim: YogStr,
1081        pos: YogVec3,
1082        vel: YogVec3,
1083        item_id: YogStr,
1084        count: u32,
1085        snbt: YogStr,
1086    ) -> YogOwnedStr,
1087    /// `item_id\tcount\tsnbt` of a dropped item entity, or NONE.
1088    pub item_entity_stack: unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr) -> YogOwnedStr,
1089    pub item_entity_set_stack: unsafe extern "C" fn(
1090        ctx: *mut c_void,
1091        uuid: YogStr,
1092        item_id: YogStr,
1093        count: u32,
1094        snbt: YogStr,
1095    ) -> bool,
1096    // ── ABI minor 2 ──
1097    /// `json` is a JSON text component.
1098    pub actionbar_json:
1099        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, json: YogStr) -> bool,
1100    /// `face` is a `Direction` ordinal (down, up, north, south, west, east).
1101    pub use_item_on_block: unsafe extern "C" fn(
1102        ctx: *mut c_void,
1103        dim: YogStr,
1104        pos: YogBlockPos,
1105        face: u8,
1106        item_id: YogStr,
1107        player: YogStr,
1108    ) -> bool,
1109    pub pour_fluid: unsafe extern "C" fn(
1110        ctx: *mut c_void,
1111        dim: YogStr,
1112        pos: YogBlockPos,
1113        bucket_item_id: YogStr,
1114    ) -> bool,
1115    pub has_entity_tag:
1116        unsafe extern "C" fn(ctx: *mut c_void, entity_type: YogStr, tag_id: YogStr) -> bool,
1117    /// The block id a block item places, or NONE.
1118    pub item_block: unsafe extern "C" fn(ctx: *mut c_void, item_id: YogStr) -> YogOwnedStr,
1119    pub place_feature: unsafe extern "C" fn(
1120        ctx: *mut c_void,
1121        dim: YogStr,
1122        pos: YogBlockPos,
1123        feature_id: YogStr,
1124    ) -> bool,
1125
1126    // ── ABI minor 3 ──────────────────────────────────────────────────────────
1127    pub set_item_cooldown:
1128        unsafe extern "C" fn(ctx: *mut c_void, player: YogStr, item_id: YogStr, ticks: i32) -> bool,
1129    pub entity_teleport_with_passengers:
1130        unsafe extern "C" fn(ctx: *mut c_void, uuid: YogStr, dim: YogStr, pos: YogVec3) -> bool,
1131    /// Received redstone power 0–15, or -1 (no such dimension).
1132    pub redstone_power: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos) -> i32,
1133    pub set_redstone_output:
1134        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos, level: i32) -> bool,
1135    /// `"ns:id[prop=value,...]"`, or NONE.
1136    pub get_block_state: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos) -> YogOwnedStr,
1137    pub set_block_state:
1138        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, pos: YogBlockPos, state: YogStr) -> bool,
1139    pub world_is_thundering: unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr) -> bool,
1140    pub world_set_thunder:
1141        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, thundering: bool, duration_ticks: i32) -> bool,
1142    /// Sets every block of the box `from..=to` to `state`; how many changed, or -1.
1143    pub fill_region: unsafe extern "C" fn(
1144        ctx: *mut c_void,
1145        dim: YogStr,
1146        from: YogBlockPos,
1147        to: YogBlockPos,
1148        state: YogStr,
1149    ) -> i32,
1150    /// The non-air blocks of the box `from..=to`: `"x y z state"` lines, or NONE.
1151    pub scan_region:
1152        unsafe extern "C" fn(ctx: *mut c_void, dim: YogStr, from: YogBlockPos, to: YogBlockPos) -> YogOwnedStr,
1153}
1154
1155// ctx = *mut JavaVM which is global/stable. All fn ptrs are pure C-ABI.
1156unsafe impl Send for YogServer {}
1157unsafe impl Sync for YogServer {}
1158
1159// ── Chunk generator callback (ABI minor 29) ───────────────────────────────────
1160
1161/// Per-callback context handed to a registered chunk generator (see
1162/// `YogApi::register_chunk_generator`) — mirrors `YogGfxApi`'s pattern of
1163/// bundling per-call context with the function pointer(s) needed to act on
1164/// it. Valid only for the duration of the generator callback.
1165#[repr(C)]
1166#[derive(Copy, Clone)]
1167pub struct YogChunkWriterApi {
1168    /// Chunk X coordinate (in chunks, not blocks).
1169    pub chunk_x: i32,
1170    /// Chunk Z coordinate (in chunks, not blocks).
1171    pub chunk_z: i32,
1172    /// Minimum build height (world Y) for this dimension.
1173    pub min_y: i32,
1174    /// Total world height for this dimension.
1175    pub height: i32,
1176    /// Opaque host-side handle for the chunk currently being generated.
1177    pub ctx: *mut c_void,
1178    /// Set a block within this chunk column. `x`/`z` are local (0..16)
1179    /// chunk-relative coordinates; `y` is world-absolute.
1180    pub set_block:
1181        unsafe extern "C" fn(ctx: *mut c_void, x: i32, y: i32, z: i32, block_id: YogStr) -> bool,
1182}
1183
1184unsafe impl Send for YogChunkWriterApi {}
1185unsafe impl Sync for YogChunkWriterApi {}
1186
1187/// Called by the host once per chunk column that needs generating in the
1188/// registered dimension. `writer` is valid only for the duration of the call.
1189pub type YogChunkGeneratorFn =
1190    unsafe extern "C" fn(ud: *mut c_void, writer: *const YogChunkWriterApi);
1191
1192// ── Registration table (passed to yog_mod_register) ──────────────────────────
1193
1194/// Passed to `yog_mod_register`. Call the function pointers here to register
1195/// handlers, commands, content, and schedulers.
1196///
1197/// When mods compiled against ABI `N` load on a runtime with ABI `M > N`:
1198/// fields beyond `size` are not present in the mod's view — check `size` before
1199/// accessing fields added in later minor versions.
1200#[repr(C)]
1201pub struct YogApi {
1202    pub abi_version: u32,
1203    /// `sizeof(YogApi)` at the runtime's build time.
1204    pub size: u32,
1205    /// Opaque pointer to runtime handler storage.
1206    pub ctx: *mut c_void,
1207    /// Stable server action table — pass to handlers.
1208    pub server: *const YogServer,
1209
1210    // ── events — all handlers receive (ud, srv, event, phase: u8) → bool ────────
1211    // phase 0 = Pre (return false to cancel), phase 1 = Post (return ignored).
1212    pub on_block_break: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogBlockBreakFn),
1213    pub on_chat: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogChatFn),
1214    pub on_player_join: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogPlayerFn),
1215    pub on_player_leave: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogPlayerFn),
1216    pub on_use_item: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogUseItemFn),
1217    pub on_use_block: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogUseBlockFn),
1218    pub on_attack_entity:
1219        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogAttackEntityFn),
1220    pub on_entity_damage:
1221        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogEntityDamageFn),
1222    pub on_entity_death:
1223        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogEntityDeathFn),
1224    pub on_entity_spawn:
1225        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogEntitySpawnFn),
1226    pub on_player_place_block:
1227        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogPlaceBlockFn),
1228    pub on_player_death:
1229        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogPlayerDeathFn),
1230    pub on_player_respawn:
1231        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogPlayerRespawnFn),
1232    pub on_advancement:
1233        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogAdvancementFn),
1234    // ── ABI minor 8 ──────────────────────────────────────────────────────────
1235    pub on_entity_interact:
1236        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogEntityInteractFn),
1237    pub on_item_craft: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogCraftFn),
1238    pub on_explosion: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogExplosionFn),
1239    // ── ABI minor 9 ──────────────────────────────────────────────────────────
1240    pub on_item_pickup: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogItemPickupFn),
1241    pub on_player_move: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogPlayerMoveFn),
1242    pub on_container_open:
1243        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogContainerOpenFn),
1244    pub on_container_close:
1245        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogContainerCloseFn),
1246    pub on_projectile_hit:
1247        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogProjectileHitFn),
1248    pub on_server_tick: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogServerFn),
1249    pub on_server_started: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogServerFn),
1250    pub on_server_stopping: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogServerFn),
1251
1252    // ── networking ───────────────────────────────────────────────────────────
1253    pub on_packet:
1254        unsafe extern "C" fn(ctx: *mut c_void, channel: YogStr, ud: *mut c_void, h: YogPacketFn),
1255    pub on_client_packet:
1256        unsafe extern "C" fn(ctx: *mut c_void, channel: YogStr, ud: *mut c_void, h: YogPacketFn),
1257
1258    // ── commands ─────────────────────────────────────────────────────────────
1259    pub register_command:
1260        unsafe extern "C" fn(ctx: *mut c_void, name: YogStr, ud: *mut c_void, h: YogCommandFn),
1261    pub register_typed_command: unsafe extern "C" fn(
1262        ctx: *mut c_void,
1263        name: YogStr,
1264        schema: YogStr,
1265        ud: *mut c_void,
1266        h: YogCommandFn,
1267    ),
1268
1269    // ── recipes ──────────────────────────────────────────────────────────────
1270    /// Register a recipe by supplying Minecraft JSON (`data/` format).
1271    /// `namespace` + `name` form the file path: `data/{ns}/recipes/{name}.json`.
1272    pub register_recipe_json:
1273        unsafe extern "C" fn(ctx: *mut c_void, namespace: YogStr, name: YogStr, json: YogStr),
1274
1275    // ── content ──────────────────────────────────────────────────────────────
1276    pub register_item: unsafe extern "C" fn(ctx: *mut c_void, def: *const YogItemDef),
1277    pub register_block: unsafe extern "C" fn(ctx: *mut c_void, def: *const YogBlockDef),
1278
1279    // ── scheduler ────────────────────────────────────────────────────────────
1280    pub schedule_once: unsafe extern "C" fn(
1281        ctx: *mut c_void,
1282        delay_ticks: u64,
1283        ud: *mut c_void,
1284        h: YogScheduledFn,
1285    ),
1286    pub schedule_repeating: unsafe extern "C" fn(
1287        ctx: *mut c_void,
1288        period_ticks: u64,
1289        ud: *mut c_void,
1290        h: YogScheduledFn,
1291    ),
1292
1293    // ── ABI minor 10 — client-side events ────────────────────────────────────
1294    pub on_client_tick: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogClientFn),
1295    pub on_hud_render: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogHudRenderFn),
1296    pub on_key_press: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogKeyPressFn),
1297    pub on_screen_open: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogScreenFn),
1298    pub on_screen_close: unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogScreenFn),
1299
1300    // ── ABI minor 14 — world render ──────────────────────────────────────────
1301    /// Register a handler that fires after world geometry is rendered.
1302    /// `gfx.view_proj` and `gfx.camera_pos` are filled; use them to project
1303    /// custom 3D geometry into clip space.
1304    pub on_world_render:
1305        unsafe extern "C" fn(ctx: *mut c_void, ud: *mut c_void, h: YogWorldRenderFn),
1306
1307    // ── ABI minor 16 — startup grants ────────────────────────────────────────
1308    pub register_startup_grant:
1309        unsafe extern "C" fn(ctx: *mut c_void, grant: *const YogStartupGrantDef),
1310
1311    // ── ABI minor 18 — books ─────────────────────────────────────────────────
1312    pub register_book: unsafe extern "C" fn(ctx: *mut c_void, book_id: YogStr, book_json: YogStr),
1313
1314    // ── ABI minor 19 — UI system ──────────────────────────────────────────────
1315    /// Register a UI tree. `ui_id` is the unique identifier (e.g. "mymod:menu").
1316    /// `layout_json` is the serialized layout tree.
1317    /// `handler` is called when an interactive element is clicked/keyed.
1318    pub register_ui: unsafe extern "C" fn(
1319        ctx: *mut c_void,
1320        ui_id: YogStr,
1321        layout_json: YogStr,
1322        ud: *mut c_void,
1323        h: YogUIEventFn,
1324    ),
1325
1326    // ── ABI minor 20 — per-UI screen renderer ────────────────────────────────
1327    /// Register a render callback that fires during `YogUIScreen.render()` for a
1328    /// specific UI id — i.e. AFTER the screen darkening, unlike `on_hud_render`.
1329    /// Reuses `YogHudRenderFn` (`fn(ud, gfx)`); `gfx.screen_w/h` are set.
1330    /// Clicks are forwarded as `"click:X:Y"` events to the `register_ui` handler
1331    /// so mods can do their own hit-testing with their stored layout.
1332    pub on_ui_render:
1333        unsafe extern "C" fn(ctx: *mut c_void, ui_id: YogStr, ud: *mut c_void, h: YogHudRenderFn),
1334
1335    // ── ABI minor 22 — menu entry registration ──────────────────────────────
1336    /// Register a button/link that the host renders on vanilla screens
1337    /// (TitleScreen on Fabric, ModListScreen on Forge/NeoForge).
1338    /// `label` is the human-readable button text (e.g. "Yog Mods").
1339    /// `ui_id` is the Yog UI to open when clicked (e.g. "example:menu").
1340    pub register_menu_entry: unsafe extern "C" fn(ctx: *mut c_void, label: YogStr, ui_id: YogStr),
1341
1342    // ── ABI minor 23 — installed mods listing ───────────────────────────────
1343    /// All installed mods as TSV, one per line:
1344    /// `source \t id \t name \t version \t authors \t description`
1345    /// where `source` is `yog` (a .yog mod) or `platform` (a loader mod, e.g.
1346    /// a Fabric/Forge jar). Tabs and newlines inside fields become spaces.
1347    /// Callable at any time after registration (also client-side).
1348    pub mods_list: unsafe extern "C" fn(ctx: *mut c_void) -> YogOwnedStr,
1349    /// Free a `YogOwnedStr` returned by an api-table call (same allocator as
1350    /// `YogServer::free_str`).
1351    pub free_str: unsafe extern "C" fn(ptr: *mut u8, len: u32),
1352
1353    // ── ABI minor 24 — open a Yog UI screen ─────────────────────────────────
1354    /// Open the Yog UI registered as `ui_id` on the client (schedules onto the
1355    /// render thread). Client-side only; a no-op on dedicated servers.
1356    /// `modal` blocks game input; `pause` pauses a singleplayer game.
1357    pub ui_open: unsafe extern "C" fn(ctx: *mut c_void, ui_id: YogStr, modal: bool, pause: bool),
1358
1359    // ── ABI minor 25 — inventory framework (yog-inventory) ──────────────────
1360    /// Register a real Container/Menu inventory screen — see `yog_inventory`.
1361    pub register_inventory: unsafe extern "C" fn(ctx: *mut c_void, def: *const YogInventoryDef),
1362
1363    // ── ABI minor 26 — inter-mod communication ─────────────────────────────
1364    /// Export a function pointer under `symbol` for the calling mod (`mod_id`).
1365    /// Other mods can import it via `interop_import`.
1366    pub interop_export:
1367        unsafe extern "C" fn(ctx: *mut c_void, mod_id: YogStr, symbol: YogStr, ptr: *const c_void),
1368    /// Import a function pointer exported by `mod_id` under `symbol`.
1369    /// Returns null if the symbol is not (yet) registered.
1370    pub interop_import:
1371        unsafe extern "C" fn(ctx: *mut c_void, mod_id: YogStr, symbol: YogStr) -> *const c_void,
1372
1373    // ── ABI minor 29 — custom dimensions ────────────────────────────────────
1374    /// Register a dimension-type definition (id + `YogDimensionTypeDef` JSON).
1375    /// Must be called at mod-init time (same window as blocks/items) — the
1376    /// host registers a `LevelStem`/`DimensionType` entry before the
1377    /// registry freezes. See `yog-dimensions` crate.
1378    pub register_dimension_json: unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, json: YogStr),
1379    /// Register a chunk generator for a previously-declared dimension `id`.
1380    /// `handler` is called once per chunk column that needs generating —
1381    /// see `YogChunkWriterApi`/`YogChunkGeneratorFn`.
1382    pub register_chunk_generator:
1383        unsafe extern "C" fn(ctx: *mut c_void, id: YogStr, ud: *mut c_void, h: YogChunkGeneratorFn),
1384
1385    // ── ABI minor 33 — closing Yog UI screens, consuming UI key events ──────
1386    /// Close the Yog UI screen showing `ui_id` (empty = whichever Yog UI
1387    /// screen is open). Scheduled onto the render thread, so it's safe to
1388    /// call from that screen's own event handler. Client-side only.
1389    pub ui_close: unsafe extern "C" fn(ctx: *mut c_void, ui_id: YogStr),
1390    /// Called from inside a `register_ui` handler while it handles a `key:`
1391    /// or `char:` event: the mod used the key, so the host skips its default
1392    /// handling (Esc closing the screen, Tab focus navigation, ...).
1393    pub ui_consume_event: unsafe extern "C" fn(ctx: *mut c_void),
1394
1395    // ── ABI minor 33 — translations ─────────────────────────────────────────
1396    /// The text of translation key `key` (e.g. `mymod.screen.title`) in the
1397    /// game's current language, from the loaded lang files — resource packs
1398    /// and `.yog` mods' `assets/<ns>/lang/*.json` (compiled from `.yres`).
1399    /// `YogOwnedStr::NONE` when no language defines the key. Format
1400    /// specifiers (`%s`, `%1$s`) come back as-is. Free with `free_str`.
1401    /// Client-side; a dedicated server only knows `en_us`.
1402    pub translate: unsafe extern "C" fn(ctx: *mut c_void, key: YogStr) -> YogOwnedStr,
1403
1404    // ── ABI minor 1 — client: screen flags, sounds, held items, keys ────────
1405    /// Like `ui_open`, with [`ui_flags`] bits: `MODAL`, `PAUSE`,
1406    /// `NO_BACKGROUND` (no dimmed/blurred world behind the screen).
1407    /// Client-side only.
1408    pub ui_open_flags: unsafe extern "C" fn(ctx: *mut c_void, ui_id: YogStr, flags: u32),
1409    /// Play sound event `sound_id` for the local player only: at the
1410    /// player's position, or (`looping`) as a loop that follows the player
1411    /// until `client_stop_sound`. Returns a handle (0 = failed).
1412    pub client_play_sound: unsafe extern "C" fn(
1413        ctx: *mut c_void,
1414        sound_id: YogStr,
1415        volume: f32,
1416        pitch: f32,
1417        looping: bool,
1418    ) -> u32,
1419    /// Stop a sound started by `client_play_sound` (0 or unknown: no-op).
1420    pub client_stop_sound: unsafe extern "C" fn(ctx: *mut c_void, handle: u32),
1421    /// Item id in the local player's main hand (`off_hand` false) or off
1422    /// hand, `YogOwnedStr::NONE` for air or no player. Free with `free_str`.
1423    pub client_held_item: unsafe extern "C" fn(ctx: *mut c_void, off_hand: bool) -> YogOwnedStr,
1424    /// Whether GLFW key `key` is held down right now (client window).
1425    pub client_key_down: unsafe extern "C" fn(ctx: *mut c_void, key: i32) -> bool,
1426}
1427
1428/// Flag bits for [`YogApi::ui_open_flags`].
1429pub mod ui_flags {
1430    /// Blocks game input (what `ui_open`'s `modal` does).
1431    pub const MODAL: u32 = 1;
1432    /// Pauses a singleplayer game.
1433    pub const PAUSE: u32 = 1 << 1;
1434    /// Draws no background behind the screen: the world stays visible.
1435    pub const NO_BACKGROUND: u32 = 1 << 2;
1436}
1437
1438unsafe impl Send for YogApi {}
1439unsafe impl Sync for YogApi {}