|
1 | | -# Parked: what commodities can be sold where |
2 | | - |
3 | | -Raised 2026-08-21 by nekron, parked to come back to. This is the state of the |
4 | | -question and the routes out of it, written down while the detail is fresh. |
5 | | - |
6 | | -The related finding — that a cargo sale in *our own logs* cannot be named — is in |
7 | | -[commodity-names.md](commodity-names.md) and is not repeated here. This page is |
8 | | -about the other half: a **reference table of which kiosk trades which commodity**, |
9 | | -which needs no logs at all, only the game's own static data. |
10 | | - |
11 | | -## The three layers between us and it |
12 | | - |
13 | | -| Layer | What it is | Where we stand | |
14 | | -|---|---|---| |
15 | | -| **Archive encryption** | `Data.p4k` is a ZIP64 container; CryEngine/Lumberyard encrypts some entries | Partly a non-issue. The localisation table is *not* encrypted and `P4kArchive` already reads it, which is where 9,527 item and 1,343 place names come from. Encrypted entries are reported, never guessed at. | |
16 | | -| **CryXMLB** | XML compiled to a binary format; opens as junk in a text editor | Not hit yet. The files read so far are plain. Community tools (`unforge`, `CryXMLConverter`) convert it, and the format is documented. | |
17 | | -| **DataForge** | `Data\Game2.dcb`, the record database — ships, items, shops, prices | **Readable.** 330 MB, unencrypted, extractable today with `P4kArchive`. It holds the commodity catalogue: `libs/foundry/records/entities/commodities/minerals/dolivine.xml`, `.../natural/sunsetberry.xml`, `.../scrap/scrap.xml`. | |
18 | | - |
19 | | -The community's account of these layers is accurate, but on this install the |
20 | | -DataCore is *not* the wall. It is open. What we have not done is **parse** it — |
21 | | -every search so far has been a raw byte scan, which finds strings and misses |
22 | | -structure. A DataForge reader resolves records, enums, string tables and |
23 | | -pointers, and only then can a shop record be asked what it stocks. |
24 | | - |
25 | | -## The routes, and what each costs |
26 | | - |
27 | | -**1. Write a DataForge reader.** Parse `Game2.dcb` from the user's own install, |
28 | | -the way `P4kArchive` already parses the container. Offline, no redistribution, no |
29 | | -new dependency, and it either answers the question or proves the answer is not |
30 | | -in there. The format is community-documented and `ScDataDumper` is a working |
31 | | -reference implementation to check behaviour against. |
32 | | - |
33 | | -*Recommended.* It is the only route that keeps every promise the README makes. |
34 | | - |
35 | | -**2. Ship pre-extracted JSON** from `StarCitizenWiki/scunpacked-data`. |
36 | | -Fastest by far, and it directly contradicts our own `NOTICE`: *no game data is |
37 | | -contained in this repository, and none may be added to it*. It also redistributes |
38 | | -data derived from CIG's build. Rejected unless that policy changes deliberately. |
39 | | - |
40 | | -**3. Fetch UEX or scunpacked at runtime.** Would give live prices too, which is |
41 | | -genuinely useful for trading and is what most neighbours do. It breaks "no |
42 | | -outbound network calls", which is the thing that distinguishes this app in |
43 | | -[landscape.md](landscape.md). Only ever as an opt-in that is off by default and |
44 | | -says plainly what it contacts. |
45 | | - |
46 | | -**4. Decrypt `Data\ShopInventories\*.json`.** These are the shop stock tables and |
47 | | -are the most likely home of the `resourceGUID` mapping. They are deliberately |
48 | | -encrypted. Reading what CIG left open is one thing; circumventing a protection |
49 | | -measure they chose to apply is another, and it would break on any key change |
50 | | -besides. **Not planned.** |
51 | | - |
52 | | -## What to try first, if this is picked up |
53 | | - |
54 | | -1. Extract `Data\Game2.dcb` with the existing `P4kArchive` — already proven. |
55 | | -2. Parse the DataForge header: structure definitions, property tables, enums, |
56 | | - string tables, then records. |
57 | | -3. Look for shop or kiosk records that reference commodity records, and for any |
58 | | - id form matching the four `resourceGUID` values in the logs. |
59 | | -4. If the mapping is there, the Cargo view gains real names and a |
60 | | - "where to sell this" reference, entirely offline. |
61 | | -5. If it is not, say so here, and the decision becomes route 3 or nothing. |
62 | | - |
63 | | -Whatever comes of it, the rule from [architecture.md](architecture.md) holds: if |
64 | | -a name cannot be established, show what is provably known and stay quiet about |
65 | | -the rest rather than guessing from unit price. |
| 1 | +# What commodities can be sold where |
| 2 | + |
| 3 | +Raised 2026-08-21 by nekron. Route 1 — write a DataForge reader — was tried the |
| 4 | +same day. This page is now the result rather than the plan. |
| 5 | + |
| 6 | +**The short answer: half of it is possible offline, and the interesting half is |
| 7 | +not.** The commodity catalogue is in the DataCore and can be read today. Which |
| 8 | +kiosk trades which commodity is not in there at all, and neither is the join that |
| 9 | +would name a sale in our own logs. |
| 10 | + |
| 11 | +The related finding — that a cargo sale cannot be named from the log alone — is |
| 12 | +in [commodity-names.md](commodity-names.md). |
| 13 | + |
| 14 | +## What was done |
| 15 | + |
| 16 | +`Data\Game2.dcb` was pulled out of `Data.p4k` with the existing `P4kArchive`, |
| 17 | +no external tool involved, and examined in four passes. It is **330,491,142 |
| 18 | +bytes**, unencrypted, and its header reads cleanly: version 8, then the |
| 19 | +definition counts — **6,685 structs, 23,722 properties, 772 enums, 116,512 |
| 20 | +records**. |
| 21 | + |
| 22 | +So the community's account of the three protection layers is accurate in |
| 23 | +general, and beside the point here: on this install the DataCore is open. |
| 24 | + |
| 25 | +## 1. The commodity catalogue is there |
| 26 | + |
| 27 | +**135 commodity records**, named and categorised: |
| 28 | + |
| 29 | +| Category | | Category | | Category | | |
| 30 | +|---|---:|---|---:|---|---:| |
| 31 | +| minerals | 21 | manmade | 12 | agriculturalsupplies | 4 | |
| 32 | +| metals | 17 | gas | 7 | halogens | 4 | |
| 33 | +| vice | 17 | processedgoods | 5 | food | 3 | |
| 34 | +| natural | 16 | alloys | 4 | counterfeit | 3 | |
| 35 | +| consumergoods | 12 | medicalsupplies | 3 | scrap | 2 | |
| 36 | +| mixedmining | 2 | non_metals | 2 | waste | 1 | |
| 37 | + |
| 38 | +Real names, not ids: `aphorite`, `bexalite`, `dolivine`, `agricium`, |
| 39 | +`quantumfuel`, `rmc`, `sunsetberry`, `altruciatoxin`. This is a usable reference |
| 40 | +table and it costs nothing but a parser. |
| 41 | + |
| 42 | +Shops are represented too, but only as **brands**: 58 kiosk manufacturer records |
| 43 | +and 58 brand styles — CenterMass, Casaba, Astro Armada, Cordry's. The app |
| 44 | +already resolves those from the localisation table. |
| 45 | + |
| 46 | +## 2. The kiosks are not |
| 47 | + |
| 48 | +The log names shops as `SCShop_OmegaPro_NewBabbage` and |
| 49 | +`SCShop_Admin_lt_base_g`. The DataCore contains **zero strings beginning |
| 50 | +`SCShop`**. The only location-flavoured shop records are seven UI map section |
| 51 | +definitions (`shop_admin`, `shop_centermass`, `shop_wallys` and four more), |
| 52 | +which are map furniture, not stock lists. |
| 53 | + |
| 54 | +There is no shop→commodity table in this file. Nothing to parse harder for. |
| 55 | + |
| 56 | +## 3. The join is not there either |
| 57 | + |
| 58 | +Every `resourceGUID` this install has ever logged was extracted — **13 distinct |
| 59 | +ids across 146 log files** — and each was searched through the whole DataCore in |
| 60 | +three forms: ASCII text, little-endian bytes, big-endian bytes. |
| 61 | + |
| 62 | +**None of the 13 appears, in any form.** That settles the question the earlier |
| 63 | +note left open: the ids in the sale log belong to a different numbering from |
| 64 | +anything the DataCore holds. (The earlier note said four ids; the true figure |
| 65 | +across every backup is thirteen.) |
| 66 | + |
| 67 | +## 4. There is no second copy |
| 68 | + |
| 69 | +The DataCore is compiled from source records, so the archive was checked for |
| 70 | +those too — `Data\Libs\Foundry\Records\...` in both slash styles and both cases, |
| 71 | +five root spellings. **All misses.** The compiled database is the only copy in |
| 72 | +the archive. |
| 73 | + |
| 74 | +## Where that leaves it |
| 75 | + |
| 76 | +| Want | Possible offline? | |
| 77 | +|---|---| |
| 78 | +| A catalogue of every commodity, by category | **Yes.** 135 records, names and all, from the user's own install | |
| 79 | +| Which brand a kiosk belongs to | **Yes**, and already done | |
| 80 | +| What a given kiosk buys or sells | **No** — not in the DataCore. Community data has it; see below | |
| 81 | +| Naming a commodity in our own sale log | **Not offline** — solved via the opt-in community dataset; see below | |
| 82 | + |
| 83 | +The last two most likely live in `Data\ShopInventories\*.json`, which ships |
| 84 | +encrypted. Reading what CIG leaves open is one thing; circumventing a protection |
| 85 | +measure they deliberately applied is another, and it would break on any key |
| 86 | +change besides. Still not planned. |
| 87 | + |
| 88 | +## The break: the community already resolved the join |
| 89 | + |
| 90 | +Checked the same day, at nekron's prompting: **StarCitizenWiki/scunpacked-data** |
| 91 | +carries `resources/commodities.json` — 243 KB, regenerated after each game |
| 92 | +patch — and it resolves **every resourceGUID this install has ever logged**. |
| 93 | +All of them, tested, not sampled: the sales were DynaFlex, Waste, Tin, Stims, |
| 94 | +Medical Supplies, Iron, Copper, Aluminum, Nitrogen, Hydrogen, Hephaestanite and |
| 95 | +a Year of the Rat Envelope. |
| 96 | + |
| 97 | +Seven further byte-order permutations were tried against the DataCore first |
| 98 | +(CryEngine's CigGuid has its own layout) — all misses, so the id genuinely is |
| 99 | +not recoverable from the local install. The community file is the only source. |
| 100 | + |
| 101 | +**Shipped as an opt-in.** The repository carries no licence and the data is |
| 102 | +CIG-derived, so it is not vendored into this repository or the binary — that |
| 103 | +decision is not ours to make. Instead the Cargo page offers a button that |
| 104 | +fetches the one file into local app data, with the source named and the promise |
| 105 | +stated: it is the only network request the application can make, and it never |
| 106 | +happens without the click. `CommunityData` in the Data project holds the |
| 107 | +mechanics; the README's network claims carry the exception. |
| 108 | + |
| 109 | +## Still open: what sells where, on the map |
| 110 | + |
| 111 | +The same repository has `resources/commodity_trade_locations.json` (27.9 MB): |
| 112 | +per commodity, the facilities that buy and sell it, with class names like |
| 113 | +`DC_Stan_Hurston_S1_Farnesway_CargoShop` that our resolver's grammar can meet. |
| 114 | +That is the map-enrichment half of nekron's ask — "sell Waste here" markers — |
| 115 | +and it is a second, larger piece of work: download opt-in alongside the first |
| 116 | +file, parse, and join facility class names onto atlas nodes. Parked until the |
| 117 | +naming slice has settled. |
| 118 | + |
| 119 | +## If the offline catalogue is still wanted |
| 120 | + |
| 121 | +Parsing 135 records out of the DataCore needs the DataForge structure walked |
| 122 | +properly. The header is understood (above), which is the part that usually |
| 123 | +stops people. But with the community file resolving ids for anyone who opts in, |
| 124 | +the offline catalogue would only serve those who decline — worth doing someday |
| 125 | +for completeness, not first. |
0 commit comments