AMod Kit / Asset Lane, Accelerated Accelerated · 14 modules

AshForge Mod Kit · Asset Lane · the whole lane, one course

How your own art gets in,
and why it does not ship as a PNG.

An icon you drew and a model you made, carried into the exported mod and referenced by your own definitions. The mechanism is small and worth knowing exactly — including why shipping the obvious file format costs four times the video memory.

Application  AshForge Mod Kit Prerequisites  none Format  one course, 14 modules Time  ~85 min

What it is

Two folders in your mod, icons/ and models/, and the lane that carries what they hold into Assets/ inside the exported mod.

Modules 1–4 are references, 5–9 are formats, 10–14 are what ships.

The number that matters

The game cannot compress a texture at runtime. One 256×256 icon costs 349,524 bytes as a loose PNG against 87,408 compressed.

Four times, silently, per texture, with no symptom but a budget that ran out early.

Why this is one course

This lane is 14 things worth knowing, not three escalating tiers. The old split implied the later material needed the earlier and it does not — read straight through, or jump to the module that matches your problem. The Mod Kit's other lanes are separate courses.

01

Sources

Where art lives

Do two folders

Two folders in your mod, and two prefixes in the Definitions forms that point into them.

FolderWritten in a definition asUsed for
<mod>/icons/icon:beacon.pngAn item, research node or anything with an Icon field.
<mod>/models/model:beacon.glbThe mesh a thing renders as.

Both are set from the Definitions workspace, in the same forms you already know — the art fields were always there, holding these icon: and model: values. For a long time nothing read them and every exported reference was a base-game constant; the asset lane is what connects the two ends.

Note the extensions here: you name a real file, with its extension, because you are pointing at something on your disk. What comes out the other end does not have one, which is the next lesson and the single most common source of confusion.

02

The mechanism

A reference has no extension

Know the game appends it

★★ A reference is a namespace plus a path, and never a filename. The game builds the filename itself.

When the game wants a texture it appends .png; when it wants a mesh it appends .glb. So what goes into the definition is <modid>/<path> with nothing on the end, and the same reference serves an icon and a mesh in different fields without ambiguity — because the field decides the extension, not the value.

Here is a real exported item, produced for this page. One reference, used three times:

FieldValueThe game will look for
IconAshForgeAssetDemo/beaconbeacon.png
MeshPathAshForgeAssetDemo/beaconbeacon.glb
MaterialAshForgeAssetDemo/beaconthe material for it
Key
If you ever hand-edit a dec, do not add an extension. A reference ending in .png becomes a request for beacon.png.png, which does not exist, and you get a placeholder with no explanation.
03

Organisation

Subfolders are kept

Read not flattened

If you organise your icons into folders, that structure survives into the exported mod.

icons/ui/crate.png becomes Assets/ui/crate.ashtex and is referenced as <modid>/ui/crate. The lane could have flattened everything into one directory and it deliberately does not, for two reasons worth knowing.

First, flattening renames an author's files behind their back, and a pipeline that quietly changes your names is one you cannot reason about. Second, and more seriously, two icons called crate.png in two different folders would collide silently — one would overwrite the other and the mod would ship with the wrong art and no error. Keeping the structure makes that collision impossible rather than merely unlikely.

In practice
Organise your art however suits you. The folder layout you choose is the reference path you get, so icons/weapons/rifle.png reads back as <modid>/weapons/rifle — which is easier to recognise in a dec than a flat list would be.
04

The result

What actually ships

Read a real export

A demo mod with one item that owns its icon, its mesh and its material was exported for this page. This is everything it produced.

File under Assets/SizeWhat it is
beacon.ashtex3,873 BThe icon, compressed.
beacon.glb3,428 BThe mesh, copied as-is.
beacon.ashmat148 BThe material.
beacon_albedo.ashtex159 BThe material's texture.
.ashforge-provenance.json1,106 BWhere every one of the above came from.

The export reported it plainly: ships 1 icon, 1 mesh, 1 material of its own, and closed with an audit line — 3 references into this mod's own namespace, all of them served. That last number is the one to read: it counts references that point at your mod and confirms each one found a file.

Notice what the mesh did not do: beacon.glb is copied unchanged. Meshes ship as they are. Textures do not, and that is the whole of the next tutorial.

05

The reason

Why the PNG can't go

Know 4×, silently

A PNG is compressed on disk. It is not compressed in video memory, and those are completely different things.

When a texture is uploaded to the GPU it has to be in a format the GPU can sample directly. Most engines will compress one for you on the way in. This game cannot — the capability is checked every launch and is unavailable — so a PNG lands as raw pixels, four bytes each.

The arithmetic for a single 256×256 icon:

Shipped asIn video memory
A loose .png349,524 bytes — raw, four bytes per pixel
A .ashtex87,408 bytes — compressed, with its mipmaps

That is one icon. A mod with fifty of them is paying for two hundred that it does not have. And the cost is invisible from inside the game: the art looks right, nothing errors, and the only symptom is a memory budget that ran out sooner than anyone expected.

06

The trick

The substitution

Read ask png, get ashtex

The game is hard-coded to ask for a .png. The loader answers with the .ashtex instead.

This is why the two facts that look contradictory are both true. Your definition holds <modid>/beacon, the game turns that into a request for beacon.png, and the loader — which sits between the game and your mod's files — hands back beacon.ashtex. The game never learns the difference.

It also means you cannot get compressed textures into this game any other way. There is no setting, no import flag and no alternative path: the substitution is the mechanism.

If you are debugging
A reference ending in .png inside a dec is wrong, and a .png sitting in your exported Assets/ is waste. Neither will error. The first shows as a missing texture, the second only as memory.
07

The conversion

What conversion does

Read measured

A 256×256 image was converted for this page. Here is what came out.

PropertyValue
Dimensions256 × 256
MipmapsGenerated — the full chain down to 1×1
Size in video memory87,408 bytes
Size on disk38,800 bytes — deflated on top of the compression

So the format does two jobs at once. It stores the texture already in the form the GPU wants, which is the part that saves the memory, and it then deflates that for storage, which is why the file on disk is smaller than the memory it will occupy. Your download gets smaller and your video memory gets smaller, from one conversion.

★ A small confirmation worth mentioning, because it is the kind of thing that catches a bad pipeline: the size the file claims it will occupy — 87,408 bytes — matches an independent calculation of what a 256×256 compressed texture with a full mipmap chain should be, exactly, to the byte. The file is not merely well-formed; it is arithmetically consistent with what it says it is.

Mipmaps
Leave them on. They are the smaller copies the GPU uses when something is far away or small on screen, they cost about a third extra memory, and without them your icons shimmer. The converter generates them by default.
08

Materials

Materials carry their own texture

Read a second file

A material is not a texture. It is a small description that points at one, plus the numbers that decide how the surface behaves.

The demo mod's material is 148 bytes and holds four things: a base colour, a roughness, a metallic value, and the path to its albedo texture — which is a separate file, converted the same way as any icon.

That is why an item that ships one mesh can end up with two texture files in Assets/: the icon you see in a list, and the albedo wrapped around the model in the world. They are unrelated images doing unrelated jobs, and forgetting the second is why a model can appear correctly shaped and completely untextured.

The material is read out of your .glb automatically. ⚠ If the mesh cannot be read, no material is produced and the definition keeps its base-game one — which loads and renders, so the failure looks like "my model has the wrong texture" rather than like an error.

09

The trap

One field, four files

Do check the kind

Most things need one mesh. Two kinds of thing need more, from the same single field, and the game does not check.

What it isFiles required from one mesh reference
An ordinary item or buildingfoo.glb
A storage building foo.glb, foo_Low.glb, foo_Partial.glb, foo_Full.glb
A plant foo.glb, foo_Half.glb, foo_Sprout.glb

A storage building shows how full it is by swapping mesh; a plant shows its growth stage the same way. One field in your definition therefore stands for four files or three, named by convention, and the game dereferences them without checking they exist. A missing one is not an error — it is a bright magenta placeholder in the world.

The signing gate refuses a mod in this state, which is the right place to catch it but a late one. If you are modelling a stockpile or a crop, plan for the whole set from the start, because discovering it at signing means going back to your modelling tool.

10

By design

When a placeholder is right

Know three good reasons

The lane deliberately leaves a definition alone when its art is unset or is a built-in preview name. Three reasons, and each one matters.

CaseWhy it must keep working
Your mod uses base-game art on purpose Legitimate and common. A mod that adds a recipe for an existing item needs no art at all.
You are part-way through pipelining You must still be able to export and test. A pipeline that refuses to run until every asset exists is one nobody can iterate in.
The reference points outside your mod The gate deliberately does not judge foreign namespaces — it has no way to know what another mod ships.

So "placeholder" in the report is a statement of fact, not an accusation. The question it asks you is simply: did you mean this one? Nothing else in the pipeline can answer that, which is why the report lists them for a person to read rather than failing the export.

11

The defaults

The four substitutions

Read what you get

When art is missing, four specific base-game assets fill the gap.

MissingYou getWhat it looks like
A meshModels/Items/WoodA wooden item. Loads and renders.
A materialTextures/Items/WoodMatWood texturing on whatever shape it is applied to.
An item iconUI/Items/PotatoIconA potato. Without any icon an item loads but never draws.
A research iconUI/Items/PotatoIconThe same potato.

The potato is doing more work than it looks. An item with no icon at all does not fall back to a blank square — it fails to draw, so the item exists, can be picked up and crafted, and is invisible in every list. Substituting something absurd and visible is far better than that, and it is why these constants exist rather than being left empty.

⚠ If you see wood and potatoes in game, the export told you. It is in the report every time, and it is the most common reason a first mod looks nothing like the author expected.

12

A principle

Silence is the truth

Know no invented material

When your mesh cannot be read, the lane produces no material at all rather than a plausible one.

It would be easy to substitute a generic grey surface and carry on. The lane refuses, and its reasoning is worth quoting because it applies to far more than materials: substituting is for a preview; shipping needs the truth.

So a mesh that fails to load leaves the definition on its base-game material, which loads and renders. The consequence is that the symptom you see is "my model has the wrong texture" rather than an error — but the alternative is worse: a grey material that looks deliberate would have hidden the fact that your mesh never loaded at all.

Diagnosing it
Model correct, texture wrong or wooden? Suspect the mesh, not the material. The material is read out of the .glb, so a material problem is usually a mesh problem wearing a disguise.
13

Shipping

Accounting for every file

Do one file per folder

Every asset in the exported mod appears in a provenance record. An asset with no origin stops the mod being signed.

The export writes .ashforge-provenance.json beside your assets, listing each file and where it came from. It fills in the local path automatically; what it cannot know are the fields that actually matter for release:

FieldWhat it is for
sourceFilled in for you — the file on your disk it was built from.
packThe asset pack it came out of, if any.
licenseThe licence you hold it under. Yours to supply.
attributionWho to credit.
urlWhere it came from.

You supply these by putting a .ashforge-origin.json in the folder each asset was downloaded into — once per folder, not once per file — and the export carries it through. Art you made yourself still needs one; "I drew it" is a perfectly good origin, and the gate only checks that an answer exists.

★ Note what this is and is not. It cannot tell whether you had the right to ship something. It checks that every file is accounted for, which makes an unlicensed asset a deliberate act rather than an oversight. That is the honest limit of what a tool can do here, and doing it well is worth more than pretending to do more.

14

In practice

Reading your own report

Do three lines that matter

Three lines in UNMAPPED.txt tell you the state of your art, and the placeholder section tells you exactly what is left to do.

LineRead it as
ASSETS: this mod ships N icon(s) and N mesh(es) of its own What actually got carried. Compare against what you expected.
ASSET AUDIT: N reference(s) into this mod's own namespace, all of them served Every reference pointing at your mod found its file. This is the line that confirms the lane worked.
N shipped asset(s) have no origin record A blocker. Fix before you try to sign.
The placeholder section counts

Each line names how many things were substituted — "material on 5 items/buildings" — and a line appears only when a substitution actually happened. A mod that ships its own icon, mesh and material has no asset lines in that section at all.

So the counts are worth reading as numbers, not just as warnings: if you expected to ship twelve models and the report says a mesh was substituted on three things, you know exactly how much is left to do.

If you are reading an older export
Before this was fixed, those lines were printed whenever a mod contained any items, whether or not anything had been substituted — and the material line claimed a modded mesh could not be textured at all. If you have an old UNMAPPED.txt saying that, check the dec instead: a <Material> holding <yourmodid>/something means your material shipped and the warning was not about you.

That is the habit this whole ladder comes down to: the report is generated, so read it, and the dec is the truth, so check it. Between those two files there is nothing about your art you cannot find out before a player does.

Course complete

What you now know

Check yourself

  • Art lives in <mod>/icons/ and <mod>/models/, pointed at from a definition as icon:file.png and model:file.glb.
  • Your mod's id is its asset namespace, and the loader maps it to the mod's Assets/ folder.
  • ★★ A reference carries no extension — the game appends .png or .glb according to the field. Adding one yourself breaks it silently.
  • Subfolders are preserved, not flattened, so same-named files in different folders cannot collide.
  • Art is opt-in: a definition that points at nothing keeps a base-game placeholder, so an unfinished mod still loads.
  • A mesh is copied unchanged; a texture is converted.
  • The export prints an asset audit — how many references point into your namespace and whether each was served.
  • The game cannot compress a texture at runtime, so whatever you ship is what occupies video memory.
  • A loose PNG costs 349,524 bytes for one 256×256 icon against 87,408 compressed — four times, silently, per texture.
  • Compress always and ship only the .ashtex. The PNG is pure download weight.
  • The game asks for .png and the loader answers with the .ashtex. That is the only route to compressed textures, so both facts being true is not a bug.
  • Conversion saves twice: compressed for the GPU, then deflated for disk — 87,408 in memory, 38,800 on disk.
  • A material is a separate small file that points at its own albedo texture, so one item can ship two images. No material is produced if the mesh cannot be read.
  • A storage building needs four meshes and a plant needs three, from one field, by naming convention, unchecked by the game — a missing one is a magenta placeholder.
  • A placeholder is a deliberate outcome with three good reasons behind it — the report asks "did you mean this?", it does not accuse you.
  • The four substitutions are wood, wood material and two potatoes. An item with no icon at all loads but never draws, which is why an absurd visible icon beats none.
  • A mesh that will not load produces no material rather than an invented one — substituting is for a preview; shipping needs the truth.
  • So "wrong texture" is usually a mesh problem in disguise.
  • Every shipped asset needs an origin record or the mod cannot be signed. One .ashforge-origin.json per source folder, and art you made yourself needs one too.
  • The gate checks that you said where a file came from, not that you had the right to ship it — an honest limit, done properly.
  • In the report: ships N, audit all served, no origin record — and a placeholder section that lists only real substitutions, with counts, so a mod shipping its own art has no asset lines there at all.

That is the asset lane. Your mod's id is its asset namespace, a reference carries no extension, and an asset with no origin record cannot be signed — the export always succeeds, and signing is where it stops.