# Presentation modules as a native library (`libgfpresent`) ## What it is for Every kit that draws something (a HUD, a camera, an effect) has a presentation module: a small program that is given what the game state looks like and answers what to draw. On the web these modules are loaded as `.wasm` files. `libgfpresent` is the same modules compiled to native code, in one library, for hosts that are not a browser: the C kit host, the Godot, Unity and Unreal wrappers and the desktop player. The library answers the same bytes as the `.wasm` of the web, so a kit looks the same on every engine. It only computes. Drawing the answer is the job of the engine adapter. ## Install You do not build it to use a game: the wrappers and the desktop player ship it. To build it yourself: ```sh cd wrappers/present-native && cargo build --locked --release ``` The result is `libgfpresent` (shared) in `target/release/`. ## First example List the kits that have a module, create one and ask what it needs: ```c uint32_t abi = gfp_abi(); /* the present ABI the modules speak */ for (uint32_t i = 0; i < gfp_count(); i++) { const char *kit = gfp_kit(i); /* e.g. "combat.core" */ GfpModule *m = gfp_create((const uint8_t *)kit, strlen(kit)); if (!m) continue; /* NULL: no module for that kit */ const uint8_t *out; size_t len; if (gfp_needs(m, &out, &len) == 0) { /* out[0..len] is the module's declaration of what it needs, as postcard bytes */ } gfp_free(m); } ``` ## C interface Bytes in and out are postcard, exactly like the `.wasm` exports `gf_needs`, `gf_init` and `gf_frame`. | Function | Role | |---|---| | `gfp_abi()` | The present ABI version these modules speak. | | `gfp_count()` | The number of kits that have a module. | | `gfp_kit(index)` | The kit id at that index, as a C string; NULL past the end. | | `gfp_create(kit, len)` | A module for the kit id (UTF-8, matched exactly); NULL when there is none. | | `gfp_needs(m, &out, &out_len)` | What the module needs from the host. | | `gfp_init(m, in, len, &out, &out_len)` | Starts the module with its configuration. | | `gfp_frame(m, in, len, &out, &out_len)` | One frame: the state in, the drawing commands out. | | `gfp_input(m, in, len, &out, &out_len)` | One input event of the window, for a module that draws an interface surface (ABI 1.5). | | `gfp_free(m)` | Releases the module. | Rules: - A call answers 0 when it worked and 1 when the module panicked: leave that module out. `gfp_input` answers 2 for a module that takes no input. - `out` stays valid until the next call on the same module; copy it if you need it longer. - A module belongs to one thread at a time. - The kit names are those of the kits (`combat.core`, `hud.action`…); an unknown name, an empty name or one that is not text gives NULL. ## When it does not do what you expect - `gfp_create` returns NULL: that kit has no presentation module, or the name is not exact (case and spaces count). - A module answers 1: it panicked. Stop calling it and run the game without its presentation. - The answer differs from the web: it should not. The library is checked byte for byte against the `.wasm` modules; report the kit and the input. ## Limits - It draws nothing and loads no files; the engine adapter draws the answers. - There is no `.wasm` interpreter inside: native hosts use this library, web hosts use the `.wasm` files. - Using the Rust crate directly takes the features of your own build; the C library is the one that is proved identical. ## Versions Library 0.2, present ABI 1 (with the input entry from 1.5).