AMod Kit / Assets, Accelerated Accelerated · 14 modules

AshForge Mod Kit · Assets · the whole lane, one course

Where art comes from, what survives
being written down, and what stops a bad mod shipping.

Three things that look unrelated and are one chain: the library you pull art from, the failure that loses your work while reporting success, and the gate that refuses to let a mod ship with its weapons in the wrong place.

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

What it is

The Mod Kit's view onto the Vault asset library, the rules for writing data down safely, and the convention gate that runs over a deployed mod.

Modules 1–4 are the library, 5–9 are persistence, 10–14 are the gate.

The one that has cost twice

A Godot struct written straight to JSON writes nothing of itself, successfully. A vector becomes {}; a colour becomes a payload full of plausible numbers that cannot restore it.

Modules 5–9. It has hit two tools, and once it survived review.

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

Orientation

What you are looking at

Read a tree of published work

The tab reads the library's own index and shows you what has been published, with the lineage each asset carries.

Verified end to end: an asset published to the library appears in the tab's tree by name, and its lineage survives the round trip through JSON — where it came from travels with it rather than being reconstructed. That matters later, when signing asks your mod to account for every asset it ships.

The tab reads the format through the shared reader, not a Vault object. That is not fussiness: the Mod Kit and Vault are separate applications and neither can reference the other's types. What they agree on is a folder and a file layout, which is the loosest coupling that could possibly work — and therefore the most robust.

02

The action

Pulling one in

Do Use in This Mod

Select an asset, press Use in This Mod, and a copy lands in your mod's assets/ folder under its own category.

What was checkedResult
The file arrives in the modMyMod/assets/textures/rust_plate.png
The bytes match the published originalIdentical
The library object afterwardsStill there, untouched — the Mod Kit only ever reads

The destination folder comes from what the asset is — a texture lands under textures/ — so your mod's asset folder stays organised without you filing anything. And because this is a copy rather than a reference, your mod is self-contained from that moment on: it will build, package and sign on a machine that has no Vault library at all.

Key
Pull assets in when you decide to use them, not speculatively. Every copy is one more file your mod ships and one more thing signing will ask you to account for.
03

The control

The button's three states

Know it tells you why

The button is always there. Whether it is usable answers a question you would otherwise have to guess.

SituationButton
No mod openDisabled. There is nowhere to put the copy.
Mod open, nothing selectedDisabled. Nothing to copy.
Mod open, asset selectedEnabled.

This is the same lesson as the Definitions workspace's header, arriving through a different control: the tool tells you whether a mod is open, and it will not let you do the damaging version of the mistake. Where the Definitions workspace saves somewhere unhelpful, the Library tab simply refuses — a copy has to have a destination, so there is no "somewhere else" for it to go.

04

Edge case

Empty is not broken

Know deliberate

If you have never opened Vault, you have no library. The tab shows that as empty, not as an error.

Verified: a library that does not exist yet reads as empty rather than raising. That is a deliberate choice with a reason attached — a tool that reports a normal situation as a failure teaches people to ignore its warnings, and the warnings here are worth reading.

So an empty Library tab means one of two ordinary things: nothing has been published yet, or you have not used Vault on this machine. Neither needs fixing, and neither is the tool malfunctioning.

Worth borrowing
That principle applies to reading any of this suite's output: distinguish "nothing here" from "something went wrong" before you start debugging. Several of the tools go out of their way to keep those two apart.
05

Mechanism

Fields and properties

Know a one-word mismatch

Two reasonable decisions, made by two different teams, that produce silence when combined.

Godot's maths types store X, Y, Z as fields — the fastest thing they can be, which is what you want in an engine that touches them millions of times a frame. The JSON writer, following the .NET default, serialises properties and ignores fields.

Neither is wrong. Together they mean a struct handed straight to the writer produces a document with nothing of the struct in it, and the writer reports success because nothing failed — it wrote everything it was willing to look at.

Key
This is not a bug you can see by reading the value before you save it. The value is correct right up until the moment it is written, which is why the only reliable test is a round trip: write it, read it back, compare.
06

Vectors

The loud one

Read obvious once seen

A raw Vector3 serialises to {}. Empty braces.

This is the merciful version, because once you have opened the file you cannot miss it. A position, a rotation and a scale all written as {} is unmistakable, and it explains the symptom exactly: every prop reads back as the default, which is the origin, and a scale of zero.

Verified in both directions — a raw vector still writes nothing, and through the correct path a scale of 2 does not come back as 0. That second assertion exists because the symptom people actually report is "my props vanished", and a zero scale is what makes a prop invisible rather than merely misplaced.

Spotting it
Open the saved file and search for {}. If your positions and scales are empty braces, you have found it, and nothing you do in the interface will fix it — the data never reached the file.
07

Colours

The quiet one

Know plausible and useless

A raw Color does not write nothing. It writes a great deal, and none of it is the colour.

Unlike a vector, Color exposes a set of derived, read-only properties — an 8-bit red, hue, saturation, value, luminance, and more — and those are properties, so the writer takes them. What it omits is R, G, B and A: the four numbers the colour is actually made of.

★★ The result is the most dangerous shape a bad file can take: a payload full of plausible numbers that cannot restore the value. It does not look empty. It looks like a rich, well-populated colour record. A reader that asks for R finds no such key, falls back to a default, and hands you white.

TypeWhat lands in the fileHow you notice
Vector3{}Immediately, on sight.
ColorHue, saturation, luminance, 8-bit channels — no R/G/B/A Only by round-tripping. The file looks fine.

That asymmetry is why the harness asserts both types separately. A check that only covered vectors would have passed the whole time the colour bug was live.

08

History

What it cost, twice

Read two tools

The same mismatch, in two tools, found months apart, by two different symptoms.

WhereWhat people saw
Atlas, Aug 2026Prop placements wrote as {}. Every prop reloaded at the origin with zero scale.
The Mod Kit's model importer Imported colours came back white. The reader looked for a channel that was never written and defaulted, silently.

The importer case is the instructive one, because it passed review. Someone read that code, saw a reader with a sensible fallback, and moved on — the fallback was the thing hiding the fault. A default value is a good idea when the data is genuinely absent and a disguise when it should have been there.

The transferable lesson
A successful save is not evidence. In this failure the write succeeds, the file is valid, the numbers are plentiful, and the data is gone. Only reading it back proves anything.
09

The fix

What correct looks like

Do round-trip it

The suite's house pattern is to never hand the writer a struct at all.

Keep the individual numbers on the saved model, and expose the convenient struct as a computed value the writer is told to ignore. The file then contains real components, and the struct is reassembled on the way out — so code keeps working with vectors and colours while the document stores what it can actually restore.

Verified through that path: a vector round-trips, a colour round-trips with its alpha, real components and real channels appear in the file, and a colour written in the web notation still reads. The importer's reader recovers the colour it was given.

Also checkedBecause
A malformed vector does not throwOne bad entry in a hand-edited file should not take the whole load down.
An omitted alpha comes back visibleDefaulting transparency to zero would make things silently invisible — the same class of failure again.
If you only remember one thing
When something you saved does not come back, open the file before you re-do the work. Empty braces mean the vectors never made it; a colour record with hue and luminance but no red means the same thing in disguise.
10

The numbers

What it measures

Read two bands

Two measurements, each with a tolerance, both taken from the game's own weapons rather than chosen.

CheckExpectedBand
Grip anchor, long guns0.278 m behind the hand±0.010
Grip anchor, handguns0.075 m±0.010
Muzzle offset1.2275 × how far the mesh reaches forward of the grip±2.5%

The muzzle rule is a ratio, not a distance, which is what lets one number cover a pistol and a rifle. It is a least-squares fit through the six weapons the game ships, and what it says is worth knowing on its own: the game spawns the shot roughly 22–23% beyond the barrel tip, scaled to the gun — not at the tip, and not at a fixed clearance.

The grip anchor is the opposite kind of number: absolute, not a fraction. The four long guns sit between 0.2706 and 0.2790 — an 8 mm spread across weapons that differ by 565 mm in length — while as a percentage of length those same six span 16.8% to 52%. There is no invariant in the percentage at all. What is anchored is anatomical: how far the weapon extends behind the hand. The 10 mm tolerance is simply that 8 mm spread with a little room.

11

The idea worth stealing

The denominator

Know decs, not assets

★★ The gate walks every weapon definition the mod ships and resolves each one's mesh. It does not walk the folder of meshes.

That inversion is the whole design. If you count assets, a weapon whose mesh is missing or unresolvable simply is not in the list, and a hole in your coverage reads as a clean pass. If you count definitions, that weapon is a failure, because a definition that cannot reach its mesh is exactly the thing you needed to hear about.

The gate also reports the other direction: meshes no definition references. Those are not coverage, they are dead weight — files your mod ships and never uses. Reporting both numbers means neither can be mistaken for the other.

The general rule
When you build any check, ask what happens to an item that is broken enough to fall out of the list entirely. If the answer is "it isn't counted", the check will pass hardest exactly when things are worst.
12

Self-check

The control group

Read six known-good

Before it judges your weapons, the gate measures the game's own six and asserts that they pass.

The game's weaponGripMuzzle vs expected
AssaultRifle0.27860.825 vs 0.8287  (−0.44%)
HuntingRifle0.27901.000 vs 1.0062  (−0.61%)
DoubleBarrelShotgun0.27060.768 vs 0.7549  (+1.73%)
PDW0.27830.315 vs 0.3147  (+0.09%)
Revolver0.07830.477 vs 0.4776  (−0.13%)
TacPistol0.07140.310 vs 0.3112  (−0.38%)

Those six are not there to be tested — they are known good by definition, being the things the convention was measured from. They are there so that if the gate ever starts failing them, you know the instrument has drifted rather than your mod being wrong.

Look at the spread: the shotgun sits 1.73% off and still passes, the PDW is within a tenth of a percent. That range is exactly why the band is ±2.5% and not ±0.5%. ★ The tolerance is derived from the ground truth's own scatter, not picked — a tighter band would reject one of the game's own weapons, which is a category error in a gate whose entire job is "conforms to how the game does it". The side-by-side shotgun is the only one outside 1%; drop it and the constant tightens to 1.224 with all five inside 0.5%.

Worth borrowing, again
A check that cannot demonstrate it would fail is not evidence of anything. Putting known-good cases through the same path as the real ones is the cheapest way to keep a green result meaningful.
13

In practice

Reading a real run

Do 12 passed, 2 failed

Pointed at the mod the adapter built for the definitions ladder, the gate passed all six control weapons and failed both of the mod's own.

LineWhat it means
FAIL ProbeCudgel: mesh Wood.glb exists The weapon resolves to Models/Items/Wood — the placeholder the exporter substitutes when a weapon has no model of its own.
FAIL ProbeSidearm: mesh Wood.glb existsThe same.
denominator: 2 WeaponDec with a mesh, 1 distinct meshes, 0 .glb referenced by no dec Two definitions, sharing one mesh between them, and no unused assets.

This is the two ladders meeting. The definitions tutorial showed the exporter reporting that it had substituted a placeholder mesh; here is the gate refusing to let that ship. One tells you, the other stops you, and the mod in question is a test fixture that was never meant to pass.

Note also what the denominator line reveals for free: two weapons resolving to one distinct mesh. In a real mod that is a red flag on its own — not an error, but almost certainly not what you intended.

14

Limits

What it cannot tell you

Know geometry, not play

The gate checks that a weapon is positioned to the convention. It has no opinion on whether it is any good.

It says nothing about balance — and as the definitions ladder established, a ranged weapon's damage is not on the weapon anyway. It says nothing about how the mesh looks, whether the silhouette reads at game distance, or whether the thing is fun. And it cannot confirm the game loads your mod; that needs the game.

What it does is remove one entire class of defect from the list of things that might be wrong, which is exactly what a gate is for. Run it before you ship, and the forty-gun morning cannot happen to you.

Course complete

What you now know

Check yourself

  • Vault owns the library; the Mod Kit reads it and never writes it. One writer means "which copy is true" is never a question.
  • The two applications agree on a folder and a format, not a shared type — they could not share one.
  • Use in This Mod copies the asset into your mod's assets/, filed by what it is. The bytes match; the original is untouched.
  • Your mod is self-contained afterwards — no library needed to build or ship it.
  • The button is disabled with no mod open, and enabled once a mod and an asset are both selected.
  • An empty library reads as empty, not as an error, on purpose.
  • Asset lineage travels with the asset — which the shipping tutorial will come back to.
  • Godot structs keep components as fields; the JSON writer takes properties. A raw struct writes nothing of itself, successfully.
  • Vector3 writes {} — the loud failure. Props reload at the origin with zero scale.
  • Color writes its derived properties and omits R/G/B/A — a payload full of plausible numbers that cannot restore the colour. Readers fall back to white.
  • The two fail differently, which is why both are asserted; a vectors-only check would have passed throughout the colour bug.
  • It has cost twice: Atlas prop placements, and the Mod Kit's own importer, where a sensible-looking fallback hid it through review.
  • The fix is scalars on the model, the struct as an ignored computed value.
  • A successful save proves nothing. Round-trip it, or open the file.
  • A weapon has three facts: length, grip origin, muzzle offset. The incident behind this gate was a check that covered one.
  • The muzzle rule is a ratio (1.2275× the mesh's forward reach), which is how one number covers pistols and rifles.
  • Long guns anchor at 0.278 m behind the hand, handguns at 0.075 m, both ±0.010.
  • ★★ The denominator is the decs, not the assets. Count definitions, or a weapon broken enough to drop out of the list will read as a pass.
  • Meshes no definition references are reported separately — dead weight, not coverage.
  • The gate measures the game's own six weapons first, so a failure there means the instrument drifted, not your mod.
  • The ±2.5% band was chosen to admit the game's own spread (−0.61% to +1.73%), not picked from the air.
  • It checks geometry, not play — and it cannot confirm the game loads anything.

That is the assets lane. ★★ The idea worth stealing from it: the denominator is the decs, not the assets — count definitions, or a thing broken enough to fall out of the list will read as a clean pass.