A maintainer CLI that regenerates the embedded Rust item dataset
(src/RustPlusBot.Features.ItemData/Data/item-data.json) consumed by the bot's
/item, /recycle, /craft, /research, /decay, /upkeep, /durability, /smelt, and /cctv calculators.
This tool is not part of the running bot — it is referenced by nothing in the application graph. It exists so the bundled item data can be refreshed when Rust updates, rather than shipping a frozen copy that silently rots.
The reference data has two very different freshness profiles:
- Item names / ids are well maintained and current.
- Calculator data (recycle yields, craft recipes, research costs, decay times, upkeep costs) is sourced from rustlabs and tends to lag game updates.
So the dataset carries per-section provenance dates (Sources.NamesAsOf,
RecycleAsOf, CraftAsOf, ResearchAsOf, DecayAsOf, UpkeepAsOf), surfaced to users as a
"data as of <date>" footer, and this tool can re-emit a fresh snapshot on
demand. It validates loudly and refuses to overwrite a good bundle with
garbage if the upstream shape drifts.
-
Reads the rustplusplus static data files (offline transform — no network):
File Provides items.jsonid → display name (the item spine) rustlabsStackData.jsonstack size rustlabsDespawnData.jsondespawn time rustlabsRecycleData.jsonrecycler yields rustlabsCraftData.jsoncraft ingredients + time rustlabsResearchData.jsonresearch scrap cost rustlabsDecayData.jsondecay time + HP rustlabsUpkeepData.jsonupkeep cost (resource + quantity range) rustlabsDurabilityData.jsonraid cost (explosives only — trimmed) rustlabsSmeltingData.jsonsmelting/cooking conversions (per smelter) cctv.jsonmonument CCTV camera codes -
Projects them into our own typed schema (
ItemDataset/ItemRecord/ …, defined inRustPlusBot.Features.ItemData), keyed by item id, with calculator data inlined per item (null where an item has none). -
Validates the result (
DatasetValidator): a minimum item-count floor, a minimum raid-target count floor, that every recycle-yield / craft-ingredient / upkeep-cost id resolves to a known item, that upkeep quantity ranges are well-formed (min <= max), that decay values are non-negative, and that every raid cost has a positive quantity and a valid tool-item id. -
On any validation error, prints the errors to stderr and exits non-zero without writing — the existing good bundle is never clobbered.
-
On success, writes the dataset as indented JSON and exits 0.
Items present in a rustlabs file but absent from items.json (no name) are
dropped, and the dropped counts are logged — never silent.
dotnet run --project tools/RustPlusBot.ItemData.Generator -- \
--out src/RustPlusBot.Features.ItemData/Data/item-data.json \
--rustplusplus ~/Dev/rustplusplus/src/staticFiles \
--min-items 1000| Argument | Required | Default | Meaning |
|---|---|---|---|
--out <path> |
yes | — | Where to write item-data.json |
--rustplusplus <dir> |
no | ~/Dev/rustplusplus/src/staticFiles |
Directory holding the source JSON files |
--min-items <n> |
no | 1000 |
Validation floor; fewer items than this fails the run |
Exit code 0 on success, 1 on a usage error or validation failure.
After regenerating, rebuild and run the test suite — the runtime loader
(EmbeddedItemDatabase) deserializes this file at startup, and the ItemData
tests assert known items resolve correctly.
- Update your local rustplusplus checkout so its
src/staticFilesis current. - Run the command above.
- If validation fails, the bundle is left untouched — investigate the reported drift (an upstream file that changed shape, or a count below the floor) before re-running.
- Bump the relevant
Sources.*AsOfdates inProgram.csto reflect the new source dates, re-run, then commit the regenerateditem-data.json.
The source dates stamped into the dataset are currently hard-coded constants in
Program.cs (NamesAsOf, RecycleAsOf, CraftAsOf,
ResearchAsOf, DecayAsOf, UpkeepAsOf, DurabilityAsOf, SmeltingAsOf, CctvAsOf).
Update them when you refresh from newer upstream data.
- 6a ships the offline transform only. A live-scrape source adapter
(
IRustLabsSource) is sketched as a seam for a future slice; for now the tool transforms a local rustplusplus checkout. - Recycle data covers the standard recycler only; safe-zone recycler and shredder yields are out of scope for this slice.
- Durability data is trimmed to the
explosivetool group during the transform (OfflineDurabilitySource) and projected intoRaidTargets(item / building-block / vehicle). The raw source (rustlabsDurabilityData.json) is ~19 MB and is never bundled — only the projected, explosive-only rows are written intoitem-data.json. - Smelting data (
rustlabsSmeltingData.json, ~28 KB) is keyed by smelter and projected into a dedicatedSmelterstable (OfflineSmeltingSource), resolved by name like raid targets. Its provenance (SmeltingAsOf, 2023-11-05) lags the other rustlabs sources because the upstream file has not changed since then. - CCTV data (
cctv.json, ~2 KB) is keyed by monument name and projected into a dedicatedCctvtable (OfflineCctvSource), resolved by name. Codes are un-escaped (\*→*) during the transform. Its provenance (CctvAsOf, 2025-11-12) is the upstream last-change date for the file.
Item names/ids originate from Facepunch's published item list; recycle/craft/ research data originates from rustlabs via the rustplusplus static files.