Desktop
Usage guide of the desktop export: gripforge game-export --target desktop makes a folder with the prebuilt native player (the Bevy player with the Rust logic of the kits and their presentation modules linked as native code) and the game as data; where the player comes from (release, catalogue, cache, --runtime, error codes), platforms, what the native window shows, the browser engine of the interface (--bundle-web-engine), checking an export without a screen (--replay), publishing the player, limits.
Using the Game Kits on the desktop (the native player) #
Make a game that starts with a double click on Linux or Windows — no browser, no Rust, no Node on the player's machine. Readable offline: grip-forge docs desktop, or the MCP tool gripforge_docs (topic desktop).
What it is for #
gripforge game-export --target desktop makes a folder from a game: the prebuilt native player and the game as data. The player is the Bevy player of the web, built for the desktop; it loads libgfkits, the Rust logic of the Game Kits, and libgfpresent, the library of the kits' presentation modules — the files the Godot addon uses. One source per kit and per module: compiled to WebAssembly for the web page, to native code here — the same rules, the same drawing commands, no interpreter in between. Exporting a game compiles nothing: the same player opens any game.
Prerequisites #
- The GripForge CLI.
- A game (
gkp_…), or its web export (gripforge game-export <gkp_id> <folder>). - On the player's machine: Linux x86-64 or Windows x86-64 (10 and later) with a Vulkan driver. See Platforms.
Install #
Nothing to install beside the CLI, 0.3.53 or later (gripforge update gives the current one). The player is fetched by the export: about 30 MB per platform the first time, then from the cache.
First run: export a game #
gripforge game-export gkp_1234 my-game --target desktop
my-game/play.sh # Linux; on Windows: my-game\play.cmd
The command downloads the web export of the game under my-game/.gripforge/web, takes the prebuilt player, and writes:
| Path | What |
|---|---|
play.sh, play.cmd | The launcher: starts the player of the machine's platform with the game of the folder. |
bin/<platform>/gripforge-player | The prebuilt player. |
bin/<platform>/libgfkits.so | The logic of the kits (the kit host behind gfkits.h), native code (gfkits.dll, libgfkits.dylib). Without it the player stops with kit_library_missing. |
bin/<platform>/libgfpresent.so | The presentation modules of the kits, native code (gfpresent.dll, libgfpresent.dylib). |
game/game.json | The game: its project, its lockfile and its game schema — the documents the web page runs. |
game/present.json | Where the files of the model and texture slots are, and the clips of each model. |
game/assets/ | Models, textures, sounds. |
export.json | What was exported: the player version, the platforms, the sha256 of every file. |
Options:
| Option | Effect |
|---|---|
--from-web <folder> | Use a web export you already have instead of downloading one (offline). |
--runtime <folder> | Take the player from a local folder instead of the published release (offline, or a player you built). |
--platforms a,b | Only these platforms: linux-x86_64, windows-x86_64 (default: every platform of the player package). |
--bundle-web-engine | Put the browser engine of the interface in the folder: the game never downloads it (see HUD and menus). |
--webui-engine-when first-load|install | When the engine is installed when it is not in the folder: the first time the game starts (default), or only by ./play.sh --prepare. |
--webui-engine-url <base> | The address the game downloads its engine from (default: the site of GripForge). |
--check | Say what would change, write nothing. |
--force | Replace files of the folder you edited. |
--json | The report as JSON. |
Run the export again on the same folder to update it. A file you edited stops the update unless --force is given.
Where the player comes from #
The CLI carries the catalogue of one player package: its version and, per platform, the sha256 of the archive and of every file in it. The archive is downloaded from https://gripforge.ai/cli/gripforge-player/<version>/<archive> (the assets of the release gripforge-player-v<version>; GRIPFORGE_DESKTOP_PLAYER_URL names another base that holds <version>/<archive>), checked against that catalogue before anything is unpacked, and kept in ~/.grip-forge/cache/gripforge-player-native/<version>. Nothing is trusted from the server.
Errors #
The export stops with a named code when it cannot have the player:
| Error code | Meaning | What to do |
|---|---|---|
desktop_player_not_catalogued | This CLI carries no player catalogue. | Update the CLI, or pass --runtime <folder>. |
desktop_player_version_not_published | The release of that version is missing. | Update the CLI, or pass --runtime. |
desktop_player_unreachable | The download failed. | Check the network, or pass --runtime. |
desktop_player_integrity | A file differs from the catalogue. Nothing is kept. | Run again; report it if it persists. |
desktop_player_platform_not_available | --platforms names a platform that is not available yet (macOS). | Export for the other platforms. |
desktop_player_platform_unknown | --platforms names a platform the package does not have. | Use a listed platform. |
webui_engine_no_archive | --bundle-web-engine was asked and this CLI carries no engine for that platform. | Update the CLI, or export without it. |
webui_engine_not_found, webui_engine_unreachable | The engine could not be downloaded. | Check the network and run again: the download resumes where it stopped. |
webui_engine_checksum | The file downloaded is not the engine of this CLI. Nothing is kept. | Check --webui-engine-url. |
A folder given to --runtime holds either the files of a release (the archives) or the unpacked platforms with their manifest.json. When the CLI has no catalogue, the manifest of the folder is used and the report says the player was not checked against a published release.
Platforms #
| Platform | State |
|---|---|
linux-x86_64 | Available: played on screen (NVIDIA, Vulkan), with the HUD. |
windows-x86_64 | Not available yet: its player was only replayed without a window under Wine, never run on Windows; no HUD. The launcher play.cmd is written when a package has it. |
macos-universal | Not available yet: --platforms macos-universal answers desktop_player_platform_not_available (« macOS: not yet available »). |
| Android, iOS | Not supported yet. |
What the native window shows #
- The models of the game, their clips, the camera, the lights, the scenery and the effects: everything the kits draw through their presentation modules, with the same module host as the web player.
- The export warns about a kit the web draws through a module the player does not link.
- HUD and menus: the fragments of the kits (
ui.webui), the same page as the web, drawn over the game by theui.webuimodule of the library (Linux). The export copies them intogame/(present-modules.json,modules/*.ui.mjs). See HUD and menus below and Known limits. - Keyboard and mouse buttons go to the input actions of the kits; the kits ask for full screen and pointer lock through their display settings.
- Which kits run: every kit whose logic is in the native library runs here with the rules of the web. The catalogue says it (
gripforge kit api <kit>, section Targets:rust: native (libgfkits)) and names what is still missing on the desktop: a view of a kit drawn on the web page only (to provide by a ui.webui fragment), a fragment not yet in the published player, or a part of the network core (below).
HUD and menus (the browser engine) #
The interface of a game is made of web fragments (ui.webui). Its native form needs a browser engine embedded in the game — never the browser of the machine: about 133 MB to download on Linux (308 MB once unpacked), 153 MB on Windows, 127 MB (Apple silicon) or 135 MB (Intel) on macOS. It is a dependency installed once into a cache shared by every game of the user, at one of three moments:
- the first time the game starts (default): the game loads and plays meanwhile, the band at the top of the window shows the download, and the HUD appears when the engine is ready. A download cut in the middle is tried again, then resumed where it stopped at the next start;
- when the game is installed:
./play.sh --prepareinstalls it with no window and exits (0 = ready); an installer or a machine without network at play time runs it once.gripforge webui-engine preparedoes the same without any game. Export with--webui-engine-when installfor a game that must never download while it plays; - in the game:
--bundle-web-engineputs it in the exported folder; nothing is downloaded, ever.
The file downloaded is checked against the sum the game carries before anything is unpacked: the address can be changed (--webui-engine-url <base> at export, --webui-engine-url=<base> or GRIPFORGE_WEBUI_ENGINE_URL when the game starts, a local folder as file:///…/), the engine cannot.
Where the engine is looked for, in order: webui-engine/<version>-<platform>/ beside the player, the folder named by GRIPFORGE_WEBUI_ENGINE_DIR (or --webui-engine-dir=<dir>) or else the cache of the user, then a download; --no-webui-engine-download forbids the download.
The cache of the user is ~/.cache/gripforge/webui-engine/ on Linux ($XDG_CACHE_HOME/gripforge/… when set), %LOCALAPPDATA%\GripForge\webui-engine\ on Windows and ~/Library/Caches/GripForge/webui-engine/ on macOS; the engine of a version lives in its own folder there, <version>-<platform>/ (for example 154.0.34-1-macos-aarch64/). An archive of the engine has no folder at its top: to install one by hand, unpack it INTO that folder (mkdir -p <cache>/<version>-<platform> && tar xzf <archive> -C <cache>/<version>-<platform>), or let gripforge webui-engine prepare do it.
No interface is never silent. When the module, the host page or the engine is missing, or the engine cannot be fetched, the game starts and goes on, and the named reason (webui-module-missing, webui-host-page-missing, webui-engine-no-archive, webui-engine-offline, webui-engine-checksum…) is written in the log and shown in a band at the top of the window, with where the engine was looked for. While the engine is fetched the band shows the progress.
The picture of the interface is a GPU texture the browser shares with the game: nothing is copied by the processor. On a machine where the browser cannot share one (a single NVIDIA card today), the module falls back to pictures copied through memory and says so in the log: [ui.webui] FALLBACK cef-copy: no-shared-picture.
Checking an export #
my-game/bin/linux-x86_64/gripforge-player --replay my-game/game/game.json --reference reference.json
No window is opened: the game is played through the operations of a parity document { fixture, trace } and its trace is compared with the reference trace — the one the web host and the Godot addon are held to. It prints replay ok: N frames identical to the reference, or the first difference and exits 1.
GRIPFORGE_STATS=2 my-game/play.sh prints the frame rate every two seconds. GRIPFORGE_CAPTURE=shot.png GRIPFORGE_CAPTURE_AFTER=8 my-game/play.sh saves what the window shows after eight seconds and exits. gripforge-player --about prints the version, the presentation ABI, the library it loads and the kits it has a module for. GRIPFORGE_PRESENT_LIBRARY=<file> loads another build of the library.
Versions #
| Part | Version |
|---|---|
| Desktop export | CLI 0.3.48 and later; the HUD and libgfkits beside the player: CLI 0.3.50; the player downloaded by itself: CLI 0.3.53 |
| Player package | gripforge-player-native/1, player 0.1.0 |
| Presentation ABI | gripforge:present@1 (v1.5), 61 modules in libgfpresent |
| Kit logic | libgfkits, C interface 1.3 |
| Engine | Bevy 0.18.1, Rust 1.99.0 |
Known limits #
- The HUD and the menu of
ui.menu(title screen, pause, Options) are web fragments; a click on one of their buttons becomes the command of its kit, as on the web (an event no module declared is refused by name in the log). Kits without a fragment are drawn as UI trees of their modules. The HUD of the car football and of the kart race is made of fragments too: the scoreboard and its banners (sport.ball), the objective (input.actions), the key prompts (ui.prompts), the end of the match (ui.endscreen), the race panel, item, speed and results (race.kart) and the mini-map (hud.minimap). The start screen of the race (shown by the web page while it holds the game) is not shown here: the race starts when the title screen closes. - The browser engine of the interface is built for Linux x86-64, Windows x86-64 (pictures copied through memory) and macOS (pictures copied through memory). It was run on screen on Linux; on Windows only under Wine; never on a Mac.
- The player itself: Linux and Windows x86-64 today; macOS is not available yet (see Platforms).
- Sound: the audio kit runs (its state is in the game), but the native window plays no sound yet.
- Gamepads are not read by the native window yet.
- Network kits (
net.*): the network core is served natively (TCP+UDP, then the WebSocket bridge); WebRTC and the shared physics ofnet.physicsare not, and are refused by name. - Saves: the kit host keeps them in memory; they are not written to the disk yet.
- A game holds at most 128 model files and 256 MB of models.