Read per-item state on conveyors, and count belt items in the item search - #23
Merged
Conversation
An item search summed every inventory in the save but nothing in transit, so a running factory under-reported by everything on its belt network -- half the iron ingots on one 54MB test save (166k of 331k), 559k items on another. Since 1.0 a belt line's items live in one ring buffer on the shared FGConveyorChainActor, each member belt owning a contiguous window of it. item_location_index now walks those windows and counts each item against the belt it physically rides -- not the chain actor, which has no footprint -- so every location the search lists stays a real placed building at a real position, and belts group next to machines and containers in the modal like any other holder. Pre-1.0 saves keep items on the belt actor itself; those count too. The ring arithmetic moves into queries::conveyor_chain_segment_window, shared with the belt tooltip's per-segment item list rather than copied. Tests: the index agrees belt-by-belt with aggregateSelectionInventory (the independent path behind the tooltip and selection panel), and the per-belt windows tile each chain's ring exactly -- no slot double-counted into two belts, none dropped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A save with anything stateful parked on a belt -- a jetpack with fuel, a loaded weapon, a gas mask with a filter -- failed to load outright: object re-parse failed during index build: object at (3861, 109202): Value 1172451892 at offset 663613945 does not match the expected 0. Since save version 44 an item's slot carries an `itemState` flag and, when set, an inline record: an empty level name, the state's type path, and its length-prefixed properties. The per-belt item format already read that; the conveyor CHAIN format -- which is where every belt item actually lives since 1.0 -- asserted the flag was zero instead, so the first geared-up item on a belt turned the rest of the object into drift and took the whole save with it. Reported in #22, reproduced on a save of belts hung with jetpacks, gas masks and hazmat suits (now map/uploads/belt_item_state.sav). Both formats now skip the record through one helper and keep its span, so the chained-belt delete write-back hands the bytes back verbatim: a jetpack that survives a cut line comes back with its fuel, not empty. Chain and belt item slots become named structs rather than tuples, which is also where the chain slot's trailing float gets its real name -- it is a distance along the line, not an instance id (consecutive gallery items sat exactly 120cm apart). Verified: every map payload in the corpus is byte-identical to before, the save-index differs only by the belt items the search now counts (nothing lost, no total decreased), and the repro save loads in the app with its belt items listed in the item search. Fixes #22 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two fixes to how items on conveyors are read, both reported against the same part of the parser.
1. Saves with stateful gear on a belt failed to load (#22)
Since save version 44 an item slot carries an
itemStateflag and, when set, an inline record: an empty level name, the state's type path, and its length-prefixed properties. The per-belt item format already read that; the conveyor chain format — where every belt item actually lives since 1.0 — asserted the flag was zero instead. The first geared-up item on a belt (a jetpack with fuel, a loaded weapon, a gas mask with a filter) turned the rest of the object into drift and took the whole save down with it.Both formats now skip the record through one helper and keep its span, so the chained-belt delete write-back hands the bytes back verbatim — a jetpack that survives a cut line comes back with its fuel, not empty.
Chain and belt item slots become named structs rather than tuples, which is where the chain slot's trailing float also gets its real name: it's a distance along the line, not an instance id (consecutive gallery items sat exactly 120 cm apart).
2. The item search never counted anything in transit
An item search summed every inventory but nothing riding the belts, so a running factory under-reported by its whole belt network — half the iron ingots on one 54 MB save (166k of 331k), 559k items on another. Items now count against the belt they physically ride, not the chain actor (which has no footprint), so every location listed is a real placed building.
Verification
tests/belt_item_state.rsgates the parse, the state spans' byte layout, searchability, and a delete round-trip;editor::applypins the write-back record layout.Test corpus bumped to
test-saves-v2(adds the 419 KB repro save; the other three assets are unchanged).Fixes #22