# Importing an Asset Pack

> Browse published Asset packs from the Game Editor, preview a prefab in 3D, and import it by reference or as a copy — with the trade-off spelled out.

- Source: https://diceytable.com/docs/editor/workflows/import-an-asset-pack
- Last verified: 2026-08-20

[Building an Asset Pack](https://diceytable.com/docs/editor/workflows/build-an-asset-pack) is the authoring half. This
is the other one: taking somebody's published pack — dice, tokens, a deck, a scripted piece — and
using it in your game.

Choose **Mod ▸ Browse Asset Packs…** in the Game Editor's menu bar (`/editor/game/{id}`). It is the Game
Editor's only, because importing is composition: a Room pack, a Table pack or another Asset pack
has nothing to compose into.

## What the browser shows

Pick a pack on the left and the right pane fills in:

- a **3D preview** of one prefab, rendered from the pack's own model files at the exact version
  you would be pinning — not a thumbnail the author uploaded;
- the strip of every prefab the pack ships, with a code glyph on the ones that run a script;
- prefab, deck and script counts, plus the pack's **declared** draw-call and triangle budget;
- the **capability disclosure** — what this pack's code is allowed to do;
- the licence and the pin (`Pinned to 1.2.0 (commit a1b2c3d)`).

Browsing changes nothing. Opening a pack, flipping through its prefabs and reading its disclosure
write nothing to your project, and — unlike some other tabletop editors — opening someone else's
prefab does not spawn a copy on your table as a side effect.

> If a prefab's model file is not among the files the pack's manifest says it ships, the preview
> says so instead of showing an empty box. A missing file is otherwise unreadable: it fails as a
> parse error about a "bad GLB magic number" rather than as "file not found".

## The capability disclosure is the important part

If the pack ships scripts, a warning block appears above the import controls listing what that
code may do — reading hidden information, spawning objects, calling a plugin, and so on.

That list is not advisory. Every player who joins your table is shown the capabilities of your
game **and of every pack it depends on**, and a warning stays on screen while elevated code runs.
This panel is where you find that out while refusing is still free.

If a pack ships code but its manifest does not describe it — or if its published manifest cannot
be read at all — the pack is disclosed as able to **read hidden information** and says so. That is
deliberate: an empty capability list is indistinguishable from "it declares nothing", so the
system over-discloses rather than guessing.

## The two import modes

Choose one before importing. They are not two spellings of one thing, and neither is the safe
default.

| | **Reference this pack** | **Copy into this project** |
|---|---|---|
| What is written | one pin in your manifest's `dependencies` | prefabs, scripts, materials and the pack's files, copied into your project |
| The author's fixes | reach you when **you** bump the version | never |
| Attribution | automatic — your listing credits them | the pack drops off your listing; only a provenance note remains |
| If the pack is deleted | its pieces stop resolving | unaffected |
| Whose capability declaration governs its code | the **pack's** | **yours** |
| Your repository | unchanged | grows by the copied files |

### Reference

The recommended default. Your manifest gains one exact pin:

```json
{
  "dependencies": [
    { "packId": "acme.dice", "version": "1.2.0", "commitSha": "a1b2c3d…" }
  ]
}
```

Pins are always **exact**. `^1.2.0`, `~1.2` and `1.x` are refused — a range makes a table
non-reproducible between two players who loaded it at different times, and nothing would ever
detect the disagreement.

A newer version of a pack you reference is an **offer**, never a swap. The author publishing 1.3.0
changes nothing about your game until you re-pin, and re-pinning replaces the pin rather than
adding a second one.

### "A newer version exists"

**Mod ▸ Pack Updates…** in the menu bar lists every pack you reference and whether its author has
published something newer. When one has, the menu item carries a count, the **Mod** menu gets a
dot, and a *N pack updates* notice appears at the right end of the menu bar that opens the
same list.

That notice is the *entire* effect of an upstream publish. Nothing in your project has changed,
nothing changed when you opened the editor, and nothing changes by opening the list. The pack's
author cannot move your pin; only you can. The list says which version you are on, which is the
latest published, and offers **Review update…** — which opens the same blast-radius preview
described below.

There is no "update everything" button, on purpose: one press that moved every pin would skip
every preview, which is the behaviour the preview exists to replace.

Two limits worth knowing:

- the notice can only offer the **latest** published version of a pack, because that is what the
  registry reports. There is no way to pin an intermediate version from here;
- if the registry's current version is *older* than your pin — a withdrawal, or a pin written by
  hand — no notice appears. Being offered a downgrade under the word "update" would be worse than
  silence.

### Updating a referenced pack

Pressing **Re-pin to this version** (or **Review update…** on the notice) does not immediately
change anything. Both open the same **blast-radius preview**: what the bump does, item by item,
with Apply and Cancel.

The preview always shows the pin itself moving, and then one row per piece you have placed from
that pack:

- **pieces that change**, with the fields that change and their before and after values;
- **pieces that stop resolving**, if the new version dropped a prefab you were using. Nothing is
  deleted — those pieces render as placeholders, so the situation is recoverable. Staying on the
  version you have is always an option;
- **your own edits, kept.** If you renamed a die, recoloured a token or resized a piece after
  placing it, that edit survives the update and the row says which upstream value it is declining.

That last one deserves the detail, because it is the reason the exact pin matters twice over.
Your edits are worked out by comparing each piece against the prefab **as it was in the version
you have pinned**. A field you never touched still matches that build, so it takes the new value;
a field you changed does not, so it is left alone. Field by field, not piece by piece — recolour a
die and you still get the author's new label.

> The one edge worth knowing: if you edited a piece to a value that happens to equal what the pack
> already had, that is indistinguishable from never having touched it, and it will take the
> upstream change.

Nothing is written until you press Apply, and the only way back afterwards is Undo (Ctrl+Z) —
re-pinning to the old version runs the same update in reverse rather than restoring what was there.

If the pinned build cannot be read (its repository is gone, or the version was withdrawn), the
bump moves the pin **and nothing else**: with no base to compare against there is no way to tell
your edits from the pack's, and the preview says so rather than guessing.

You may declare at most **24** dependencies. That is a comprehension limit, not a performance one:
each is a licence you acknowledged, a capability your players are shown, and a version bump you
have to review.

### Copy in

The escape hatch, and the answer to "the pack I depend on was deleted". It is the same operation
as **Detach & vendor** on the Room and Table rows, and it goes through the same review step: a
list of everything that will **not** come across, shown before you confirm.

What gets copied:

- the prefabs you tick (or all of them), renamed `packid.prefabid` — the same id a referenced
  prefab gets, so switching from reference to copy does not orphan anything you have already
  placed;
- the scripts those prefabs bind, renamed the same way;
- materials the copied prefabs use, **unless** you already have one with that id — yours wins, and
  the review says so;
- the model and texture files, fetched from the pack's repository at the pinned commit and written
  into `packs/{packId}/…` in your project, so two packs' `wood.jpg` cannot collide.

What does not:

- **bundled decks** — a game keeps its decks as `.deck.json` files, which the copy does not write,
  so a prefab that draws from a bundled deck arrives without its cards. Reference the pack instead
  if you need them;
- the pack's declared budget;
- anything the copy cannot fetch. Failures are listed by name rather than leaving you with silent
  placeholder boxes.

> **A copied script becomes your code.** It runs under your game's saved-data scope and is
> governed by **your** manifest's capability declaration. If it uses something you have not
> declared, the import tells you which capabilities to add — it will not add them for you, because
> that declaration is what every player at your table is shown. Publishing refuses a game whose
> declaration does not cover its scripts.

Copying does not remove the licence. The pack's terms still apply to the copy; what disappears is
the automatic credit on your listing.

## Removing an import

**Remove** next to a referenced pack drops the pin. Anything already placed from its prefabs stops
resolving, so if you needed the pieces, copy the pack in first and then remove the reference.

There is no one-click undo for a copy — the copied prefabs, scripts and files are ordinary parts of
your project now, and you delete them the way you delete your own.

## See also

- [Building an Asset Pack](https://diceytable.com/docs/editor/workflows/build-an-asset-pack)
- [Verifying as a New Player](https://diceytable.com/docs/editor/workflows/verify-as-a-new-player)
- [Lifting Content Out of a Pack](https://diceytable.com/docs/editor/workflows/lift-out-of-a-pack)
- [Assigning a Room or Table](https://diceytable.com/docs/editor/workflows/assign-a-room-or-table)
- [Capabilities](https://diceytable.com/docs/mods/manifest/capabilities)
- [What gets rejected](https://diceytable.com/docs/mods/scanner/what-gets-rejected)
