Dicey Table

Assigning a Room or Table

A room and a table are not part of your game's scene document. They are published packs — each with its own repository, its own versions and its own author — and your game holds a reference to one of each.

That is why the Game Editor shows one Room row and one Table row instead of a floor, a ceiling, four walls, their posters and a light list. Composition and construction are different jobs, done in different editors.

Open the Game Editor#

Go to /editor/game/{id}, or open the mod and use OPEN IN → Game Editor in the Projects panel. (It reloads the page, so unsaved changes are confirmed first.)

The Hierarchy collapses to four rows:

Room          Noir Parlour 1.2.0
Table         Hex Wargame 2.0.1
Player Zones (8)
Entities (14)

Nothing was deleted. If your scene has hand-edited room internals — an extra light, a poster, a moved wall — every byte of it is still there. Only the rows are hidden, and the Room Editor is the way back to them.

The assign inspector#

Click Room or Table. The Inspector shows what is assigned:

  • the pack's cover, name and author;
  • its pinned version, and the commit that version resolved to;
  • its licence;
  • Change… / Remove, two ways to open the pack's own editor, and the two content-move buttons described under Moving content in and out of a pack.

(built-in) is what you see before you assign anything, and it is a normal state rather than an empty slot: the runtime's own room look and the default table metrics. Remove always gets you back to it in one click.

The viewport shows the table you assigned#

Assigning, bumping or removing a table re-reads the pinned pack's document and rebuilds the table in the viewport — its model, its colliders and its play surface — so what you author on is what your players will get. The pack is read at the pinned commit, not at whatever is on its branch today.

If that document cannot be read — the pack is gone, the version is missing, the file is malformed — the table is refused and named, and the editor does not quietly put the built-in table back. Object positions are authored against the play surface, so a viewport guessing a height you have not assigned would write positions no player ever sees into your mod.

Choosing a pack#

Change… opens the picker. It lists every published pack of the right type — a room picker never shows a table pack, and neither ever shows a whole game — with Default (built-in) always first.

Every card carries the licence. That is deliberate: your game's listing credits the packs it uses automatically, so the picker is where you learn what you are agreeing to. Before you can apply a pack you tick an acknowledgement naming its licence and its author.

DiceyTable does not check whether one licence is compatible with another. A machine verdict on licence compatibility would be confident and often wrong, and every file involved is public on GitHub either way. The licence is shown, prominently, and the judgement is yours.

Pins, and why there are no version ranges#

An assignment names one exact version1.2.0, never ^1.2.0 or 1.x.

A range would make your table non-reproducible: two players who resolved it a week apart could be running different builds of the same room, and for a table that is not cosmetic — the table supplies the play-surface height every peer computes drag targets against.

So a pin never moves on its own. When a newer version exists, the inspector says so and offers a button:

(i) 1.3.0 is available.   [ Update pin to 1.3.0 ]

Until you press it, your game keeps using the version you chose. A published version is immutable — the label can never be re-pointed at different content — so a pin you made last month still means exactly what it meant then.

If a pinned pack disappears from the registry the row is badged unavailable and the inspector names the id that failed. The pin is kept. Silently reverting you to the built-in look would hide a problem you need to know about.

"Unavailable" is only ever said when the registry actually answered. If the list of published packs could not be loaded at all — you are offline, or the API is having a moment — the inspector says so instead, with a Try again button, and your pin is shown exactly as you saved it:

Could not load published packs. This pin has not been checked — it is shown exactly as saved, and nothing has been changed.

That is a different message on purpose. A failed request is not evidence that anybody's pack was unpublished, and a red "your pin is broken" warning raised by a dropped connection would send you looking for a problem that does not exist.

Two ways to open the pack's own editor#

Both are on the assign inspector, and they do different things:

  • Open Room pack / Table pack tab — an in-app editor tab, alongside your model and script tabs. No reload, no re-authentication, and your unsaved work in this project is untouched. It is the fuller view of the assignment: cover, summary, licence, pin, and the same controls.
  • Open in Room Editor / Table Editor — a browser tab, on the pack's own project.

The second one is only available for a pack that is one of your projects. Someone else's published pack cannot be edited here at all; fork its repository to make your own version.

Why a browser tab and not an in-app one? Each mod has its own local file tree, and one editor tab owns one tree. The pack is a different mod, so editing it means a second tab on a different tree — never a second view of the game you have open. Two tabs on one tree cannot both save; see One mod, one writing tab.

Moving content in and out of a pack#

Two buttons on the assign inspector move content between your game and a pack. They are two ends of the same operation, and both show you exactly what will and will not come along before anything changes.

Extract to a pack#

Available when the row is (built-in) — i.e. the room or table is your game's own content.

It creates a new pack project from that content and leaves your game on the built-in default. Use it when something you built inside a game turns out to be worth publishing on its own.

Some things cannot come with it, and the review step lists every one of them by name with the reason:

  • Table pieces never move into a room or table pack. They are your game's, and they stay in your game — nothing is deleted.
  • A room pack cannot carry seats, zones, snap points, prefabs or scripts; a table pack cannot carry a room, zones, snap points, prefabs or scripts. What it can carry — for a room, the room model and the environment; for a table, the seat ring — moves across.

No pin is written. A pin names an exact published version, and your new pack has not been published yet. Publish it, then assign it from this same row.

Detach & vendor#

The reverse: it copies an assigned pack's content into your game and removes the pin, so your game stops depending on it.

This is the way out when a pack you depend on is unpublished or deleted. A pinned version is immutable and can never be re-pointed, which is a guarantee — but it also means a pin whose pack has vanished stays broken until you do something. Vendoring is that something, and it needs nothing from the pack's author.

It needs the pack's files, so it is only available for a pack that is one of your own projects. If it is not, the button says so rather than sitting there dead.

Detaching a table is lossy, and it says so. The seat ring comes across; the table's model, colliders, trigger volumes, play-surface metrics and budget do not — a game scene has nowhere to put them, because the assigned table pack is the single owner of the play-surface height. Your game falls back to the default table until you assign another table pack. Detaching a room loses nothing.

Changing the table moves your seats#

Seat positions are derived from the assigned table's footprint. Assigning or changing a table therefore re-derives the seat ring — and it tells you first, with a before/after preview, rather than quietly moving your layout. See Player Zones and Seats.

Changing the table can leave your pieces floating — and it offers to fix it#

Tables are not all the same height. Assign a table whose play surface sits 1.17 ft higher than the one you laid your board out on, and every piece stays exactly where you put it — which now means hovering in mid-air. A lower table buries them inside it instead.

Nothing is moved for you. When the two surfaces differ, the Table row shows a preview:

  • the two heights, and the difference between them;
  • a row per object, by name, with its height before and after;
  • Apply and Cancel — and Cancel is a real answer.

Applying moves the objects straight up or down by exactly the height difference, and nothing else. No piece is turned, resized, slid sideways, or dropped onto the new surface. A token 0.1 ft above the old table ends up 0.1 ft above the new one; a piece you deliberately left floating stays floating by the same amount. Your layout is yours — the editor can carry it to a new height, but it will not redesign it.

What it leaves alone, and why#

Two kinds of object are listed but not moved, because the old table was not holding them up:

  • anything below the old play surface — floor tokens, a piece under the table;
  • anything outside the old table's play area — the rectangle the table pack declares. A shelf ornament against the wall is above the surface too, and moving it with the table would send it through the ceiling.

Parented objects are decided as a group: a piece follows whatever its top-level parent does, so a board and everything standing on it move together or not at all.

It cannot see everything, and it says so. A piece resting on a stand that stands on the table looks exactly like a piece resting on the table, and it will be moved with it. Read the rows before you press Apply.

If the new table is smaller, some pieces will end up past its edge. The preview names them and moves none of them sideways — repositioning a layout is a decision, not an adjustment.

Undo (Ctrl+Z) puts the heights back. It does not bring the preview back; re-pick the table from Change… if you want to see it again.

What the Table row deliberately does not offer#

There is no play-surface height field on the Table row, and there never will be.

The assigned table pack is the single owner of that number. Every peer reads it from the same pinned pack at load and uses it to work out where a dragged piece is going. A second place to set it would be a second answer, and a peer with a different answer sends the table wrong drag positions — which looks like a physics bug and is not one.

The model, the colliders, the triggers, the play surface and the seat ring all belong to the pack, and all of them are edited in the Table Editor.

Nobody can change these during a session#

The room and the table are fixed by the game mod. Once a table is running, there is no way to swap either one — not for a player, not for a spectator, not for the host. There is no menu entry, no keyboard shortcut and no setting, because there is no mechanism underneath one: every peer derives the room and the table locally from the same pinned mod, and nothing about them is sent over the network.

Adding a mod mid-session still works and still contributes pieces, prefabs and scripts — but it can never become the room or table provider. That is decided when the table is created, and if a mod's room or table is being ignored the mod list says so.

Collections: which mod supplies the room and the table#

Everything above is about one mod's assignment. A collection is a different thing: a named bundle of mod ids that share one table. It is the only way to put more than one mod on a table, and it raises a question a single mod never has to answer — if three mods are on the table and two of them assign a room, whose room is it?

The answer is a field, not a rule of thumb. Open Collections in the topbar of the Game Editor and pick a collection; the Room & table provider row names exactly one member. Every other member's room and table are ignored, and the members list says so on each of them.

DiceyTable never breaks the tie for you — not by list order, not by "the last one added", not by which one you assigned most recently. A room chosen by an implementation detail is indistinguishable from a broken one, and you would find out from a player.

There are four outcomes, and the row tells you which one you are in:

Members carrying a room or table What happens
exactly one it is designated automatically, and the row says so — you can still change it
two or more, none chosen publishing is refused, and both candidates are named
none the built-in room and the default table are used
the designated member is no longer in the collection publishing is refused — it is never re-assigned for you

That last row is the one worth reading twice. Removing the designated provider from a collection does not quietly promote another member, however obvious the alternative looks. A published version is immutable, so a guess made here would be frozen into every table that ever pins this version.

Every other member says "room/table ignored"#

Each member that is not the provider carries a room/table ignored chip, whether or not the editor can see that it has a room. This is deliberate: a room that is quietly ignored looks exactly like a room that is broken, and the bug report you get is "my room doesn't load".

While no provider is designated at all, the members are marked provider unresolved instead — nothing has been decided yet, and publishing will not proceed until it has.

But your materials are never ignored#

room/table ignored means exactly what it says, and no more. It covers the room model, the environment, the table and the seat ring. It does not cover the materials and textures your pieces are painted with — those travel with the pieces, so a non-provider member's tokens look the way you authored them.

This matters because material names are not unique across mods. Every new project starts with the same four seeded materials — Floor, Wall, Ceiling and Default — so on a collection table there are as many different materials called Default as there are members. DiceyTable keeps each member's materials to itself: a piece from member B painted Default gets B's Default, never the provider's, even though both are called the same thing and both were seeded the same way. You do not have to rename anything, and renaming would not have helped anyway.

The one thing a collection does share is the built-in preset library (Felt, Metal, Oak and the rest). A built-in is the same material everywhere by design, so two members both using Felt are using one material, not two.

If a piece renders with its plain shipped look instead of the material you assigned, the material is genuinely missing from that member — it is never another member's material wearing the same name. Check that the piece and the material are in the same mod.

The designation belongs to the version#

The provider is stored on the collection version, not on the collection. A published version can never be re-pointed, so:

  • the designation is frozen with the version, exactly like the version's member list;
  • a table that pinned version 1.0.0 keeps 1.0.0's provider forever;
  • changing the provider means publishing a new version — a deliberate act, with the same blast-radius preview as any other version bump.

And it is locked when the table is created#

The room and the table are resolved once, when the table is created, from the mod (or the pinned collection version) it was created with. Mods added later contribute pieces, prefabs and scripts and can never change the room or the table — see Nobody can change these during a session above.