Skip to content

Latest commit

 

History

History
2097 lines (1965 loc) · 131 KB

BACKLOG.md

File metadata and controls

2097 lines (1965 loc) · 131 KB

Lamium backlog

Work the maintainer has decided to pursue. Ideas are discussed first and enter this file only once they are to be worked on; each gets the next free L- number, a kind and its open questions. A task with an open user-visible choice is Design, whoever writes it down.

Each task has a kind, which decides who should pick it up:

Kind Meaning Who
Ready Spec is complete; mostly pure logic + tests + small glue Any agent, including cheap models
Design A user-visible choice is open. Output is a spec (often a web demo) that turns into Ready tasks Maintainer + strong model
Research Needs native reverse engineering, trace builds or runtime-driven debugging Strong model; cheap models may only collect traces
Refactor Preserves behavior while changing internal structure Follow the item's model and validation requirements

Ready tasks marked (strong model) are fully specified but visual or cross-cutting enough that a strong model should implement them.

A large or open-ended feature (Map, placement and breaking features, Schematic) starts with a conversation with the maintainer about what it should be - purpose, scope, what is left out - before any spec, spike or mockup (decided 2026-09-28).

Bugs (something that ships behaves wrongly) are listed first in their own section and are fixed before new features. Each bug still has a kind that decides who picks it up.

Finished and closed items live in BACKLOG-DONE.md with their full history. An L- number referenced elsewhere that is not in this file is there.

Long feature contracts and dated build/research records are linked from the L-item (MAP.md, SCHEMATIC.md); current status and remaining work stay here. Document roles: README.md.

Release policy (decided 2026-09-28)

Lamium is developed at the maintainer's pace, for their own use first, and published for whoever wants it. There is no "first release" gate.

  • Release when a meaningful set of changes has landed and main builds, passes the tests and has no known crash. Before tagging, smoke-test the release build (the mod loads, settings open, the changed features work) and update the README feature tables and Known issues, and FEATURES.md. A full regression is not required. From 0.4.0 the smoke test uses the commit's CI package and the tag's CI run attaches the assets to a draft release (DISTRIBUTION.md).
  • From 0.1.4 on, releases are ordinary GitHub releases, not marked pre-release: the 0.x version, the README status and the Experimental badges say what is unfinished.
  • Pushing a v<version> tag is public distribution. The LIP registry picks up every semver v* tag, including -rc.N style prerelease tags, whatever the GitHub pre-release flag says, and LeviLauncher offers it. A build meant only for testing is shared as a CI artifact or branch build without a tag, not as a GitHub pre-release.
  • The version is set in xmake.lua and tooth.json. The asset is Lamium-<version>-client-windows-x64.zip, built by scripts/New-ReleaseArchive.ps1 (never by hand); the folder inside stays Lamium/, and release notes name the asset the same way. The LIP registry adds each v* tag through a registry PR, so Bedrinth and LeviLauncher pick up a release without a registration step. Package rules and the release checklist: DISTRIBUTION.md.
  • Large features may start at any time. They land on main in steps, default off and with the Experimental badge, so main stays releasable while they grow. A step that is not usable yet stays out of the settings screen (or behind a build option) instead of being shown half-working.

Current execution order

Keep this section short: ordering lives here; status, contracts and open choices live in the L-items. An L-item wins if a summary drifts.

  1. L-305 move to Minecraft 1.26.60.05 / LeviLamina 26.60. The verified game is 1.26.60.05. Open: the symbols for book paste and an offhand map, and L-306.
  2. Bugs first. L-227 FreeCamera shows only the sky outside loaded terrain (Research; new native experiment needs the maintainer's go-ahead). L-177 mismatch-highlight fix is built and awaits the reporter's next schematic session, not another implementation. The 2026-10-31 maintainer reports are L-288 to L-291 (Fake Offhand twice, Hand Restock, schematic water materials): all are closed (checked 2026-11-01, BACKLOG-DONE), with L-285 (ghost pick at the feet block) after its trace. L-292 (Fake Offhand key without primary priority) is closed (checked 2026-11-01). L-293 (placement as if sneaking, toggle) is closed (2026-11-01). L-294 (water icons) is closed (2026-11-01). L-300 (block entity data in the target card) is closed (checked 2026-11-03); L-301 (a note block's pitch from the sound events) is closed (checked 2026-11-03). L-302 (a ghost's actor-drawn contents) and L-303 (the check ignoring block entity data) came out of the L-184 in-game check; both are closed (checked 2026-11-04). L-304 (a real liquid behind a ghost) is closed (checked 2026-11-03). Parked: L-192/L-193/L-194 schematic drawing, L-123 elytra pose, L-91 shield glint and L-132 inventory-screen movement; respect each item's stop/resume conditions. L-181 trident pose is low priority. L-247 and L-248 are merged (2026-10-27), checked in game and closed 2026-10-31 (BACKLOG-DONE); L-244 is parked (see its item).
  3. Small and medium work before large features/integration (maintainer 2026-10-10): L-253 is closed (checked 2026-10-31) and L-286's minimap camera arrow is merged; the arrow-look follow-up is L-287, parked. L-246, L-252 and L-254 are done. L-266 schematic follow-up batch closed with the 0.3.1 release (2026-10-27): stages 1-3, L-264, stage 4 (L-256) and L-263's creative pick are all checked. Still open from it: L-265 placement assist (Design). L-196 license/provenance review closed 2026-11-01; L-236 is a follow-up; L-295, L-296 and L-297 (map layers) are done 2026-11-01; remaining Design/Research in L-166 trade helpers, L-167 resource packs, L-168 trade finder, L-169 transfer extensions, L-170 enchantment planner, L-173 quick shapes, L-190 list selection and L-163 a Lamium inventory screen, L-259 book paste overflow (on main and checked locally; edge cases left, see the item). Agree open choices before building. L-165 Mass Craft remains below Map and needs a scope conversation; existing packs already cover part of that need.
  4. Schematic follow-ups (L-93): choose among L-114/L-115/L-116, L-183/L-184/L-185/L-186 and the remaining name-tag issue L-117. The initial feature and 0.1.8 work are complete, not new tasks.
  5. Placement/breaking: L-15 breaking redesign before placement; L-59 held-placement style waits for the maintainer's go-ahead.
  6. Optional integration (L-111): shared spatial actions, a common menu, selection and cross-links; the required 0.2.0 steps are complete.
  7. Research when convenient: L-79 pumpkin/spyglass frames, L-71 glide initiation, L-30 dragon hitboxes, L-33 mob timers, L-105 profiling. L-151/L-152/L-153 and the previously parked work remain later.
  8. Before the next release: changed-feature smoke and the relevant Pre-release checks below. Latest release: 0.5.0, 2026-11-04 (v0.5.0). No next date is selected; a full regression is not a release gate.

Task-picking rule: bugs first, then this order; follow each item's model, dependencies and validation requirements. Cheap models skip Design, Research and strong-model work. Completed work moves to BACKLOG-DONE.md; remaining runtime gaps go below and in VALIDATION.md.


Pre-release checks

The Release policy requires a smoke check of the actual release build: load, settings and changed features. Choose relevant checks from these known gaps; a full regression and every server case are not release gates. VALIDATION.md owns current per-feature coverage; VALIDATION-LOG.md owns build/hash evidence. Do not infer game success from a build or unit-test result.

Since 0.5.0

Left from the 0.5.0 tag (L-305, VALIDATION-LOG 2026-11-04):

  • The published ZIP loads through LeviLauncher on a fresh instance with LeviLamina installed first, and LIP offers it there (tooth.json's range changed).

Carried from 0.4.0:

  • Schematic check of block entity data (L-303): a smoke of the release build (a changed sign or note block is a wrong state with a yellow mark; "Ignore block entities" clears it). Unchecked so far: "Ignore sign text" on its own; banners, beds and pot sherds changed by hand; a lectern page turned by another player; scan time with many block entities; servers.

Left from the 0.4.0 tag (VALIDATION-LOG 2026-11-01):

  • Release flow (L-298): LeviLauncher installs the published 0.4.0 ZIP. The draft, its two assets and their SHA-256 passed on the tag's run.
  • Listings (L-196): the Bedrinth and LeviLauncher pages show tooth.json's description with both the LeviMC and the Minecraft notices.

Gaps carried from released builds

These are follow-up coverage, not unfinished implementations or release gates for versions already published. Full old release/smoke/regression checkpoints are retained in BACKLOG-DONE.md, under "Archived release and validation checkpoints" (snapshot 2026-10-20).

Area Remaining targeted checks
Maps, L-205/L-206/L-210/L-211/L-215/L-225/L-226/L-228 Frame times with recording off/on at 32/64/96 chunks and minimap off/on; nearby edits and movement during a wide pass; cave/Nether frame times and per-band coverage if the footprint difference recurs; broader servers. Only client-received terrain can be recorded.
LMR2 regions, L-216 Older-build fill-only merges, refusal without overwrite, damaged-file recovery, 10 s failed-save retry, measured frame times, broader servers; a focused live check of the review follow-ups (save batching, legacy warnings, cave provisional tint).
Map storage on servers, L-241 (c) A server without map storage keeps its map while moving far and back, and the temporary folder is gone after leaving.
FreeCamera, L-207/L-213/L-214 Frame times per underground-hold choice, servers, broader graphics/resource/lifecycle cases. The loaded-area sky bug is L-227.
Connected Textures corners, L-208 Resource packs, live resource reload, servers.
Target/HUD/settings, L-217 to L-224 Remaining language, size, input and server gaps in VALIDATION.md.
Item Transfer, L-169 Held-stack/drop gestures passed the local chest checklist; try inventory and slot-role screens, servers and a rebound drop key. Full gesture/screen matrix, cursor/hotbar/keep-one/re-entry/saved-switch cases, controlled rejection/timeouts, world/dimension interruption, unverified-game fallback and packs remain. See ITEM-TRANSFER.md.
Shared capability migration, L-198 to L-202 Server/server-pack smoke. A separately requested forced-unverified build should check vanilla fallback and matching UI/notices while independent paths work. Injected hook/cleanup failures and partial-loss/restart UI remain unverified in game.
Settings/help and map layers, L-197/L-146 Broader sizes, languages and editing states; narrow-window two-row map bar. Use current DESIGN and VALIDATION, not superseded footer-expansion checkpoints.
Chat position, L-174/L-203 Fresh settings, GUI scales/Pocket UI, packs, world/dimension/focus and servers beyond the recorded local checks. See CHAT-POSITION.md.
Edge Guard, L-162 Longer play, other servers, slippery blocks; correction that already puts feet off support remains a limit. Preserve environment/build/log if a fall recurs.
Repeated trading, L-166 part 1 Real RTT/loss and other servers, price changes, forced exit with a pending response, timeout/dimension cancellation isolated from earlier stops; controlled MC_SERVER delays do not establish network behavior.
Effects/ammo HUD, L-147/L-150 Beacon effects, server updates/counts, Pocket UI, layout sample, F1/inventory interplay.
In-world language/server packs, L-167 English Search and schematic ghosts after a change, broader servers/packs, rapid switching/hang risk and the 10 s interval. Cosmetic BDS evidence does not establish all pack types. See LANGUAGE.md.
Camera and visual effects FreeCamera world-exit/death/controller/body-view and hold-input cases, speed restart persistence; Hide effects restart/keys/master, ambient layers, packs, graphics modes and lifecycle. Detailed coverage is in VALIDATION.md, CAMERA.md and VISUAL-EFFECTS.md.
Schematic ghost pick in creative, L-263 A block not carried is given into the hotbar (empty selected slot, another empty slot, full hotbar), unlisted items (water, lava, structure block) do nothing, carried and survival picks unchanged; also on a server.
Distribution listings 0.1.4–0.1.8 registry pickup is recorded; LeviLauncher 0.2.0 was seen. Later registry/LeviLauncher/Bedrinth checks remain unrecorded here. Verify the version being released using DISTRIBUTION.md rather than reopening old release gates.

Bugs

L-305 Move to Minecraft 1.26.60.05 and LeviLamina 26.60

Kind: Update. Follows the playbook in GAME-UPDATES.md. Built against SDK 26.60.0 on 2026-11-04. The gated features passed a round in game the same day (VALIDATION-LOG), so verifiedGame is 1.26.60.5.

Open:

  1. Trace builds. Only transfer_trace was built against 26.60 among the trace options; the others may need the same treatment.
  2. Offhand map stays drawn with Hide Offhand on (regression from 26.51). It does not go through the render calls Lamium can hook, and the likely target is not exported: ?_renderMiniMapHand@ItemInHandRenderer@@QEAAXAEAVBaseActorRenderContext@@AEAVPlayer@@_N@Z. Added to the symbol request on 2026-11-04; whether it draws the map is unconfirmed.
  3. Launching on 26.60. An instance where PeEditor ran after LeviLauncher's import patch fails at launch: the import table is left unaligned and LeviLauncher.dll rejects it (Cannot install directory imports (Windows error 193), exit 0xC0000142). Lamium is not involved. Repeat PeEditor on the original executable, so that the launcher patches last. Reported as LiteLDev/LeviLauncher#176. A separate install failure on slow connections, as LiteLDev/lip#402.
  4. Symbols. LAMIUM_MCAPI_PENDING (xmake.lua) holds these back, because the SDK does not export them. Remove it once they are available. The book paste list was filed in LiteLDev/mcapi-requests on 2026-11-04 and passed its automatic check; it was closed as completed on 2026-11-04, and bedrock-runtime-data v26.60.5-client.6 followed. LeviLamina 26.60.0 pins client.5, so an instance gets the new data only with a later LeviLamina; building against it before then would fail on players' installs. Not yet checked that client.6 holds these symbols.
    • Book paste (L-259, stays vanilla): ?$preFrameTick@BookScreenController@@QEAAXXZ, ?$_isStillValid@BookScreenController@@QEBA_NXZ, ?_addPageAt@BookScreenController@@QEAAXHAEBUPageContent@@@Z, ?_parsePageText@BookScreenController@@QEAAXH@Z, ??0PageContent@@QEAA@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$optional@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@Z, ??1PageContent@@QEAA@XZ, ?handleFocusSet@TextEditComponent@@QEAAX_N@Z, ?trySetText@TextEditComponent@@QEAA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z, ?_textFitsInControl@TextEditComponent@@QEBA_NAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z, ?feedText@TextEditContext@@QEAAXV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z, ?_setText@TextEditContext@@QEAAXV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z. The trace build also needs other functions this list leaves out.
    • Ghost note block instrument (no row on the card, not compared in the check): ??$tryGetComponent@UBlockInstrumentComponent@@@Block@@QEBAPEBUBlockInstrumentComponent@@XZ. The request's check rejects it because the template is declared MCAPI, but this instantiation does not link. Needs another way to read the component.

A note block's instrument name without a Lamium translation now falls back to its number, because noteBlockInstrumentToString is not exported.

L-306 A glass pane edge at a chunk border changed in 26.60

Kind: Bug. Reported 2026-11-04 on 1.26.60.05 with Connected Textures on: an edge is drawn at a chunk border where the pane continues. On 1.26.51.01 the same spot has an edge cut off at the border instead, so neither is right. Other glass joins correctly across chunks. Hypothesis, not checked: partsAt in ConnectedTexturesHooks.cpp asks a neighbor pane for its shape, which depends on that neighbor's own neighbors, two blocks away; the region a chunk rebuild reads may not reach that far. A bent lower row beside a straight upper row also looks odd, on both versions; the maintainer takes that as unfinished design, not this bug.

L-276 A temporary waypoint whose removal cannot be saved is never announced again

Kind: Bug. Review finding 2026-10-27 on 08da0c47: waypoints::arrive() in src/features/map/WaypointSession.cpp called ArrivalWatch::update() before it saved the set with the reached waypoints erased, so a failed write left them in place but no longer armed: standing still never announced them again until the player left and came back. Fixed in src/features/map/Waypoints.h: ArrivalWatch::plan() returns the reached ids and the state that goes with them, and arrivalStep() erases the reached waypoints from a copy, hands it to the store and applies the plan only once the store reports the copy written. A failed save announces nothing and leaves the waypoint armed, so the announcement comes on the frame the write succeeds; the announce rules themselves are unchanged. The armed ids are an std::unordered_set instead of a list, because every HUD frame looked each temporary waypoint up in it (isArmed) with up to 1000 entries. Status 2026-10-27: the normal path is checked in game on 9006c175 (one toast, the waypoint removed); the save-failure path - read-only waypoints.json, no toast and the waypoint kept, removed only once writes work again - is still to check. Table test in tests/WaypointTests.cpp (arrivalSave) covers a save that fails first (the waypoint stays and a later frame announces it) and one that works (announced once, the other waypoint kept). In game: add a temporary waypoint, walk away and back (announced once, removed); then make the waypoint file read-only, add and reach another (nothing announced, it stays), make the file writable again and stand there (announced and removed).

L-274 Ghost pick cannot tell a refused pick from an accepted one

Kind: Bug. Review of L-263, 2026-10-27. game::movePair and game::giveCreative returning true only means the transaction was sent, and GhostPick.cpp discarded the result: a server that refused the move looked exactly like an accepted pick. Decided: confirm from authoritative state on a later frame. The pick is remembered as PickPending (slot, wanted name and data value, the frame it was sent on) in src/features/inventory/PickConfirm.h; pickConfirmed() compares the slot's contents with the wanted item and data value. The read waits pickConfirmFrames frames first, because the slot holds the predicted contents right after the send and only the server's answer replaces them. stepPick(LocalPlayer&) in GhostPick.cpp runs from the ghost pass's per-frame hook (LevelRendererPlayer::$renderEntityEffects, the entry the ghost drawing already uses, no new hook), reads the slot once, logs one pick not confirmed: slot N wanted <item> <aux> holds <item> <aux> line (holds nothing when the slot is empty) when the contents differ, and forgets the pick. A newer pick replaces the waiting one and stopping the feature clears it. Status 2026-10-27: the accepted path is checked in game on 9006c175 (a successful pick logs nothing); the refused path - one pick not confirmed line - still needs a server that refuses the give or the move. Tests in tests/FetchSlotTests.cpp for pickConfirmed (name, data value, empty slot, empty pick) and for PickPending::due (the frame itself, the frame after, the last frame before the read, after it, cleared and item-less picks). In game: a pick the server refuses must log that line instead of passing silently; an accepted pick must log nothing.

L-299 Screenless inventory moves can leave a slot stuck when client and server desync

Kind: Research. Origin: a Discord report (2026-10-31, reporter not named) said Hand Restock "locks" the hotbar after placing a lava bucket. The maintainer could not reproduce it in single-player or on a BDS (1.26.51) with matched settings, and closed the thread on 2026-11-01 as not reproducible: the stated conditions kept changing and the requested log was never sent. Reopening was gated on exact steps that anyone can reproduce using publicly available releases only, with that session's log and a short video.

Why this is tracked anyway, and not as a Hand Restock bug: another mod developer noted on Discord (2026-11-02) that this class of item lock-up is generally a client/server desync. It can happen in a local world too, because a local world still runs on an integrated server; it showed up often in the redstone era before native client mods, always when acting too fast, and item pickup and consumption gave the same trouble in recent mod work. That matches Lamium's own records for the shared screenless-move path, which Hand Restock, Transfer, Sort and the equipment swaps all use (game::beginTransfer, movePair):

  • HAND-RESTOCK.md ("Ordering the move"): the server runs a legacy use in its next tick but applies an inventory transaction on receipt, so a move sent right after a use reached the server first and was rejected on BDS (a41f0f2). The move therefore waits for a server update showing the consumption; a local prediction or a sent transaction is not server confirmation.
  • DESIGN.md (bulk moves, L-169): a traced resource-pack bulk move sent up to 44 requests in one frame (2026-10-15); Lamium waits for all responses and checks touched slots against the authoritative state. A rejected or timed-out request, an unexpected prediction or a changed source stops the operation and drops the queue; vanilla rolls back its rejected predictions.
  • The reporter's own session showed the shared layer's log line "Inventory transfer stopped: response 2" — TransferSession.cpp stopping with "request not accepted" when the result is not Accepted. The log's source is the shared transfer session, not Hand Restock itself.
  • README's known limits already say rejected moves on laggy servers are untested for Inventory transfer, and that server timing and very fast use may make Hand Restock skip a refill.
  • Maintainer's own experience while building the shared screenless-move foundation under Hand Restock (recalled 2026-11-02): a desync lock of this shape did occur, and leaving and rejoining the world cleared it. Whether anything short of a relog also clears it was not established.

Direction (maintainer, 2026-11-02): the desync predates native client mods — fast vanilla play could already produce it — so suppressing occurrence is not the promising line; Lamium's own moves can at most avoid adding to it. The promising line is repair after the fact. Deliberately re-trigger the desync seen while building the shared foundation, observe exactly which state is stale, and catalogue recovery steps from lightest to heaviest. If a safe in-session resync exists, shipping it as a recovery feature is on the table. Any such feature may only restore from authoritative server state — never synthesize, rewrite or forge items — and must fail open to vanilla.

Research questions, in order:

  1. When a transfer is not accepted, or a server correction lands in the middle of an operation, can any Lamium state outlive the failure — a pending operation, a transfer token, a predicted snapshot — and make a slot behave as locked afterwards? The decided rules say operations stop and queues drop; verify the failure paths actually release everything.
  2. Does vanilla alone, with no Lamium, leave the same stuck slot under fast repeated use/pickup/consumption? The comparison is for learning the shape of the residue, not for assigning blame: occurrence in vanilla is expected, and it is what makes the recovery line the product of this item.
  3. Which recovery clears a stuck slot, and what is the lightest reliable one? A relog is already known to clear it (the maintainer's experience above), so in that case the authoritative state was intact and the residue lived in session state. Test the lighter steps — reopening the inventory, interacting with the slot, changing dimension — and record which ones work; each working step narrows where the residue sits and is a candidate for what a recovery feature would do. This is why the original thread asked it first.
  4. Can a stuck slot be detected from client-visible state, and can the client obtain a fresh authoritative inventory snapshot in-session — the thing a relog does — without leaving the world? These two answers decide whether a recovery feature is feasible at all, and whether it would be automatic or a manual action.

Gate: no fix work from the original report; it does not meet the 2026-11-01 reopening condition. The research above starts from the maintainer's own deliberate re-triggering, or from a public reproduction, or from a session log that pairs the "Inventory transfer stopped" line with the state of the stuck slot in the same session.

Check if a reproduction is found: the stuck slot's contents before and after each recovery step; whether another Lamium operation owns the transfer tracker at that moment; the same fast-use sequence with each screenless-move feature on and off in turn; local world and BDS. No release target selected.

L-243 Large terrain gaps that only reload when the player comes near

Kind: Bug / Research, not reproduced; watch item. Maintainer report 2026-10-22 on fca2ef9 (0.3.0), local world, after dimension changes, world map teleports and FreeCamera use: large areas of terrain, near and far, are missing (sky shows through the ground). Looking at them does not bring them back; only walking or flying near reloads them. Earlier rendering glitches (distance fog hiding) recovered when looked at; this does not, and was not seen before. Not yet known: which change since 0.2.3 is involved (candidates: the FreeCamera spectator culler gate and underground hold L-207/L-213/L-214, the distance fog change L-212, map recording now centred on the camera L-241, or teleports themselves); whether it happens without FreeCamera, with the world map recording off, with Hide effects off, or on 0.2.3. First step: the maintainer's A/B answers, then a bounded trace if needed. Related: L-227 (FreeCamera far out shows only the sky). A/B the same day: with everything on and with FreeCamera, map recording and Hide effects each used or avoided, already generated Overworld chunks never failed to load again; the gaps did not come back under any condition. Not a 0.3.0 blocker while it cannot be reproduced; reopen with the conditions if it returns. Seen while trying (2026-10-22), likely vanilla: in the Nether, walking toward chunks that were never generated only generates them out to about the fog distance around the body, whatever the render distance; FreeCamera moving alone generates nothing, which with fog hidden looks like missing terrain. Chunk generation follows the body; not a Lamium change.

L-244 FreeCamera keeps the inside-a-block view after starting in a block

Kind: Bug, parked as research 2026-10-27 (see the end of this item). Maintainer report 2026-10-22: start FreeCamera while the body's head is inside a block (buried in the ground); the camera then shows the inside-a-block screen effect the whole time, also while flying in the air. The effect should follow the camera, not the body, or be suppressed while FreeCamera owns the view. Not a 0.3.0 blocker (leave the block first). Decided (maintainer 2026-10-26): while FreeCamera owns the view, the inside-a-block screen effect is not drawn; outside FreeCamera it stays vanilla. Find the game path that draws it (record it in GAME-UPDATES.md), gate the suppression with versionSensitiveAllowed() and fail open to vanilla. Check in game: start FreeCamera with the head buried and fly out; leave FreeCamera while still buried (the effect returns); Freelook and the ordinary view unchanged. No release target selected. Built 2026-10-27 (29022178), not yet checked in game: the view the game builds for the local player (LevelRendererPlayer::createViewRenderObject) carries ViewRenderData::mDrawInsideCubes; while FreeCamera owns the view FreeCameraInsideBlock.cpp clears that flag on the frame's own copy, gated (FreeCamera view) and fail-open. The SDK's InsideCubeRenderer and InsideBlockEffect declarations are empty, so this flag is the only reachable path (GAME-UPDATES.md). One log line "FreeCamera view: inside-a-block effect not drawn" marks the first frame suppression reached; the four checks above remain. The hook returns ViewRenderObject by value (13 KB, MCAPI), so the game has to pass the sret through on every call: a crash on world entry would point at that return path first. Checked in game 2026-10-27 (merged line 3ac38a3a, DLL 81006cda): the effect stayed after flying out of the block, so the shipped clear did not work. A probe build (e88bb2a7) logged once per 60 frames whether FreeCamera owned the view, the incoming flag and whether it was cleared: while FreeCamera flew in the open the answer was suppress true, vanilla true, cleared true every line - the flag was cleared on every frame and the effect still drew - and the actor answered getInsideBlock() = air. mDrawInsideCubes is therefore not what drives the effect. A second probe (68e32ba3) returned null from Actor::getInsideBlock() while FreeCamera owned the view: the game crashed at once (0xC0000005, mov rax, [rax+0x68], RAX = 0; logs/crash/trace_2026-10-27_10-13-33.log), so that answer is dereferenced without a null check elsewhere and cannot be suppressed. Parked 2026-10-27 (maintainer): not fixable through the exposed SDK paths - the flag is not the driver and the actor answer may not be nulled - without reverse-engineering the renderer that consumes it. Left vanilla, not a release blocker (leaving FreeCamera once restores the view). The hook and its FreeCamera view capability, all four translations, the test and the docs were removed 2026-10-27 (73584825): it was a no-op in practice and its "effect not drawn" log line could be read as success. The item stays parked as research; the crash evidence above still stands as the reason the actor path is closed.

L-245 Ghost face disappears next to real glass or a beacon from some angles

Kind: Bug / Research, low priority. Maintainer report 2026-10-22 (0.3.0, 2900d1dc): a white stained glass ghost next to real white stained glass or a beacon shows no face at the shared plane from some angles. cullAgainstGhosts treats a real blended full-support block as covering the ghost face (realOpaque), assuming the real face is drawn. The game also culls the real block's back face from inside it or at some angles, and draws a beacon beam similarly, so both faces can be absent. Same family as L-192/L-193/L-194 (real see-through blocks and ghost faces). Not a 0.3.0 blocker; record before changing the face rule. First step: reproduce with one ghost and one real glass/beacon block, note the camera side, then decide whether to keep the ghost face where the real block's face is not visible from the camera.

L-257 FreeCamera culler reads blocks on the render thread

Kind: Research. Split from L-242 (pre-0.3.0 review) on 2026-10-26. The FreeCamera culler hook reads BlockSource::getBlock on the render thread. Confirm whether that read is thread safe (or how vanilla reads blocks there) before changing it; do not change it without runtime proof.

L-240 Death layout restore sometimes restores unexpectedly or wrongly

Kind: Bug / Research. Maintainer report 2026-10-22 (everyday use, builds not recorded): Death layout restore sometimes acts after a death the player does not recall ("did I die there?"), and when it restores, the result sometimes looks wrong. Hard to reproduce or pin down because deaths and pickups are hard to observe. Keeps its Experimental badge in 0.3.0 (DESIGN.md). First step: decide what to observe (which death a restore belongs to, the recorded layout versus the pickups applied) and whether a bounded trace build or an in-game log line per restore is the cheapest way to catch it; no fix before a concrete case.

L-227 FreeCamera outside the loaded area shows only the sky

Kind: Bug / Research. Maintainer 2026-10-19 (9a565f0): with FreeCamera flown out past the render distance, all terrain disappears, also the loaded terrain near the player that should still be in view; only the sky and environment draw. Rejected 2026-10-19: the L-207 culler gate. With the underground hold set to Always (the spectator culler for the whole session, as before L-207) the maintainer still saw only the sky. Where (maintainer, by eye): about one chunk past the edge of the loaded area, all at once, while the loaded terrain is still well inside the camera's render radius. So something keyed to the camera's own position having no chunk, not the render radius. SDK (26.51.5 headers, 2026-10-19): the culler classes (LevelCullerBase, LevelCullerDistanceField*, LevelCullerManhattan, LevelCullerNone, VisibilityExtimator) are empty there, so the walk cannot be read. LevelRendererCamera has the camera-centered view area (mViewArea, updateViewArea/setViewArea, mViewAreaDistance), mLastCameraPos, shouldCullThisFrame(lastNumRenderChunksVisibleFromCullingPoint) and _createCuller(type, ...). Candidates to test with a trace build, not decided: (a) when the camera's chunk is not loaded, request another culler type through the L-37 hook (types other than 3 and 5 are not mapped yet); (b) find what the "culling point" is and whether it can stay at the nearest loaded chunk. Each is a new game dependency (GAME-UPDATES.md) and needs the maintainer's go-ahead. Terrain beyond the loaded area stays out of scope (CAMERA.md). CAMERA.md

L-177 Schematic mismatch highlight appears at the wrong position

Kind: Bug / Research. User report 2026-10-14. Status: cause found and fix built 2026-10-14 (0235527), not checked in game. Maintainer 2026-10-15: checked when the reporter next uses the schematic features; no dedicated check before that. Details from the reporter: with a layer view, Show in world / Nearest mistake lit a cell far above the shown ghosts; showing it again was right. Changing layers or moving a placement restarts the check, but the last complete result stayed published, so the pointer used a cell from the earlier layers. The result is now kept for the list but marked stale, and Show in world / Nearest mistake say "still counting" until the new pass finishes. Check in game: change the layer, at once press Nearest mistake (counting), then after the pass it lights a shown cell. Original report: a highlighted discrepancy in a placed schematic can appear at a different world position from the corresponding incorrect block. Investigate the check result's cell coordinates, placement translation, rotation/mirroring, layer filters and overlay transform separately; do not assume the check data itself is wrong. Compare Check rows, world-space highlights and targeted blocks across transformed placements. Record a reproduction before choosing a fix. SCHEMATIC.md.

L-181 FreeCamera draws the held trident the wrong way round

Kind: Bug / Research, low priority (maintainer 2026-10-15: drawing only, harmless). User report 2026-10-14; not yet reproduced. Clarified 2026-10-14: nothing hits the player. In FreeCamera the trident in the player's hand is drawn the wrong way round, so it looks stuck in the player. A drawing problem like L-123 (stale pose state while the body is out of the camera's normal view); check whether the use/charge pose or the held-item transform is the stale part. Status: open drawing issue; the original "struck by the trident" report is superseded by the clarification above. Capture the held/use/charge pose, camera/body visibility and local/server sequence when resuming. In FreeCamera, player interaction suppression and restoration must remain intact. CAMERA.md.

L-123 FreeCamera stretches the worn elytra on the inventory player model

Kind: Bug, low priority. Reported from use 2026-10-09 (maintainer's notes). Parked 2026-10-10 (maintainer) after two culling rounds; resume from the next ideas below. Status: open. Checked 2026-10-10 (VALIDATION-LOG): wrong when the body is out of view (camera near), right when the body is in view (camera far), so the inventory model reuses pose state that only the world render of the body updates. Next: Research which state (elytra wing animation) is left stale and whether it can be refreshed for the inventory model alone. Two rounds 2026-10-10, both reverted: keeping the body "visible" to the camera's LevelRendererCamera::isAABBVisible (round 1: never matched on the render thread) and to both isAABBVisible and cullerIsVisible on any thread (round 2: 1751/249 calls, 10/22 near the body, the point test was overridden) left the elytra stretched. So these camera tests are not what skips the body's pose update. Stopped after two rounds. Next ideas (not started): find the entity render queue's own visibility step (LevelRendererCamera::queueRenderEntities and what it calls), or refresh the pose on the inventory model's side (the paper doll render path, GeometryAtlas::DollRenderContextImpl::update, PaperDollData). Reproduction (maintainer 2026-10-10): wear an elytra, turn FreeCamera on, move the camera away from the body, open the inventory. The elytra on the player's 3D model in the inventory screen draws simplified and stretched downward. The elytra slot icon is not affected. Whether pose, animation state, level of detail by camera distance or the render context left by FreeCamera causes it is unknown; a first check is whether the distance matters (camera near the body vs far).

L-117 Schematic entity name tags render badly in Japanese

Kind: Bug, low priority. Reported by the maintainer 2026-10-08 (L-93 checks). Status: partly fixed (47534d7, checked in game 2026-10-08): the colored fringes are gone. Not solved: Japanese text in these tags draws dark gray instead of white; a white dark color brought the fringes back. The maintainer accepts it for now but keeps the item open. World name tags appear only over entities drawn as dashed frames (no model, L-115); they are drawn in GhostRenderer.cpp drawNameTags (Japanese glyphs from sheet 48, type 3, scale 1.333, with the font's own material).


L-192 Glass ghost brightness changes by section with the camera position

Kind: Bug / Research. Maintainer report 2026-10-14 (VALIDATION-LOG). Status update 2026-10-14 (2): the real see-through part passed; darkening left where blended quads overlap; fixed by sorting all blended quads together from the current camera, not checked. Status update 2026-10-14: happens only where a real see-through block is below the ghost; fix built (real see-through faces hide the ghost face in their plane), not checked in game. Status: open. More evidence 2026-10-14: only the current camera position matters (not where the camera was), so the build-time sort hypothesis below does not fit; with the camera below the floor both sides darken. White stained glass ghosts turn darker or lighter in world-aligned groups that look like the 8-block ghost sections, depending on where the camera is, not which way it looks; moving the placement keeps the dark area at the same world coordinates. Hypothesis (not checked): blended ghosts draw both sides without depth writes, so a glass cell's top and bottom faces both blend and the one drawn last dominates. Each section sorts its quads far to near from the camera position when it was built, and sections rebuild at different times, so sections built with the camera on different sides of the faces end up in a different order. Candidate fixes: drop back faces of blended ghosts (as the game does for glass) and rebuild a section when the camera crosses its planes, or re-sort blended quads when the camera has moved. Check first whether walking below and back above the floor flips which sections are dark.

L-193 Glass ghosts of two adjacent placements flicker at their border

Kind: Bug. Split from L-178 on 2026-10-14. Status update 2026-10-14 (2): left where two placements' see-through quads overlap on screen; same global sort fix as L-192, not checked. Status update 2026-10-14: does not happen with one placement; the flicker needs real see-through blocks below too; same fix as L-192, not checked in game. Status: open. pistons (8x3x7 at -95 84 -60) and shulkers (5x5x5 at -87 84 -63) touch across x = -87; their white glass ghosts at y 84, z -60 and -59 face each other and flicker. Cause found from the log (VALIDATION-LOG): next to the camera the pairing rule keeps one face of a shared plane, and the two placements' sections, built with the camera on different sides, each kept theirs. Fix built 2026-10-14: same-kind see-through pairs drop both faces even next to the camera; the flicker remained (VALIDATION-LOG), also where no faces meet, alternating between two looks. A perf trace build checks whether sections keep being rebuilt.

L-194 Save corner marks over real glass or water change with the camera

Kind: Bug / Research, low priority. Maintainer report 2026-10-14/15; parked 2026-10-15 after three tries (VALIDATION-LOG). Status: open. A save corner mark (red or blue) in or against a real see-through block (glass, water) looks different from either side of a plane that lies on Chunk Borders lines: from one side the real water behind the mark is hidden, from the other it shows through. Not over air or opaque blocks; the same in Fancy and Simple graphics. Tried without effect: drawing such marks in the block entity alpha pass, in the name tag pass, and lifting the faces 0.02 out of the cell (also looked lifted over stone). Kept: only the seen sides are drawn, and corner 1 is pulled nearer than corner 2 (their shared edge lines no longer trade places). Next idea: find where the game draws translucent terrain relative to the camera's chunk, or draw the faces with a material that does not write depth.

Feature work and research

L-298 Attach release assets from the tag's CI run

Kind: Ready (implemented 2026-11-01; first run on v0.4.0 passed). Follow-up to L-196: release ZIPs up to 0.3.1 were built and attached by hand, and where they were built was not recorded, while THIRD_PARTY_NOTICES says a release is built from its tag. Decided with the maintainer 2026-11-01: CI builds and attaches, a person writes the notes and publishes. build.yml uploads bin/release/ as release-assets on a tag push; a separate draft-release job (the only job with contents: write, no build code) creates the draft "Lamium " with both assets, or replaces the assets of an existing draft, and refuses a published release. The flow is in DISTRIBUTION.md. Not done: build provenance attestation (optional; needs a pinned action and id-token/attestations write). Validation: the v0.4.0 run created the draft with both assets and matching SHA-256 (VALIDATION-LOG 2026-11-01). Left: LeviLauncher installs the published ZIP (BACKLOG "Since 0.4.0"); close this item after it passes.

L-249 Show the chunks within simulation distance

Kind: Design / Research. User request 2026-10-23 after 0.3.0: show which chunks are within the simulation distance (where mobs, crops and redstone tick). Chunk Borders (src/overlay/ChunkBorders.h) draws only the borders around the player; nothing shows the simulated area. Goal: let the player see which chunks are simulated, without implying more than the game guarantees. Open: where the simulation distance comes from (the world setting is known locally; on servers it may not reach the client) and whether the client can read it from game state; how to show it (Chunk Borders option, minimap overlay or world map layer); behavior on servers where it is unknown. Research the source first, then agree the presentation with the maintainer. No release target selected.

L-259 Book and quill: paste overflow into new pages

Kind: Ready (behavior and the switch decided; built, waiting for the in-game checks below). Maintainer request 2026-10-25: pasting into a book and quill page is refused outright when the result would exceed the page limit, which gets in the way of copying text into books. Goal: a paste that does not fit on the current page fills it and continues on new pages, staying within the vanilla per-page and 50-page limits so the edit is sent as ordinary page edits and any server accepts it. Raising the limits themselves is out of scope: whether a server keeps a page longer than the client allows is unknown, and a rejected edit would lose text.

What limits a page (from SDK headers and the vanilla ui/book_screen.json, not yet seen at runtime): the page text box uses max_length: "$max_page_length", a variable the JSON does not define, so it presumably comes from BookScreenController::addStaticScreenVars. The box's TextEditComponent also has mConstrainToRect and _textFitsInControl(text), which presumably make the visible-lines limit. Edits go to the server as BookEditPacket (replace/add/delete/swap/ finalize).

Decided (maintainer 2026-10-25, accepting the proposals):

  • Only a paste into a page of an editable book and quill. Typing at a full page, the title box and everything else stay vanilla. A paste that fits is left to vanilla.
  • The pasted text is inserted at the caret, replacing a selection. The current page keeps the text before the insertion point plus as much of the pasted text as fits. The rest, followed by the text that came after the caret, goes onto new pages inserted after the current page; existing later pages move back and are never overwritten.
  • If the result needs more pages than the 50-page limit leaves, nothing is pasted and a short message says how many pages it needs and how many are free. No partial paste.
  • Page break: within the part that fits, break after the last line break, else after the last space, unless that leaves the page less than half full; otherwise break at the last character that fits (never inside a UTF-8 sequence). The break's line break or space is dropped so a new page does not start blank. Japanese text without spaces breaks by character.
  • "Fits" is the game's own test: the page's length limit and _textFitsInControl, so wrapping and fonts need no copy in Lamium.
  • One switch, on by default; off is the vanilla refusal. Decided 2026-10-27: interface.bookPaste on feature bookPaste, Settings::Interface group, named "Book paste across pages" (「本への貼り付けをページまたぎ」), the switch labelled "Paste across pages: {}" (「ページまたぎの貼り付け: {}」).

Research before building (trace build, Windows):

  1. Which path a paste takes (TextEditContext::feedAction(Paste), feedText, TextEditComponent::handleTextCharEvent) and on which thread; where the caret and selection can be read (TextEditContext mCaret, mSelection).
  2. The page limit's unit: bytes or characters. Japanese is 3 bytes per character in UTF-8, so a byte limit fits about 85 characters.
  3. Whether BookScreenController::_setPageText/_addPageAt send the edit to the server or BookScreenManager::editPage/addPageAt must be called, and when: apply the overflow on the next BookScreenController::tick from owned strings, without keeping the controller pointer. Pure part with tests: splitting text into pages given a fits-predicate. New hooks go into GAME-UPDATES.md. Verify on a local world and on a server that the pages survive closing and reopening the book. Status 2026-10-27: built, not yet checked in game (branch l259-book-paste-trace). The trace build (eb42d2c9, --book_paste_trace=y, src/features/inventory/BookPaste.cpp plus a "Book paste diagnostics" entry in Runtime.cpp) answered the three research questions in a real game:
  • A paste is TextEditContext::feedAction(Paste) then one TextEditContext::feedText(clipboardText), which inserts what fits and silently drops the rest: 4,631 characters offered on a page holding 69 left exactly 256, with no message, and nothing on a page already at 256.
  • 256 counts characters, not bytes: a page held 602 bytes / 256 characters, and 519 bytes / 173 Japanese characters were accepted.
  • The page box is mMaxLength = 256 with mConstrainToRect = true; the title box takes 512 and does not constrain, so the page is identifiable by its limit. Edits reach the server as BookEditPacket(replace) after _setPageText -> _parsePageText/BookScreenManager::editPage, sent by both $send and $sendToServer, so _setPageText and _addPageAt are enough to write pages. Built in src/features/inventory/BookPaste.{h,cpp}: the split is pure (splitPaste, chooseBreak, byteOffset in the header, covered by tests/BookPasteTests.cpp) and TextEditContext::feedText is the interception point. It runs only when the switch is on, a book screen was seen this frame (BookScreenController::$preFrameTick), the book is mEditable, the view is Viewing, the context's limit is the page's 256 characters, and the page box was seen by its own focus or text calls; any other text field goes to the game untouched. Fits is the game's own test (_textFitsInControl plus the 256-character limit). A paste that needs more pages than the 50-page limit leaves is refused whole, with a toast saying how many pages it needs and how many are free; the HUD is not drawn over the book screen, so the message is repeated when the book closes. Crash 2026-10-27, first in-game run of the merged build 1d2c341a with the switch on: 0xC0000005 on mov dword ptr [0x0000000000000000], 0xDEADC0DE inside ContextText::detour+0x802 (BookPaste.cpp:266L), the line that called origin() after the paste had been written, with the game's own frames above it. The cause was that write: _setPageText and _addPageAt ran inside feedText, i.e. with the text edit's own call on the stack, and the page rebuild they trigger invalidates the TextEditContext being edited - the detour then returned into memory the screen had already freed, which is what the dump's poison value marks. The same window explains pastes that did nothing. Fixed in 80d6dfb8: feedText writes no page model at all. When the gate passes and the split yields pages, the detour calls the game's own origin(<the part of the paste that fits>) - plus context._setText(<first page>) when the caret had text after it, so that tail belongs to the last new page - and keeps the remaining page texts as owned strings in DeferredPages: the page index, the text that page must hold, the page text from before the paste, the paste's frame number and the screen identity (controller address plus a generation the $preFrameTick hook bumps whenever the controller changes, so a heap reuse at one address is not the old screen). The existing $preFrameTick hook applies them on the next frame, and only if the same screen is current and still mEditable, the page still holds what the paste left (or the text from before it, or a prefix of that while the model is one parse behind) and pages + kept <= 50; the kept pages go in with _addPageAt(index + k, PageContent(text)) ascending, so later pages move back and are never overwritten, wrapped so a throw drops the plan. Any other verdict drops the plan with a reason, and the screen going away clears it. The refusal toast is queued the same way and shown from the book's own frame, never from inside the paste, and again when the book closes. Page-text gate relaxed in the same commit: a stored page that is a prefix of the live text is a page whose typing has not reached the model yet, so it passes and the caret counts the live text; unrelated text still goes to the game untouched. The old rule rejected any difference, which is why a paste right after typing did nothing. The pure part now carries the gate and the deferred plan (pageTextGate, ScreenId, DeferredPages, pageUnchanged, planApply, applySkipReason, planDue), with table tests in tests/BookPasteTests.cpp for pending typing, unrelated text, the same screen, a reused address, a moved page, the 50-page room and the next-frame rule; each rule was mutated once and its test failed. Trace lines for the retry (--book_paste_trace=y, DLL SHA-256 7775e0b839d7fa979795419384aeed698f76235c3f2538768a68c5fd27821170): paste gate=<reason> names the verdict (ok, pending-typing, text-unrelated, option, limit, box, not-editable, view, page-index, photo, caret, empty, split), paste defer index= frame= extra= head trim= what was kept, and paste apply index= added= pages=-> or paste apply skipped=<reason> (screen, not-editable, page, page-moved, no-room, empty) the deferred write. In-game checks still to do: a book that already has later pages, a paste that replaces a selection, a paste into a nearly full page, Japanese text, a paste at a mid-page caret, typing one character and pasting immediately, and a server (the pages must survive closing and reopening the book). Review fixes 2026-10-28 (after the in-game rounds, not yet seen in game): the pasted page is searched only among the preferred page and its two neighbours (an exact match before pending typing, longer before shorter, the preferred page on a tie; two equal neighbours give gate=page-ambiguous and the game keeps the paste), because a book-wide search let any empty page match an empty or freshly typed box and the overflow went in after that page. A second paste while kept pages wait for the next frame pastes nothing (gate=busy) instead of replacing them, and a CRLF whose CR is the first character past a page drops its LF so the next page does not open with a blank line. Fix 2026-10-28 (not yet seen in game): the maintainer saw text missing between the pasted page and the next one. The trace of a 7,687-character paste showed the book holding planned pages 0, 2, 3, ... and an empty page after the last: _addPageAt(i) inserts before page i, so the new pages went in front of the pasted page (whose model still held the old empty text), and the box then wrote the pasted page's text over the first new page. New pages now go in from index + 1. Settings change 2026-10-28 (maintainer): a single switch nested under a heading made no sense and could not take a key. Book paste is now a plain feature row whose state column is interface.bookPaste (like Skip server resource packs), with the unbound toggle action bookpaste (ToggleBookPaste); the details that were the nested row's help moved into the feature's help. Status 2026-11-01: every commit of branch l259-book-paste-trace is on main (PR #55, 2026-10-28), and main has the later page-index fix (fa6cc2f4) and the plain switch (1c845919), both checked in game (VALIDATION.md). Unchecked: servers, Japanese text, the right page of a spread, a replaced selection and the 50-page refusal. No release target selected.

L-263 Pick the aimed ghost block from the inventory

Kind: Research (pick-block hook), then Ready. Same feedback as L-262: take the block of the schematic ghost under the crosshair from the inventory. Decided (maintainer 2026-10-26): build this first, with the "bring this block from the inventory into the hand" step as a shared part that a later placement assist (L-265) can reuse. The vanilla pick-block input (middle click by default) does it when the crosshair is on a ghost and not on a real block; on a real block it stays vanilla. Like vanilla pick block: select the hotbar slot that holds it, else bring it from the inventory into the hotbar; nothing happens when it is not carried. Open: creative mode (vanilla gives the item; whether a ghost pick should too), and a ghost behind a wrong real block (vanilla wins as decided). Decided 2026-10-26 (maintainer): in creative mode a ghost pick gives the block even when it is not carried, like vanilla. Research (2026-10-26, SDK 26.51.8): vanilla's creative pick asks the server for the block at the hit (BlockPickRequestPacket), which cannot name a ghost; the creative inventory screen takes items with an item stack request whose action is CraftCreative (ItemStackRequestActionType 14, a CreativeItemNetId from CreativeItemRegistry) followed by a move into a slot. Lamium's moves use legacy transactions (game::movePair) and never build item stack requests. Next: a trace build that logs the request the creative screen sends when a block is taken into the hotbar, then the same request built by Lamium, confirmed from the slot's authoritative contents; gated, with a GAME-UPDATES entry. Correction the same day: building an item stack request is not possible with the SDK (ItemStackNetManagerClient::_beginRequest, addRequestAction, trySendBatch are all MCNAPI, as L-66 found). Experiment built instead (xmake f --schematic_creative_pick=y, off by default, not in release builds): in creative mode, a ghost pick of a block that is not carried puts it into the hotbar (creativeSlotFor: the selected slot when empty, else the first empty one, else the selected one replaced) through the same legacy transaction as movePair, balanced by creative-inventory actions (slot 1 gives the item, slot 0 takes back the replaced one). The log line "creative pick: slot N sent X, now holds Y", written at the next pick, shows whether the server kept it. To check: a local world and a server, an empty and a full hotbar, then whether the item stays after reopening the inventory or the world. Checked 2026-10-26 on b2bde4f (VALIDATION-LOG "L-263 creative pick experiment"): accepted in a local world (empty and full hotbar, kept after reopening); refused for water, lava and a structure block, and twice for a give into an empty hotbar slot that was not yet selected. Changed next (not yet checked): only items the creative inventory lists are given (CreativeItemRegistry, as sorting uses), and the slot is selected before the transaction is sent; the log adds the slot selected before and the time to the check. Servers not tried yet. Checked 2026-10-26 on 7d41160 (VALIDATION-LOG "L-263 creative pick, second check"): every give went through at once, unlisted items were not sent; the log now says "skipped" for those. Made a normal part of the pick the same day (maintainer: in-game checks go to the 0.3.1 pre-release round): the build option and the log lines are gone; the give is gated by the direct capability "Schematic pick (creative inventory give)" (GAME-UPDATES.md), off on an unverified game build. Left: the pre-release check of this build and a server. Status 2026-10-27 (review of this implementation, L-273 to L-275): the owned-item path compares the data value as the creative path does, so a skull or monster egg variant is no longer picked or swapped for another one; the pick is read back from the slot on a later frame, and one the server did not make logs pick not confirmed; and a ghost without an item (fire, water) no longer falls through to vanilla's pick of the real block behind it. Built, not yet checked in game. Research: where pick block is handled in the SDK and how the inventory move is confirmed from authoritative state (reuse the existing inventory transfer paths). New hooks go into GAME-UPDATES.md. No release target selected. Release target: 0.3.1, batch L-266.

L-265 Schematic placement assist: place the ghost's block in its state

Kind: Design / Research (strong model). Maintainer note 2026-10-26 while deciding L-263: a mode in which using a block on a ghost cell places the schematic's block there with the schematic's facing and states. Open: whether to do it at all; which states can be produced by the player's own placement (facing from look direction, half, slab type) and which would need a faked look or a server-visible trick; what servers and anti-cheat accept; how it relates to the vanilla place input and to L-263 (it reuses L-263's "bring the block into the hand" step); refusal when the block is not carried. Do not change gameplay packets beyond what the player could do by hand without a separate decision. No release target selected.

L-233 Make inventory transfer gestures rebindable

Kind: Design, future. Maintainer 2026-10-20: now that a wheel direction can be part of a binding, the transfer gestures should be configurable instead of fixed to Shift/Ctrl/Alt plus wheel, drag or click. Not urgent; nothing is blocked today. Current model: TransferGesture.h derives 14 gestures (one/stack/matching/ all on the wheel, stack/one/keep-one/drop drags, matching/all clicks, cursor matching) from hardcoded modifiers; the settings only enable or disable each gesture. Open: which gestures to expose and which model to use. Wheel gestures fit the existing Press-plus-wheel chords. Drags are press-move-release and clicks carry cursor state, so plain chords cannot express them without a gesture model. Also decide modifier roles, defaults matching today, the container- only context, conflicts with other actions, and whether to start with the wheel subset only. L-169 owns transfer extensions; do not start without choosing the subset and model.

L-236 Rebuild only the ghost sections whose visible layer changed

Kind: Design, low priority. Performance follow-up split from L-234 (2026-10-21). Maintainer check 2026-10-22 on a desert village: stepping the cut under Only is fine; under Up to the redraw after each step takes a noticeable while. Not urgent: drawing a large schematic whole is heavy anyway, so day-to-day work likely uses Only. A cheaper first step if it returns: keep the old sections drawn until their replacements are built. The ghost cache key is per placement, so moving the cut discards and rebuilds every 8-block section (and re-resolves the palette), including sections whose shown cells did not change. Give each section a layer visibility signature (fully shown, fully hidden, or the cut boundary inside it) and reuse unchanged sections when the cut moves; changing an unused field (Keep under Only, Axis/Cut under All) already avoids a rebuild because the key only covers visible fields. Needs a pure section-state helper and tests, renderer cache changes, and an in-game frame check on a large placement while stepping the cut. Not part of the current L-234 branch.

L-190 Select several rows at once in list screens

Kind: Design. Maintainer idea 2026-10-14; no implementation or release chosen. Goal: in list screens (waypoints, the schematic Check list and similar lists) select several rows with Ctrl/Shift + click or by dragging, and act on them together (for example hide, delete or show in world). Open: which lists and which bulk actions; how Ctrl (toggle one) and Shift (range) combine with the current single selection and the detail pane; drag selection versus dragging to scroll or reorder; confirmation for destructive bulk actions; keyboard equivalents.

L-183 Temporarily disregard selected schematic check mismatches

Kind: Design, then Ready/Research depending on the chosen check state. User feedback clarified 2026-10-14; not chosen for implementation or a release. Goal: while building redstone and other stateful structures, temporarily exclude selected expected-vs-actual discrepancies from the check results. A block with a temporarily different powered/open/extended state can be intentional during construction; the schematic file and physical blocks do not change. This is check-result suppression, not hiding the ghost or automatically relaxing every BlockState comparison. Open: scope (one world cell, selected group, or a state key), persistence (until manual reset, reload, or session end), whether ignored rows contribute to completion totals/HUD/nearest-mistake, and how to unignore/review them. Keep the original strict comparison available. SCHEMATIC.md.

L-184 Inspect ghost block data and schematic container contents

Kind: Design / Research for saved data inspection. The target-card part has local checks: ghost/real targets on b5daa75, followed by the ray and ghost-edge fixes L-217/L-222/L-224 (last 30b66ce, 2026-10-19). Saved container/Block Entity inspection remains open. The sequence below is the earlier 2026-10-15 target-card checkpoint, not a new implementation. Target-card history 2026-10-15: the ghost-as-target card with a "Ghost of " row was built first, then replaced by an upper/lower section (334889a, 0b89cd2) and a None / Stacked / Side by side choice (771ba02). The maintainer then found those sections hard to read and decided: keep the ordinary single-card layout and polish its details; keep the Target Info setting (now an on/off "Show schematic information") and the ghost target. Built: ghost name in light blue with "Schematic: Not placed yet" (no placement name), difference rows first under the header, the cell compared live, the setting saved with compatibility for the test builds' numbers (DESIGN "Target and Schematics"). Awaiting in-game checks: ghost in the air and in front of a real block, wrong/extra/state rows, the setting off, short screens. Container inspection and saved Block Entity data remain Design / Research. Built 2026-11-03: the ghost's saved block entity data shows as target-card rows under the same rules a real block's rows use (L-300/L-301) - sign text, colour, glow and waxed state, a jukebox record, a lectern book and page, a potted plant, a note block's note and instrument - so a ghost and the block it becomes read alike. Decided 2026-11-03 (maintainer): a ghost's card follows the same rules as the real block's, from the file alone. This is the base for the file-only data and the comparison still to come, so a difference between a ghost and its block must come from the data, never from the presentation. The world never fills a gap: a value the file does not decide reads "Not set by the schematic" rather than the world's, which would pass for the file's. A note block's instrument comes from the file's blocks below and above it (each block declares one instrument for a note block under it and one for a note block on it, checked in game); outside the file or at a void cell it is not set. Passed in game on a193244e, and on the merged build 951fb651 (PR #68). Reviewed 2026-11-03: a block type that stores an engaged none where others store nothing would have counted as a decision and swallowed the instrument row, so the neighbour read normalises it (declaresNoInstrument). Three things to keep in mind, not defects: a note block on the file's top or bottom layer always reads "Not set by the schematic", correct but likely in a small schematic, so the wording may want to name that reason; fileCellAt guards only structure, not visibility, dimension or layers as blockEntityAt does through drawsCell, which is safe while ghostAlong is its only caller; and GhostAt::blockEntity points into the structure the same struct owns, a lifetime the type does not enforce. The row comes from the placement's block_entities entry for that cell (PlacementOverlap.h blockEntityAt, turned and mirrored like the cells), so it is complete even though the world's copy of a block entity is not. Still open, and now the whole of what is left: the data only the file has (container contents, a comparator's signal) and how to present it. Goal: inspect the ghost under the crosshair: expected block name, facing, BlockState and available saved Block Entity data. Provide a way to understand inventory contents of barrels/hoppers and other data relevant to redstone output (for example comparator signal), without assuming an on-world text overlay is the right presentation for all of it. Open: compact target-card details versus an expanded inspection view; how to display inventory slots, NBT fields and signal values; what is derivable from the saved file versus current world state; absent or unsupported data and transform-aware directions. Do not promise data that the client/schematic never stored. SCHEMATIC.md.

L-185 Instantly load a schematic into the world when cheats allow it

Kind: Design, then Research (strong model). User feedback 2026-10-14; not approved for implementation or release. Goal: explicitly materialize an entire chosen placed schematic in the world, analogous to the game's structure-block Load action, rather than manually building ghost cells. Open: exact permission/capability checks for local and server worlds, world/block replacement policy, entities, block entities and inventory data, size/loaded-chunk limits, placement transformations and failure/undo UX. Never silently modify the world, use a client-side visual as proof of server acceptance or bypass permission checks. SCHEMATIC.md.

L-186 Improve schematic ghost legibility and reconsider translucency

Kind: Design / Research (strong model). User feedback 2026-10-14; no renderer or release choice yet. Part built 2026-10-15 (maintainer: choice (c) plus an outline width): a "Ghost tint" setting (strong = the earlier look, weak = default, none) and a "Ghost outlines" width (thin = one pixel, default; normal and thick draw each axis-aligned edge again at four offsets across it). Not checked in game. Later the same day normal/thick became solid bars (7d79bef, passed). Bars of neighbors with different check results flickered; they now sit on the shared edge and a stronger result's bar is slightly wider: wrong block > unknown block > wrong state > ghost/missing. Wrong beside missing passed; wrong-state stairs over a missing block still fought, so within a section only the strongest copy of a shared edge is drawn and the width step grew to 0.002 (passed, ee196c6). Ghost tint (maintainer, 2026-10-15): the three choices changed the look too sharply, so it is now a 0-100% slider in 5% steps; 100% is the former strong, 40% about the former weak, 0% none. Saved as ghostTintPercent; the former ghostTint choice maps to 100/40/0. Passed in game (ee196c6). The maintainer then chose 70% tint and Normal outlines as the defaults: a little rugged, but the block and whether it is a ghost read best there. Translucent ghosts stay open (maintainer: after the release). Goal: distinguish ghost blocks from real blocks while keeping their native colors readable. In the reported screenshot a pink concrete ghost overlapped a light-blue overlay enough that the pink color, and even whether it was a ghost, became unclear. Investigate the current light-blue outline/tint, line density, face shading, overlap/occlusion and depth behavior first; compare with translucent ghosts (previously not selected) as an optional alternative rather than presuming translucency is better. Evaluate dense redstone builds, ghost-on-ghost overlap, real/ghost boundaries, opaque/cut-out/blended/water blocks and ordinary/Vibrant Visuals graphics. Consider mode/opacity controls only after comparison; avoid changing the existing default without the maintainer's decision. Related but distinct: L-114's Check-tab 3D preview mistake styling. SCHEMATIC.md.

L-173 Quick shapes: a beacon's range at a glance, shapes that are not saved

Kind: Design. From the maintainer's notes (2026-10-13); not chosen for building, no release. Goal: see a beacon's range without making a shape (kind, center, radius, saving). Proposal (not decided): looking at a beacon, one action shows its range as an overlay; the pyramid's levels set the size where they can be read, else the shown size is marked as assumed. Shapes gain temporary ("quick") shapes that are drawn but not saved, and can be kept as named shapes when wanted; the same works for distances, radii and building guides. Open: the range's vertical extent and edges as Bedrock behaves (check in game), how long a quick shape lives (until cleared, rejoin, dimension change), and where the action lives (key, radial menu). The Shapes editing and saving flow stays as it is.

L-170 Enchantment order planner

Kind: Design, then Research (strong model). Requested by the maintainer 2026-10-12; not chosen for building, no release. Goal: given an item and the enchantments wanted, show the order of anvil combinations that costs the least experience and avoids steps the anvil refuses as too expensive. Agent's proposal (not decided):

  • Data from the game, so new enchantments need no Lamium update: the registry Enchant::mEnchants() gives each enchantment's id, max level (getMaxLevel), rarity (Frequency, which sets the anvil multiplier), compatibility (isCompatibleWith) and whether it can go on the item.
  • Anvil rules (prior-work penalty doubling per use, per-level multipliers, books against items, the refusal threshold) as a pure, tested table. Bedrock's rules are not assumed to equal another edition's: check every rule against the cost the anvil screen shows (AnvilScreenController) before trusting the planner.
  • Solver: a pure, bounded search over combination trees (exhaustive up to about 10 inputs, which covers every real item), minimizing total levels with no step at or above the refusal threshold; ties prefer fewer steps.
  • UI: a Lamium screen; pick the item (held item preselected), tick the enchantments and levels (incompatible ones greyed), optionally "use the books I carry" (read from the inventory, with their existing prior-work penalty). The result is a numbered list of steps with each step's cost and the total.
  • Later, if wanted: highlight the next pair in the anvil screen. Decided (maintainer 2026-10-12): the first version plans from fresh books only (no prior-work penalty on the inputs); planning from the books in the inventory can come later. Decided (maintainer 2026-10-12): an unbound hotkey (and the settings screen) opens it with the held item preselected; anything inside the anvil screen comes later. Open (maintainer): whether the anvil highlight is wanted later.

L-169 Item Transfer: remaining gesture and screen extensions

Kind: Design. Current status reconciled 2026-10-20: matching/everything, keep-one and native slot-role routing shipped in 0.2.2; held-stack matching and the four drop gestures shipped in 0.2.3. The former passed locally and on BDS on 37c3745; the latter passed the local chest checklist on 9da5d9d (2026-10-15). All five held-stack/drop switches default on, as chosen by the maintainer. L-154 is merged here and archived. Current behavior and authoritative confirmation rules: DESIGN.md "Inventory transfer" and ITEM-TRANSFER.md. Completion and the superseded proposal/handoff are retained in BACKLOG-DONE.md (L-169's 0.2.2 and 0.2.3 records). Do not implement the old proposal again.

Unchosen extensions, with no implementation or release approved:

  • Extra Shift + double-click (matching) or Ctrl + Shift + click (leave one) bindings; decide whether they add value beside the shipped gestures.
  • "Fill existing stacks only" and W/S-directed moves; the latter were explicitly deferred, not selected.
  • Additional screen families: reproduce a specific unsupported operation and confirm its native slot roles before extending coverage. The full gesture/screen matrix, drop-key rebinding, controlled rejection or timeout, lifecycle interruption, unverified-game fallback, packs and wider server checks are validation gaps, not unfinished gesture implementation; see Pre-release checks and VALIDATION.md.

L-168 Trade finder: reroll a villager until a wanted trade appears

Kind: Design, then Research (strong model). Requested by the maintainer 2026-10-12 for later; separate from L-166 (trading once a good villager is found). Not chosen for building, no release. Goal: find a wanted trade (for example a librarian's enchanted book at a given level and price) by resetting a villager's profession again and again, for every profession, inside Lamium's UI. Background: a villager that has never been traded with loses its profession when its workstation is broken and rolls new trades when it takes one again. On Bedrock the client receives every trade of every level when the trade screen opens (L-129 research), so even level-5 offers can be checked at level 1. Research first: when trades are rolled on 26.51 (on taking the profession or on the first opening), how long the villager takes to claim a placed workstation, and whether a server sends the same. Agent's proposal (not decided), in two stages:

  1. Assist (no automation): a list of wanted offers (item, enchantment and level for books, maximum price). Each time a trade screen opens, Lamium checks the received offers (L-129's parsing) and announces a match with a toast and sound; otherwise it says what was offered. The player breaks and places the workstation by hand.
  2. Loop (only if wanted): with the player looking at a villager and its workstation, Lamium repeats break, place, open the trade screen, read, close, until a match or a stop. Every step goes through vanilla's own actions (break and build), waits for authoritative results, and stops on any player input, a missing workstation item, a different villager, a traded (locked) villager, low durability (L-62), or world/dimension change. Default off; help text warns that servers may treat the loop as automation. Decided (maintainer 2026-10-12): stage 2, the loop, is wanted. The list of wanted offers is kept per world or server (keyed like the map's per-world data), not shared. Open (maintainer): how wanted offers are entered (agent: a picker from the game's item and enchantment lists), and whether matches are kept as a short log.

L-167 Change the language and resource packs from inside a world

Kind: Research, then Design (strong model) for the remaining pack work. Current status, 2026-10-20: Game language and Skip server resource packs shipped in 0.2.1; language was checked locally and server-pack skipping with a cosmetic BDS pack. Broader coverage is in VALIDATION.md. General stack editing and applying the player's global packs while skipping server packs remain unchosen Research/Design. The dated research below is history. Imported from the maintainer's notes (2026-09-25) on 2026-10-12. Goal: switch the game's display language, and look at or change the global resource pack stack, without leaving the world or server first. Research first, before any spec: what 26.51 already allows from the pause menu's settings (language list, Global Resources) and where it stops. Do not build what vanilla already does. Agent's proposal (not decided), in two parts that are judged separately:

  1. Language (smaller): if vanilla refuses in-world, offer the same language list from Lamium (a settings row or the pause menu) and apply it through the game's own path (GeneralSettingsScreenController::_chooseLanguage, MinecraftGame::onLanguageChanged, ResourcePackManager::onLanguageChanged, FontRepository::onLanguageChanged), never by writing option memory. Lamium's own UI follows the new language on the next frame. Check that item names, signs, chat and open screens refresh, and that L-130 English search still works.
  2. Resource packs (larger): first a read-only view of the active global stack in-world. Changing it is not hot reloaded: queue the change, leave the world through vanilla's exit, apply the stack (ResourcePackManager::setStack, the same path as the Global Resources screen), then rejoin the same local world. Rejoining a server is only offered if the game keeps its address without Lamium storing it. World and server packs are never changed or skipped. Decided (maintainer 2026-10-12): the language part first; resource packs wait until it is done and seen. Decided (maintainer 2026-10-13): General settings has a "Game language" entry opening the game's language list. The maintainer confirms the vanilla pause settings have no Language entry on 1.26.51.01. This establishes the missing entry, not the safety of applying a language during play. Current research: language_trace observes vanilla selection, the saved option, I18n, game/font/pack observers and pack stack changes without changing any return value or argument. The title-screen baseline is recorded. Language part done 2026-10-13 (9651b4e, seen in a local world, kept after restart): General settings > Game language. Not separately seen: English Search after a change, schematic ghosts, BDS. All 29 game languages listed since cedccf6 (seen). Resource packs, vanilla baseline (2026-10-13, VALIDATION-LOG): in-world Settings > Global Resources lists the active packs but offers no control to change them, and no stack change happens in the world. Vanilla's in-world JSON settings also drops the Language tab with a static not $is_pregame condition; the controller still holds the language list. Server packs (2026-10-14): accepting a required pack and not applying it locally works on BDS for a cosmetic test pack (research build only); in-world Global Resources then shows a gray page. Hang: 12 in-world switches in 23 s froze the game; the title screen does not (VALIDATION-LOG). Decided (maintainer 2026-10-14): the language entry stays in Lamium's General settings, drawn inside the settings frame; in-world switching stays with one change per 10 s and a notice (experimental). Server packs: one Lamium switch "do not apply server resource packs" for remote servers, taking effect on the next join, with a notice when packs were left out (the usual Lamium message toast, or a chat line only the player sees; the toast is the agent's default). Per-server and per-pack choice are not wanted now. The look is vanilla: on a required-pack server vanilla also drops the player's global packs and shows a gray Global Resources page (confirmed on unmodded Minecraft). Built 2026-10-14, not yet seen in game. Later (maintainer 2026-10-14): show the player's own global packs instead of vanilla while skipping a server's packs; needs research on reapplying the Global stack during a server session. Contract, findings and next checks: LANGUAGE.md. Added research request (maintainer 2026-10-13): whether a server-required resource pack can be disabled locally without general pack-stack editing. Separate receiving/accepting packs from applying their visual resources. This request approved feasibility research only; the switch above was decided after the research (2026-10-14). The download/acceptance handshake is never changed or skipped; only local application is. Fail open: if the game's own apply path cannot be found, show nothing.

L-166 Villager trade helpers: favourites and assisted trading

Kind: Design, then Research for optional part 2. Requested by the maintainer 2026-10-14; no implementation or release approved for part 2. Part 1 (Shift + right-click repeated trading) shipped in 0.2.1. Keep that gesture and ordinary left/plain right click. Part 1 record: BACKLOG-DONE; runtime contract: TRADE-HELPERS.md; tests: VALIDATION.md. Sources of the idea: PROVENANCE.md (reference only).

Goal: make a familiar villager's useful trades one action rather than manually finding and repeating rows every visit. Prefer small extensions to the vanilla trade screen, not a replacement screen or more one-off feature toggles. Automation stays on the current trade screen: Lamium never scans for, walks to or opens other villagers. Remaining uses and bounded trade counts are presentation candidates; keep the vanilla-looking UI and existing behaviours.

Proposed part 2, in incremental stages (not yet decided):

  1. Favourite offers. Toggle a star/marker on a trade row, possibly via middle-click (Shift + middle-click for shared favourites). Verify the input mappings, other mods and vanilla pick-block behaviour before choosing gestures. Avoid reordering vanilla rows at first. Investigate scope: per-villager favourites plus profession-wide defaults, with individual favourites taking precedence where set; consider whether an additional all-professions global scope is useful. Persist per world/server, as with other world-specific Lamium settings. Research a stable villager identity across sessions/servers; do not persist by a transient actor runtime ID. Match offers by verified contents (including enchantments and trade tier), not an unchecked row index; account for duplicate offers and dynamic prices.
  2. Trade all favourites on demand. A separate unbound action/key processes the current villager's matched, unlocked favourites in a deterministic order, as far as stock, materials and output space permit. Reuse part 1's vanilla trade path and per-request authoritative confirmation. Never fall back to an unfavourited row if none can be traded. Leave the existing Shift + right-click one-row action unchanged.
  3. Optional automatic run and close. Option (default OFF): when the player opens a trade screen, identify favourites and run the same queue without another click. Separate option (default OFF): close the screen after a successful, normally completed favourite run. Proposed guard: at least one confirmed trade, no further actionable favourites, and no pending requests. No favourites, manual interruption, inventory full, mismatched offers, timeout or other abnormal stop leaves the screen open. Never open a different villager or drop items to continue.
  4. Faster request batching (Research, optional). The L-166 trace in TRADE-HELPERS.md confirmed vanilla result-slot Shift + click can submit multiple crafts in one request, limited by ingredients already in the trade input slots; it does not refill from inventory. Explore a verified refill -> vanilla multi-craft -> acknowledge -> revalidate cycle rather than one craft per round. Benchmark against the shipped implementation on local worlds and BDS before adopting. Do not synthesize custom trade packets or send more work while a response is pending.
  5. Optional display. Consider remaining available uses, actionable trade count and minimal in-progress feedback; keep favourites readable without obscuring locked offers and their tooltips (L-129). Exact trade count limits and price caps are candidates, not committed features.

Safety and validation gates:

  • Reconfirm the chosen villager, offer, costs, lock/stock state, inventory capacity and request result at every step. Stop on failed/untracked/stale responses, price or recipe changes, insufficient space, screen/focus/world/ dimension change, settings-off or player input. Never drop/overflow output.
  • Check local and BDS: two-input enchanted books, restocks/level changes, discounted/demand-adjusted prices, identical-looking offers, sold-out rows, no materials, full inventory, interrupted close, network delay/loss and server rejoin. If a stable persistent identity or reliable vanilla input hook is unavailable, fall back to an explicit/smaller manual mode.
  • Keep L-168 Trade finder separate: L-168 finds a wanted offer by rerolling a villager's profession; L-166 performs trades once the offer exists. Share offer matching if practical, not automation of workstation placement or profession changes.

Open for the maintainer: favourite scope and identity, gestures, queue order, automatic-run/close UX and success criterion, whether use counts and caps are worth the UI, and whether batch optimisation justifies its compatibility surface. Treat every item above as a design candidate, not permission to build it.

L-165 Mass Craft: craft a recipe many times at once

Kind: Design, then Research (strong model). In the notes since 2026-09-22; imported on 2026-10-12. Not chosen for building, no release. It still needs the conversation about purpose and scope that a larger feature starts with (see the top of this file). Goal: turn a whole inventory of ingredients into products with one action (logs into planks, iron into blocks), instead of repeating fill-the-grid and take-the-output by hand. Vanilla baseline to measure first: what one recipe-book click and one shift-take of the output already do on 26.51 (how many crafts per action, where the output goes, what happens when it does not fit). Craft requests already carry a craft count (ItemStackRequestActionCraftBase::mNumCrafts), so vanilla may already do more per action than it looks. Agent's proposal (not decided):

  • A "Craft all" action on a recipe in the recipe book repeats vanilla's own steps (CraftingScreenController::_handleRecipeSelect, then _handleCraftItem(ItemCraftType::All)) until the ingredients run out, the output would not fit or the player stops it. Lamium never builds crafting transactions; the server validates every round.
  • One round at a time: the next starts only after the inventory changed as expected (ingredients down, output up) on authoritative state; a mismatch or timeout stops with a toast. A per-tick bound keeps the rate modest.
  • Stops on: screen closed, any click or key by the player, focus loss, world or dimension change.
  • Never drops items: check room for the output before each round.
  • Screens: the 2x2 inventory grid and the crafting table first. Stonecutter, loom, smithing and furnaces are later or out.
  • A small progress toast ("Crafting 320/640"), and the total at the end. Watch out for: recipes with leftovers (buckets, bottles), recipes that accept several ingredient kinds (any log), the OreUI recipe book versus the JSON UI screen (L-130 found only the latter covered), servers that limit request rates (help-text warning like Auto Attack's). Decided (maintainer 2026-10-12): Ctrl + click on a recipe crafts all (no count in the first version), default off: Ctrl + click lies close to Shift + click and an accidental mass craft would hurt. Crafting from nearby chests is out. Open (maintainer): whether a "craft the last recipe again" key is wanted (agent: not in the first version).

L-163 A Lamium-drawn inventory screen

Kind: Research, then Design (strong model). Raised by the maintainer 2026-10-12 after L-149 (opening the vanilla inventory in a portal is refused by the server) and L-132 (moving with the vanilla inventory open failed). Not started; recorded for later. Idea: draw an inventory-like screen in Lamium and move items through the same client inventory path Lamium already uses without a screen (inventory::game moves; Auto Elytra and Hand Restock). Evidence: Auto Elytra swapped items while the player stood in a portal (local world), and Hand Restock works on BDS. Such a screen could open in portals and let the player move (a different input routing than the vanilla screen). Costs and risks: slot rendering (Inventory HUD parts exist), click, right click split, shift click, drag spreading, number keys, armor and offhand slots, tooltips; 2x2 crafting is much harder and should stay out at first; loss or duplication if a move is not confirmed from authoritative state (DESIGN engineering rules); servers with their own anti-cheat may refuse; version sensitivity. Suggested order: (1) a spike moving one item from a Lamium screen in a portal and while walking, locally and on BDS; (2) if it holds, a minimal screen (main inventory, hotbar, armor, offhand; click and shift click; no crafting); (3) a mockup agreed before the real build.

L-132 Move while the inventory screen is open

Kind: Research, then Feature. Requested by the maintainer 2026-10-10; direction agreed the same day. Status: open; paused 2026-10-10 after eight trial rounds without smooth movement (findings below). While the player's own inventory screen is open, keep walking, jumping and sprinting from the bound movement keys so items and armor can be arranged on the move. The camera cannot turn (the mouse belongs to the screen).

  • Only the player inventory screen at first; containers (chests etc.) and other block screens come later, if at all.
  • Sneak is not passed through: Shift is shift-click (quick move) in the inventory.
  • Paused while a text field has focus (creative search, recipe book search) and on focus loss.
  • Default off; the help text warns that some servers may treat moving with an open inventory as cheating (like Auto Attack's warning).
  • Research first: where the game stops reading movement input while a screen is open (ClientInputHandler, ClientMoveInputHandler, ClientInputMappingFactory::_createScreen*Mapping, MoveInputComponent) and the least invasive place to feed the movement keys back in, without touching game state from the window procedure (AGENTS.md rule 2).
  • Trial record (2026-10-10, xmake f --inventorymove_trace=y, src/features/interaction/InventoryMoveTrace.cpp, single player on 1.26.51.01; commits 7e56cc8..40de3e3, last DLL 9edd5c65...):
    • ClientInputUpdateSystem::extractRawHIDInput keeps running (~20/s) with inventory_screen open; vanilla's bindings read from getOptions().getCurrentKeyboardRemapping() (key.forward = 87, ..., key.sprint = 17). Bedrock's move x is positive to the left.
    • Raw flags written after extraction are gone again by PlayerMovement::calculateMoveVector (two calls per tick: the RawMoveInputComponent state and a second state, likely the local server's). No movement.
    • Writing the flags into MoveInputComponent's states after inputHandlerUpdatePlayerState (and forcing the vector) reaches calculateMoveVector, yet MoveInputComponent::mMove and the built PlayerAuthInputPacket stay zero: the player moved only through server corrections (~2/s), in jerks; no jump. The injected state flags also persisted after closing the screen (kept walking). Patching the auth packet's move vector and input flags did not smooth it.
    • Not the cause: MoveInputComponent::Flag::MoveInputStateLocked and the client input locks are clear; UIScene::absorbsInput forced false for the inventory changes nothing; copying the gameplay key bindings (button.up/down/left/right/jump/sprint from gamePlayNormal) into the screen* input mappings changes nothing.
    • Next guesses: find where mMove is zeroed while a non-play screen is on top (inside ClientInputUpdateSystemInternal::tickUpdateClientInputView, perhaps via VanillaClientGameplayComponent or a play-screen check); or whether the input handler only routes movement button events to ClientMoveInputHandler while the gameplay mapping is the active one (ClientInputMappingFactory::_activateMapping).

L-59 Held placement style: vanilla, Java-like or fast

Kind: Design done (discussion with the maintainer, 2026-09-28); Research first, then Ready (strong model). Started as "keep placing across a left click" after L-49 closed as vanilla parity. Status: planning. Nothing is built, and no step starts until the maintainer says so. What it is for: building bridges and long straight lines quickly by holding the use button with a block. Block placement only; eating, bows and buckets keep vanilla behavior.

Spec (decided 2026-09-28)

  • One setting, "Held placement", under Actions: Vanilla (default), Java-like, Fast. Default Vanilla because players expecting Bedrock would be surprised.
  • Vanilla: Bedrock's own held build session, unchanged.
  • Java-like: while the use button is held with a block, place on whatever face the crosshair targets at Java's fixed interval (every 4 ticks): no direction lock and no placing into air; nothing is placed when the crosshair is not on a face. An intervening left click does not end it (the original L-59 request): placing resumes while right is still held.
  • Fast: while right is held, place on each new block face the crosshair crosses, capped per tick (a setting with a modest default). The help text warns that some servers may treat it as unfair. Also survives a left click.
  • Both non-vanilla styles respect the placement restriction (L-15) when it is on, which turns Fast into "paint a flat floor".
  • Interactive blocks (chests, doors, buttons), ordinary attacks, Fake Offhand and custom activation chords keep their current behavior.

Steps

External behavior research suggests the following hypotheses, but they are not treated as facts until Lamium traces current Bedrock: while the button is held, Bedrock may lock the build direction set by the first placement; blocks hovered outside that direction may be ignored; the session may place into air in front of the last block while bridging; and it may place as soon as a new position is valid instead of on a fixed interval. The Java-like mode defined above places on the currently targeted face every 4 ticks and does nothing when no valid face is targeted. Hypothesis sources (Java mods describing Bedrock, behavior only): modrinth.com/mod/pro-placer and github.com/squeeglii/BridgingMod/issues/13.

  1. Research: record Bedrock's held build session with the L-49 trace (research_trace, FakeOffhandTrace.cpp) and confirm or correct each point above: the direction lock (what sets it, which positions it accepts), placing into air along it, the timing, and what ends the session. Lamium already hooks GameMode::buildBlock and SurvivalMode::buildBlock for detached-camera interaction; test whether a discrete ordinary build action is sufficient for one server-authoritative placement, and map any required start/stop lifecycle. Do not synthesize a custom packet merely to imitate held input. Report before building.
  2. Java-like style (Ready after step 1), with tests for the interval and the left-click rule.
  3. Fast style with the per-tick cap; then combine both with L-15's placement restriction once that exists.

L-15 Breaking and placement restrictions

Kind: Design (reopened). Breaking shipped in 0.1.8 and will be redesigned; placement waits for that Design and then needs Research. The 2026-09-28 plan below replaced the old Breaking Restriction (capture/reset keys). Status: step 1 (breaking) built 2026-10-07 with L-73 step 13 and checked in game 2026-10-08 (VALIDATION-LOG). Implementation notes: RESTRICTIONS.md. Shipped in 0.1.8; the maintainer is not yet satisfied with it and expects to redesign breaking too (2026-10-10). Reopened for Design (maintainer, 2026-10-08): the plan dates from 2026-09-28 and should be rethought before placement is built. Problems seen: too many modes to cycle through, and the placement mode has no key (and does nothing yet). Steps 2-3 below wait for that rethink; the breaking behavior that passed stays until it is replaced. Faces z-fighting: L-110 (fixed). Decided 2026-10-07: breaking keeps the existing Breaking Restriction toggle and Cycle Breaking Mode bindings (no new default keys); the saved breaking mode carries over unchanged and Height band is added to the list. What it is for: leveling ground and digging tunnels without breaking past a chosen level or face, and laying floors, walls and roofs flat without placing outside them. Placing with a chosen facing is not wanted for now.

Spec (decided 2026-09-28)

Anchor and lifetime

  • The anchor is the block where the button press starts (breaking: the first block mined; placement: the first block placed). The restriction holds while that button stays held and ends on release. The capture and reset keys go away.
  • Rejected blocks never end the physical hold: when the crosshair comes back to an allowed block, breaking or placing continues (L-36 already does this for breaking). Breaking modes
  • Layer: only blocks at the first block's Y.
  • Height band: from the feet level up N blocks (default 2, a setting); this mode is anchored at the feet, not the first block. For 2-high tunnels and wide leveling.
  • Plane: the plane of the first block's mined face.
  • Line and column: straight on from the first block, or vertical through it. Placement modes (chosen separately from breaking, so leveling and laying a floor can run at once)
  • Layer (same Y as the first placed block), plane (a wall: the vertical plane through it, oriented by the first clicked face), line, column. Controls and feedback
  • Breaking and placement each have a switch with a key and a "next mode" key (no default keys decided yet); while on, the Status element shows the mode.
  • While the button is held, the allowed region shows as faint faces like Shapes, skipping the targeted block so the vanilla outline stays visible. A rejected block is silent: no sound, no toast.
  • Later, after the basic modes work: shape-linked modes (inside a shape, on its surface). Settings and ids
  • The Actions category keeps one "Block Restrictions" group. The old capture and reset actions stay in enum Action (ids are saved) but are no longer shown or dispatched; the old breaking mode setting maps to the new list. Say so in the settings migration notes before changing the store.

Steps

  1. Breaking (Ready, strong model): press-anchored lifetime, the four modes plus height band, the allowed-region faces, Status line, removal of the capture/reset flow. Pure region predicates already exist (RESTRICTIONS.md); extend them and their tests. In game: every mode in survival and creative, held-button target changes, Tool Switch together, world exit and dimension change.
  2. Placement gate (Research): Lamium already has cancellable GameMode::buildBlock / SurvivalMode::buildBlock hooks in the detached-camera interaction guard. Determine whether that boundary can reject the whole placement before mutation and, separately, how to derive the actual destination cell/state using vanilla placement semantics rather than assuming clicked-block + face is always correct. Trace ordinary blocks, replaceable vegetation, slabs/snow, doors/beds, signs, redstone, waterlogged/merge cases and edge placements without touching container use or buckets. Prefer a vanilla placement-prediction API when available. RESTRICTIONS.md lists the existing trace candidates. Stop and report if no safe path exists.
  3. Placement modes (Ready once step 2 finds a path): the four modes, anchor on the first placed block, faces and Status line. Input from the maintainer's notes (2026-10-13), for the redesign: protect by a fixed height chosen on the spot. From the looked-at block or the feet, "keep everything at or below this Y" or "break only above this Y", with the boundary plane previewed and moved with the wheel. Unlike the press anchor or the height band, it stays in world coordinates until cleared. Open: clearing it, dimension changes, combining it with fixed ranges; ordinary mining and the existing modes must keep working.

L-91 Shield glint missing in Lamium's item icons

Kind: Research. Found by the maintainer 2026-10-02 while checking L-75; leather added 2026-10-06 (found under L-61). Status: parked 2026-10-06 after a trace and three in-game experiments; the Update 2026-10-10: leather layers (and fence gates, L-119) fixed by the shared-mesh icon path inspection/render/ItemIcon (checked). Update 2026-10-11 (L-142): glinting items went back to the direct path for their glint, so an enchanted leather piece shows its undyeable parts see-through again (maintainer: record it, not now). Left: the enchanted shield's glint; one round failed and is parked; the research record and the next idea are in BACKLOG-DONE under L-119. cause is known, the fix needs a different draw path (below). Known issue. Symptoms: an enchanted shield shows no glint in container previews and the L-75 offhand slot; dyed or undyed leather armor loses its undyeable layer in container previews and the durability HUD. Vanilla slots show both. Findings (VALIDATION-LOG 2026-10-06, icon_trace):

  • Lamium draws icons with ItemRenderer::renderGuiItemNew (plus a foil call when Item::isGlint). Vanilla slots are InventoryItemRenderer, a UI custom renderer whose passes the UI batch prepares (material per pass, two texture slots) before calling renderGuiItemInChunk.
  • Leather: one slot pass, UI material Item (13), chunk type 2, and one iconBlit with exactly the arguments Lamium's call makes. With renderGuiItemNew the undyeable pixels are dropped by every material tried: the plain icon material, the multi-color tint material (which tints the dyeable pixels with the secondary color) and the UI Item material; the entity change-color material draws the transparent background too. Vanilla's own equip animation, which uses renderGuiItemNew, shows the same gap (maintainer's recording, 2026-10-06). So this call cannot draw the layer; it is not a missing argument.
  • Glint: flat icons get three slot passes (ItemGlintStencil chunk 2, InventoryItemGlint chunk 4, ItemUnglintStencil chunk 5); Lamium's single foil call at 1.35 matches them. The shield is a model (Shield material, chunk 7) and the foil call draws nothing for it.
  • Calling renderGuiItemInChunk outside a slot drew a flat tint square (L-61), because the batch setup is missing. Next step if resumed (a larger change, maintainer's call): draw these icons through the slot path, e.g. drive an InventoryItemRenderer (or its pass setup) from Lamium, which could fix the shield glint too. Keep isGlint as the glint predicate; do not replace it with isEnchanted.

L-79 Carved pumpkin and spyglass frame draw path

Kind: Research. Cheap models may run the steps below and report; implementing a hide switch needs a strong model. Parked from L-42 on 2026-09-30. Goal: find a typed, verifiable way to skip only the carved pumpkin overlay and the spyglass frame while keeping the pumpkin worn and the spyglass zoom. Known (VISUAL-EFFECTS.md "Gated frame trace" and after): neither frame passes through the three Mesh::renderMesh overloads, ScreenRenderer::blit, Tessellator::triggerIntercept or the UI render context (getTexture/drawImage/flushImages), even counted per frame. The frost frame and nausea color do pass through Mesh::renderMesh. The vanilla pack has textures/misc/pumpkinblur and textures/ui/spyglass_scope; the vanilla UI definitions reference neither. FullScreenEffectRenderer and OnCameraEffectRenderer (members of InGamePlayScreen) are opaque in SDK 26.51.5. Steps, one at a time, each with a written hypothesis first:

  1. Texture test (no code): a local test pack whose pumpkinblur.png and spyglass_scope.png are fully transparent. If the frames vanish, the frames sample those textures and a texture-load route (return a transparent texture while the switch is on, then reload) becomes the candidate; if not, find which texture they use.
  2. Search the SDK headers for other typed draw entry points not yet traced (dragon frame builder, mce::MeshHelpers, render-graph passes) and add them to the effects trace's gate/count comparison; never read or guess opaque layouts.
  3. Record each result in VISUAL-EFFECTS.md and VALIDATION-LOG.md. Stop and hand back after two runtime rounds without a new candidate.

L-71 Start an elytra glide from the mod

Kind: Research (cheap models may collect traces). Split from L-70 on 2026-09-30; low priority. Status: open. After L-70 puts an elytra on in mid-air, calling Player::tryStartGliding on the swap tick and the next three ticks always returned false (traces at 5728561 and 05648bf), and without a worn elytra vanilla never calls it. Find what vanilla's own jump-to-glide path checks and sends (input flags, the start-glide auth input action, equipment sync) and whether the client can start a glide right after the swap. No faked flags or packets: only a vanilla path that the server accepts.

L-93 Schematic: load, place, project, verify and list materials (experimental)

Kind: Follow-up tracking; each L-item below owns its kind and open choices. The initial scope shipped in 0.1.7; the screen review and 0.1.8 rendering/ compatibility work are complete. Their full record is in BACKLOG-DONE.md (L-93); SCHEMATIC.md owns the feature contract and technical history. Runtime coverage remains in VALIDATION.md.

Open work, to choose with the maintainer rather than implement as one batch:

  • Bugs: L-177 stale mismatch highlight (fix built, reporter check pending), L-117 Japanese entity-name text, and paused drawing work L-192/L-193/L-194.
  • Controls: L-230 view-directed movement (done), L-231 control rework (merged in PR #36), L-234 cut-plane layer model (merged in PR #37; L-236 follow-up; L-237 done) and L-238 menu/key parity. The design is in SCHEMATIC-CONTROLS.md.
  • Inspection and checking: L-183 mismatch suppression, L-184 saved ghost/ container data, L-190 multi-selection; permission-gated world load L-185.
  • Rendering and materials: L-114 Check-preview mistake styling/interaction, L-115 richer entity models, L-116 recipe-derived raw materials, and L-186 the remaining ghost-legibility/translucency design. L-178 piston ghosts, L-179 shulker facing and L-182 rejoin-preview crash are closed; their records are in BACKLOG-DONE.md. Map-layer integration shipped under L-139; the remaining shared controls are L-111.

L-30 Ender Dragon multipart hitboxes on Bedrock

Status: research. The maintainer wants the hitbox overlay to distinguish the dragon's damageable parts (at minimum head vs body/rest, ideally every real part exposed by the client) instead of drawing only the dragon's coarse actor AABB.

Java F3+B displays eight damageable sub-hitboxes (head, neck/body, wings and tail parts). Current public documentation also distinguishes Bedrock head-hit damage behavior, but that does not prove that the Bedrock 26.51.5 client exposes Java-style part entities or stable per-part AABBs.

  • Inspect the current client SDK/symbols and, if needed, a bounded runtime trace for dragon-specific part/AABB data used by targeting or damage.
  • Prefer the actual client damage/targeting boxes. Do not derive boxes from render bones or copy Java dimensions merely to look similar.
  • If stable parts are exposed, feed them to the normal hitbox overlay and label or color enough to distinguish the head from the other parts. If all eight parts are available, render all eight.
  • If Bedrock exposes only a coarse box or an opaque internal head test, record that limit and leave L-11's ordinary entity hitboxes unchanged.
  • Validate against a real Ender Dragon in the End; summoned/custom entities are not sufficient evidence for vanilla dragon part behavior.

References for expected Java behavior / Bedrock uncertainty: https://minecraft.wiki/w/Ender_Dragon https://minecraft.wiki/w/Tutorial:Hitboxes

L-33 Mob growth and breeding timers in the target card

Status: research (asked 2026-09-24; not part of L-08). The maintainer wants the time until a baby mob grows up and the remaining breeding cooldown. The client SDK has AgeableComponent::mAge and BreedableComponent::mBreedCooldown/mLoveTimer, but these are behavior (server-side) components; the client-side actor only receives the synced Baby and Inlove flags. Find out:

  • whether the client actor carries these components at all (likely not);
  • in a local world, whether the in-process server actor with the same unique ID can be read safely from the client thread (singleplayer only);
  • otherwise show only "baby" / "in love" states, and say so in the help text. Estimating from observed events (feeding speeds growth up) is not accurate enough to show as a time.

L-114 3D previews in the schematic screen

Kind: Research (strong model). Chosen 2026-10-08 (L-93 screen review). Status: open for the Check tab. The Files preview and the Check tab's colored preview are built, checked and shipped in 0.1.8. Not done: the Check tab preview's mistake look and see-through emphasis (decided in the Check tab review below, then deferred to the 0.1.8 rendering work, which shipped without them), plus moving the zoomed view and drawing entities, water and block entities in the previews. History: Files preview built and checked in game 2026-10-08 (f2fbf49); Check tab colored preview built and checked (1c0b8bc). Check tab review decided 2026-10-08 (SCHEMATIC.md "Check tab review"): layout A, chips drive the preview, wheel zoom, layers in the preview; the mistake look and see-through emphasis wait for the 0.1.8 rendering work. Built and checked 2026-10-09 (511cb35): layout A, chips drive the preview, wheel zoom held at the size that fits the box (the UI scissor does not clip the mesh), Shift+wheel peels layers from the side chosen when peeling starts, click to inspect (Files names the block; Check selects its row or checks the cell on the spot), the Check list keeps the nearest 2000 of each kind. Left for later: moving the zoomed view, entities, water and block entities in the preview, the mistake look and see-through emphasis. Not drawn yet: entities, water, block entities (chest, ender chest, shulker box), honey block and others without an in-world mesh. How it works (Preview.cpp, pure parts in PreviewView.h): visible blocks are tessellated in-world at a spot above the build limit (no real neighbor or light), moved to their cell, and drawn with the ghosts' block material into a scissored box. The UI pass keeps the first fragment at a spot and has no usable depth (giving vertices depth cut blocks apart), so every quad is sorted near to far for the view's octant; the quads are kept and only re-sorted when the view turns or recolored when the check changes. Faces touching a block that covers them (opaque, drawn on this path) are dropped. Normals all point up and faces are darkened by direction (lighting through the flattening matrix flashed). Builds 3000 blocks a frame, up to 120000 visible blocks. Drag turns it. Goal: a rotatable 3D preview of a file in the Files tab and of the selected placement colored by verifier state in the Check tab (the selected row lit). Vanilla draws 3D inside UI (the structure block screen), so find that path first; the ghosts already tessellate schematic blocks into meshes. Stop and report after two runtime rounds without a working path.

L-115 Entity ghosts drawn as models

Kind: Research (strong model). Chosen 2026-10-08 (L-93 screen review). Status: open. A first version is built, checked in game 2026-10-08 (EntityModels.cpp, rounds on trace builds up to ef9bc54) and shipped in 0.1.8, but it is a compromise (maintainer 2026-10-10): many entities draw light-blue faces instead of their skin, and details such as cushion colors are not drawn. Known limits are listed below. Draw missing schematic entities as their models with the light-blue outline, not translucent, without a live entity.

How it works:

  • Model: ActorRenderDispatcher::getDataDrivenRenderer(id) by the entity identifier gives the model and default skin, drawn with the renderer's mEntityAlphatestMaterial. Model holds several geometries (adult, baby, charged, variants): draw "default", else the first that is not baby/charged. Entities without a model keep the dashed frame and the only world name tags (logged once per identifier). At most 64 models a frame.
  • Placement: compileCubes (untransformed, once per part) emits each part's quads relative to its bone pivot (BoneOrientation::mPivot, absolute) with y flipped, cube rotations and inflation applied. Parts are chained in the stored y-up space, each turned about its bone pivot; geometry x is mirrored in the world, as the game draws it. Rotations in that stored space: x and z turn the other way, y as is. Outlines follow the compiled quads. translateTo and ModelPart::mRot are not used (the game writes a live entity's pose into the shared model: posing one armor stand moved every ghost).
  • Pose: bone rest rotations plus the constant parts of the entity's own animation.<name>.* setup/general animations (an armor stand's default_pose), rotations and position offsets, only from animations whose bones are all in the model (a horse's legacy setup moved the new head). Molang is evaluated only when it needs nothing from the entity (RestPose.h, tested): numbers, this as the bone's rest value, arithmetic. Legacy .v1.0 copies are skipped when the current one exists. A bone the entity's own animations leave alone takes a rotation that two or more other entities' setup/general animations agree on, when all their bones are in the model (the witch's crossed arms come from the villager's). Borrowing a whole animation family by bone fit was tried and removed: it gave traders, strays and polar bears the sheep's head offset.
  • Skin: the default skin is one texture of the entity's set; when it is a layer (armor, decor, markings, profession, _none, baby, saddle, overlay) the model draws light-blue faces with the overlay face material (overlay/FaceMaterial.h, per graphics mode). Horses, donkeys, mules, llamas, trader llamas, villagers and rabbits do.
  • The saved Rotation yaw turns with the placement (toWorldYaw, tested).
  • xmake f --schematic_model_trace=y logs each model's geometries, skin, animations, pose and per-part pivots once.

Checked in game: armor stand (default pose, arms on the right sides), chicken, cow, creeper, witch, wolf, pig, polar bear, turtle, camel, frog, wandering trader, stray, zombie, drowned, horse family (tinted). Known limits:

  • Poses that need the entity stay at rest: a wolf's tail hangs straight down into the body (query.tail_angle); zombie-like arms hang down, so a drowned's sleeves flicker against its jacket; sitting, walking.
  • Layered skins beyond the default: a sheep's wool on head and legs is not drawn; variants (cat, rabbit, villager profession) use the default skin.
  • An armor stand's own pose (Pose.PoseIndex in its saved data) is not read. Animations are found by name, so an entity animated under another name (donkey: horse) stays unposed.
  • Light-blue faces flicker more in Simple graphics (lightning material).
  • Many mobs (water, flying, projectiles) were not in the test schematic.

L-116 Raw materials from the game's recipes

Kind: Research, then Design. Chosen 2026-10-08 (L-93 screen review). Status: open. Show the raw materials needed for a schematic's missing blocks (logs for planks, cobblestone for stone bricks) in the Materials tab, computed from the recipes the client holds (Level::getRecipes(): crafting, furnace, stonecutter), not from an outside calculator (ResourceCalculator's data is GPL-3.0; see SCHEMATIC.md). First find what the client actually holds and how ingredients with several choices (any log, tags) and multi-step chains (cobblestone, stone, stone bricks) appear; then decide with the maintainer which recipe to prefer when several make the same item. The calculation is pure logic with tests.

L-111 Integration between features: remaining shared controls

Kind: Design. The required 0.2.0 work (L-134/L-135/L-136/L-137/L-138/L-139) passed the recorded regression checks and two outside reviews, then shipped on 2026-10-11. Its plan and release/regression checkpoints are retained in BACKLOG-DONE.md. No 0.2.0 work remains to be released.

Open optional scope (no implementation or release chosen): a common Lamium radial menu, looked-at selection and settings cross-links (C/D/E in INTEGRATION.md). A menu needs an agreed demo first; one common opener versus per-feature openers remains undecided. Maintainer input, 2026-10-13: make spatial actions usable while working, without setting up a feature first. Candidate shared operations are a base point from the looked-at block or feet, two range corners, a Y boundary adjusted by the wheel, and repeating the last adjustment. L-173 quick shapes and L-15 restrictions own their behavior; L-230/L-231 first address the schematic controls themselves.

Keep independent feature lifecycles and shared parts that features register into; do not merge features. Keep display layers distinct from allowed-action regions. Check input contexts, binding conflicts and UI weight with the maintainer. Tidy touched code separately from behavior changes, preserve per-capability fail-open, and check each step in game before the next.

L-105 Performance: find the real bottleneck before optimizing

Kind: Research (strong model). Chosen by the maintainer 2026-10-07 from their notes. Measured 2026-10-14 (VALIDATION-LOG, schematic perf trace): with 3086 ghost sections shown the ghost pass costs 4-6 ms a frame standing still with nothing rebuilt, mostly per-section draws (faces, lines, block actors, entities); a candidate is merging sections into fewer meshes. Status: open. Step 1 only; no optimization is built until it names a bottleneck. Why: Hide particles / weather / overlays avoid some drawing, but they are situational wins, not a way to large frame-time gains. Bedrock is already native C++ on RenderDragon, so gains that come easily on other platforms may already be present; measure what is expensive here first. The ideas worth testing are known in general terms (sources for the hypotheses are in PROVENANCE.md): rebuild terrain meshes less often or off the critical path, submit many small draws as fewer batches, skip entities and block entities that cannot be seen, and cache or make event-driven repeated per-tick work. Direction: Lamium does not become a renderer replacement. Prefer bounded, measurable substitutions that skip, cache, batch or defer one expensive vanilla path while keeping vanilla behavior, capability-gated and fail open like every version-sensitive path. Steps:

  1. Profiler spike (a build option, like the trace options, never on in a release): measure per frame, in heavy real scenes (a village, a large farm, a storage room, flying fast over new terrain), frame time and its 1 % lows, and as far as hooks allow: terrain/chunk drawing, chunk mesh rebuild count and time (and on which thread), entity and block-entity drawing, particles, HUD/UI, mesh draw-call counts. Record results in VALIDATION-LOG.md.
  2. Pick at most one or two dominant costs and write a bounded candidate per cost (what is skipped, cached, batched or deferred; how vanilla behavior is kept; how it fails open). Each becomes its own L-item with the maintainer. Areas to look at first:
  • Chunk mesh rebuild scheduling: what triggers rebuilds, how much runs on the render or main thread, whether some can be deferred without gameplay change. A likely cause of stutter while turning or moving.
  • Draw submission: whether meshes, entities, block entities, particles or UI still issue many small draws or state changes.
  • Visibility: whether entities and block entities behind walls, underground or in other rooms still cost a lot. Conservative culling could matter in farms, villages and storage.
  • Repeated simulation work (lookups, per-tick scans, collision checks, short-lived allocations), only after the profile points there.
  • Particles: Hide particles skips drawing, not necessarily their creation and updates. A "skip particle processing" path may help particle-heavy scenes; it is not the main route. Success: better frame time and 1 % lows in heavy scenes, not a higher average in an empty world. One proven large bottleneck beats many guessed micro-optimizations.

Later / parked

The first notes here were imported on 2026-10-12 for later consideration; low-priority requests accepted since then are appended at the end. Documentation tracking does not approve implementation or a release target. L-154 was merged into L-169 and is archived in BACKLOG-DONE.md. Fake Offhand reserved-slot protection is excluded from this import; the undecided historical idea remains in L-94's record.

L-151 Show the player's body in first person

Kind: Research, with Design before implementation. Low priority. Goal: optionally show the body when looking down; proposed default off. Investigate whether the detached camera's player-model component can be applied locally without a deeper renderer change. Check head/face clipping, duplicate vanilla arms/items, armor and elytra animations, perspective and FreeCamera transitions, and restoration. L-123 is a related unresolved rendering risk. Defer if many special cases or deep hooks are needed. No implementation or runtime evidence; not required for integration work.

L-152 Preview held map items in inventory

Kind: Design, then Research for client-observed map data and rendering. Goal: make a map item easier to inspect from inventory without equipping it. Open: hover preview versus explicit action, preview size and zoom, empty or unreceived map data, and supported screens. Keep this distinct from the world map; never infer unexplored contents. No implementation commitment.

L-153 Prefer the last pressed opposing movement key

Kind: Design, then Research for the native input boundary. Goal: optionally resolve simultaneous W/S or A/D input to the last pressed direction. Open: default, release/resume semantics and interaction with remapped keys, controllers, permanent movement and detached cameras. Model event sequences in pure logic before touching gameplay input; menus and focus changes must not leave stale held inputs. Not implemented.

L-282 Toggle Vibrant Visuals with a key

Kind: Research, then Design. Requested on the Discord server 2026-10-28: is there a Vibrant Visuals toggle key; if not, can one be added. Maintainer note 2026-10-30: the motive, as reported, is weak PCs — turning Vibrant Visuals off from a key instead of opening the vanilla settings screen, which is heavy on such machines. The value is mostly in the quick exit; turning it back on is the same key press. Research first: whether the client can change the vanilla graphics mode outside the settings screen (an options path the client owns), what a switch costs mid-world (resource or shader reload, hitch, screen flash), whether the vanilla setting itself persists the change, and how version-sensitive the path is (Vibrant Visuals is still changing; a new hook needs a GAME-UPDATES entry and the capability gate). Priority is not high: this is a convenience proxy for a vanilla setting, not information Lamium adds. Decide whether to build it only once the research prices the switch. No release target selected.

L-283 Stronger block outline and a crosshair face highlight

Kind: Design. Requested on the Discord server 2026-10-29: a customizable block outline (color, thickness, a see-through mode showing all the cuboid's edges instead of only the visible ones) and a highlight of the face the crosshair points at. The vanilla outline is "way too inconspicuous"; the face highlight is for operations that rely on precise angles. Maintainer priority note 2026-10-30: tools outrank visual enhancement, and Lamium's visual features mostly make more information readable. Split this request the same way: the face highlight and the outline's legibility are information and are the point of the item; free color/thickness choice is aesthetics and carries less weight, so decide the customization scope against the existing discipline (palette colors; the four shape colors) rather than assuming a free picker. Open: the rendering path for the targeted block and its version sensitivity (capability gate, GAME-UPDATES entry); the depth order against the vanilla outline under the DESIGN world-overlay rule (position markers win, guides yield); replace the vanilla outline or draw alongside it; non-cuboid blocks (slabs, stairs, fences) whose selection shape is not the full cube; what see-through edges may draw over. Settings shape is one feature switch with only the child options the design actually decides. No release target selected.

L-284 Custom crosshair

Kind: Design. Requested on the Discord server (maintainer's recollection 2026-10-30; the requester and the date were not recorded): let the player change the crosshair's appearance instead of keeping the vanilla one. Open: what is customizable within the UI discipline — style/shape, size, color from the palette; the drawing is rectangles and text only. A Lamium-drawn crosshair needs the vanilla one hidden and must follow the vanilla crosshair's contexts (hidden with Hide HUD, the states where vanilla changes or drops it). Related to L-283 (both are about reading the aim point); decide whether they share a settings home. Priority: low as pure appearance unless the design ties it to visibility; nothing decided yet. No release target selected.

L-287 Make the minimap arrows legible at every map size

Kind: Design (parked 2026-10-31). Split from L-286 when its camera arrow landed on main: the marker itself is done, but the player and camera arrows are drawn into the 256 px map texture, so a small map minifies them into a mangled shape, and at larger sizes the plain triangle does not read as an arrow. The maintainer gave up on the current look for now. Tried on branch l286-minimap-camera-arrow (kept locally, commits b2f563e4 to ec66e53f, not merged): screen-space arrow images (no minification with the map), scaling with the Map Size with a 6 px floor, a two-unit outline, a notch-less triangle for small arrows, a head-and-shaft glyph, and hard black/white edges instead of anti-aliasing. Each was checked in game; none was accepted: small sizes stayed hard to tell apart from the white radar dots, and large ones showed a thin edge, an obvious triangle, or a grey mosaic. Open: a different marker rather than another glyph tweak - for example a direction wedge on the map frame, the mockup's green player arrow, or drawing the arrow in the HUD layer above the map. It must read at the smallest Map Size without dominating it, keep the camera arrow distinguishable, and still look like the map grew out of the game's own art. Do not re-tune the current glyph without a new idea. Re-check 2026-10-31 after L-286 merged to main (b6ad8327, DLL c38a2ff2): the camera arrow draws well, and most Map Size and Range settings look clean. Narrowed the same day: the distorted player and camera arrows come back around Map Size 18 %, so the distortion is limited to some map sizes rather than gone. That fits the in-texture drawing (the 256 px map texture, arrow included, is minified to the map's on-screen size and those scales alias the arrow's thin outline and notch). Watch item: re-open with that condition if wanted. No release target selected.

Previously parked work

  • L-19 Freelook in multiplayer, riding, dimension change, controller: runtime checks only, no code expected.
  • L-25 Detached-camera interaction options (parked, after L-18; agreed 2026-09-24, implement only once FreeCamera proves viable). While detached, attack/use are fully blocked and clicks still swing the arm. Desired shape: per-feature detail settings, FreeCamera x {attack, use/place/interact, break} and Freelook x {attack, use/place/interact, break} (6 toggles, all default off). Aim follows the body, never the detached view; state this in the help text. Movement freeze (FreeCamera) and movement keep (Freelook) stay non-optional. Swing suppression (no arm swing while detached) is a separate Research item: find the swing trigger first.
  • L-29 Hide the hotbar while detached (parked, after L-18). Requested 2026-09-24: an option to hide the hotbar while FreeCamera is active (looking-only flight needs no hotbar). Find the vanilla hotbar render entry first; Freelook is out of scope unless trivially shared.
  • L-86 Radar faces follow-up (after L-85; noted 2026-10-02): mobs without a "head" part (silverfish, tadpole) could use the whole model seen from the front; rotated head bones (camel, hoglin) need the bone rotation in the front view; check the remaining mob kinds (only about 25 of 80+ were seen); decide whether faces become the default once they hold up.
  • L-21 Shape color picker or more colors: only if the four colors prove insufficient.
  • External PR #10 (Spanish localization and map daylight tint, opened 2026-10-07): the maintainer asked on 2026-10-08 for one PR per feature, translations updated to the latest main, Night Vision and unaffected markers for the map tint, and the provenance statement. Nothing is discussed further until it is split.
  • Mass Craft became L-165 (2026-10-12). (Schematic became L-93; Fast Attack/Use became L-34; Scroll Transfer became L-41.)