| name | tinyworld-tool-icons-and-modes |
| description | Use when changing Tiny World Builder's mode indicator, boot tool selection, or Esc-to-Select behaviour. |
Tiny World Mode Safety
Mode safety
- Boot always ends on the Select tool:
bootApp calls
selectTool(DEFAULT_TOOL) after loadState(), so a restored world's saved
toolId never leaves a fresh session "armed" for building.
- Build/Play mode is separate from Showcase.
#build-play-mode toggles
body.tw-play-mode, persists tinyworld:build-play-mode.v1, and exposes
window.__tinyworldIsPlayMode() / window.__tinyworldMode. In PLAY mode,
build panels and edit radials are hidden, selection/sub-edit state is cleared,
and mutation paths should be gated through the same edit checks that call
mpEditAllowed().
- First load goes through
#welcome-modal: the rounded .launch-modal shows
assets/twlogo.png with Tinyverse, Battleworlds, Build, and Play buttons,
includes the compact "Created by Jason Kneen" footer with @jasonkneen and
@tinyworldsapp links, and hides app chrome via body.welcome-launch-open.
Build/Play call window.__tinyworldMode; Tinyverse waits for
window.__tinyworldWorlds.open() (or the tinyworld:worlds-ready signal)
and opens the Worlds frontend rather than silently falling back to Build.
Battleworlds calls window.__tinyworldBattleworlds.open() when present and
otherwise falls back to Play. Do not bring back the old farm/vehicle welcome
picker for this path, and keep publish.sh copying the assets/ directory
into dist/assets/.
- Showcase mode keeps only a simple top-right circular
#showcase-exit X
button visible. Do not turn it back into a wide "Exit Showcase Esc" text pill;
keep aria-keyshortcuts="Escape" and the existing Escape handler that calls
setShowcaseActive(false).
#mode-indicator (HUD chip, updated in updateModeIndicator in
19-tools-toolbar.js) names the current mode and colours itself: calm
mode-select, amber mode-build, red mode-erase. Keep it
pointer-events:none.
Esc disarms any build/paint/erase tool back to Select (handler in
20-input-place-erase.js, skipped in first-person walk mode).
- The View modes popup has five modes: top-down, isometric, perspective,
third-person walk (
tp), and first-person walk (fp). Both walk modes are
driven by the same fp controller in 20-input-place-erase.js; tp shows a
chase camera behind the voxel avatar, while fp uses the avatar rig's
getEyeWorldPosition() and hides the head via setFirstPerson(true).
Keep tp in camera-mode schema/import allowlists when touching saved camera
validation.
- Both walk modes are home-builder only. The
fp avatar is added to the
shared worldGroup, so it must never coexist with a Tinyverse room's own
networked avatar or the player sees two copies of themselves. setCameraMode
redirects fp/tp to perspective while window.__tinyworldInWorldRoom is
set, and 47-worlds-room.js enterRoom calls window.__tinyworldExitWalkMode
(exposed from 20-input-place-erase.js) to dispose any active walk avatar
before spawning the room avatar. The room's own first-person is the surface
roam zoom-in (v key, _sr* in 47), not the builder fp controller.
Gotcha
npm test (tools/check.js / smoke-static.js) reconstructs the split app
from tiny-world-builder.html plus engine/**/*.js. Update those static guards
when changing boot mode, launcher chrome, or mode persistence.
Bottom toolbar vs floating block palette
- The grouped bottom
.toolbar is the default. The "Show groups" checkbox in
Settings → App (#toolbar-show-groups, persisted as tinyworld:showGroups,
default on) switches modes. When off, body.hide-groups hides only the
bottom toolbar's block tools/group buttons and a floating, resizable,
draggable #tool-palette shows every placeable block (select + all
TOOL_GROUPS tools with house variants expanded + erase). The bottom
toolbar itself must stay visible for utility controls such as Build/Play,
Home, Shield, View modes, Time/weather, Sound, Layers, Settings, and Account.
- The palette is a self-contained module:
engine/world/35-tool-palette.js.
Blocks are built with buildToolButton(t, { flyout: true }), so they keep
their colors and are highlighted by the same updateToolActiveStates() loop.
- Small screens force grouped mode.
showGroupsEnabled() returns true on
<=700px regardless of the stored pref (isSmallScreenForGroups()), the
checkbox is disabled there, and a resize listener re-applies across the
breakpoint. The floating palette is unusable on phones, so never let it open
there. The phone toolbar is also compacted to icon-only (labels/chevrons
hidden, smaller buttons) in the @media (max-width: 700px) block.
The grid uses fixed 64px square cells (repeat(auto-fill, 64px)), so resizing
the panel reflows blocks to the nearest square. buildToolbar() calls
rebuildToolPaletteIfActive() so toolbar rebuilds refresh an open palette.
- The group popout flyout (
.flyout.tool-menu) lays its icons out as a
2-row grid block (gridTemplateColumns: repeat(ceil(n/2), auto) set in
renderToolGroupFlyout).
- The old vertical
.controls rail is no longer visible. Keep its element IDs
in the DOM as stable wiring targets, but put everyday chrome in the bottom
toolbar: Build/Play, Home, Shield, View modes, Time/weather, Settings, and
Account. Import/export must remain owner-gated and should not be added to the
normal user toolbar.
- The old
#mode-indicator HUD chip has been removed from the DOM;
updateModeIndicator() still runs but no-ops on the missing element.
- In Tinyverse multiplayer HUD chrome, account sign-out is the only place that
should use the door-arrow
leave icon. The in-world exit that returns to the
world picker uses tw-hud-back-worlds, the reply glyph, and
worlds.backToWorlds so it is not confused with logging out.