The amd_assets module
Resolving image://, face:// and ship:// for a document rendered outside the engine.
Overview
media_paths already answers "where does this art live", but through
fs.get_mission_dir_filename, which needs an install and a running mission. A static
exporter has only a folder, so this mirrors that module's search order against a
folder handed to it — the mission's own media/, then each pack story.json pins, then
the engine's data/graphics.
| Scheme | Resolves? |
|---|---|
image:// |
Yes. Including engine built-ins like ball, which live in the install rather than any mission |
face:// |
No file — but it composites. The value names cells of a race atlas, and those atlases are real PNGs. cosmos_dev/mockgui/face.js is the canonical compositor and carries a setSheetResolver hook precisely so another host can use it |
ship:// |
No. The tag names a 3D hull; the .png beside each mesh is its diffuse texture, a near-white sheet that prints as a blank box |
A placeholder is a real answer, not a failure: a printed page should say "a ship goes here" rather than closing the gap silently, because art nobody can see is missing is art nobody restores.
API
Resolving image:// art for a document rendered OUTSIDE the engine.
media_paths already answers "where does this logical art path live", but it
answers it through fs.get_mission_dir_filename, which needs an Artemis install
and a running mission. A static exporter has neither - it has a folder path - so
this mirrors that module's SEARCH ORDER against a folder handed to it:
<mission>/media/... the mission's own art
__lib__/media/<pack-name>/... each pack it pinned
The pinned packs come out of story.json exactly as media_paths._pinned_packs
reads them (resources values plus shared_media, .zip stripped, declaration
order), because a document that resolves art differently from the game is a
document that shows the wrong picture.
What resolves, and what does not:
image://- a file, once the search includes the ENGINE graphics dir. Keys likeballandtestare engine built-ins living in<cosmos>/data/graphics, not in any mission, so a search that stops at the mission folder reports art as missing that is sitting right there.face://- no file, but not unresolvable either. The value is a face-BUILDER string (arv #ffffff 0 0;arv ...) naming cells of a race ATLAS, and those atlases are real PNGs in the engine graphics dir. The browser mock already composites them (cosmos_dev/mockgui/face.js, which carries asetSheetResolverhook precisely so a second host can), so a document can too - seeface_atlases.ship://- genuinely not resolvable. The tag names a 3D hull, and the.pngbeside each mesh is its DIFFUSE TEXTURE, not a picture of the ship:ships/tsn_light_cruiser.pngis a near-white sheet that would print as a blank box. The browser mock does not draw one either. A placeholder is the honest answer, not a limitation to work around.
A placeholder is a real answer, not a failure: a printed page should say "a ship goes here" rather than closing the gap silently, because art nobody can see is missing is art nobody restores.
MissionAssets
Resolves a media block to something a <img src> can use.
embed=True inlines the bytes as a data: URI, which is what makes the page
self-contained and therefore printable from anywhere. embed=False emits a
relative path instead: a much smaller file that stops working the moment it
is moved, which is the right trade only while iterating.
face_sheets(specs)
{atlas basename: url} for every race the given face strings use.
Only the atlases actually referenced are resolved: a mission whose cast is all Zimni pays 0.44 MB, not the 6.8 MB of all six sheets.
find(name)
The file a logical image name resolves to, or None.
media(block)
The src for one media block, or None to leave a placeholder.
all_face_files(mission_dir=None)
{alias: sheet path} read from the engine's own allFaceFiles.txt.
This file IS the registry - the engine maps a face string's alias to a sheet
through it, and it is the only place a MOD can add one, because a mastlib is a
zip and cannot write into data/graphics. Its values may point outside the
graphics folder (the TNG mod registers
../missions/__lib__/media/<pack>/faces_tng/TNG_Faces_1), so they are resolved
against the graphics dir rather than assumed to live in it.
Returns {} when the file or the graphics dir cannot be found, which is the normal case for a checkout with no Cosmos install beside it.
face_alias_table(mission_dir=None)
{alias: atlas basename}.
Prefers the engine's allFaceFiles.txt when a mission dir is given, because
that is the only source that knows about MOD sheets - face.js hard-codes the six
stock aliases, so a mod atlas (tng1..tng6) rendered as nothing in the mock,
the AMD static site and the VS Code preview. Falls back to parsing face.js so a
checkout with no Cosmos install beside it still resolves the stock six.
face_aliases_in(spec)
The race aliases one face string references (arv #fff 0 0;arv ...).
face_js_path()
cosmos_dev/mockgui/face.js, or None when cosmos_dev is not installed
(it is a dev-only package and never ships inside the .sbslib).
graphics_dir(mission_dir)
The engine's data/graphics, found by walking up from the mission.
fs.get_artemis_graphics_dir answers this at RUNTIME, from an install the
engine already located. A static exporter has only a folder, so it looks the
way the mock server does - it is handed (or finds) the Cosmos root and reads
data/graphics under it. Missions live in <cosmos>/data/missions/<name>,
so the graphics folder is a sibling of the missions folder.
media_roots(mission_dir)
Every root a logical media path may resolve against, nearest first.
Mission art wins over engine art, deliberately: a mission that ships its own
ball.png means its own.
pinned_packs(mission_dir)
The media packs story.json declares, in declaration order.
Mirrors media_paths._pinned_packs: resources values (unpacked INTO the
mission by Mast.expand_resources - not by the engine, which has never heard of
story.json) plus shared_media (read from the one shared copy), .zip
stripped because the unpacked folder is named for the zip.
png_size(path)
A PNG's (width, height) from its IHDR, or None.
Twelve bytes of header rather than an image library, because nothing in this
stack may add a dependency and the only thing an atlas needs is the sheet's
dimensions - the cell itself is placed with CSS background-position, which
is what the engine does on the GPU anyway.