CURRENT EXECUTION DOMAIN
The table that matters is the one owned by the program doing the mining
Current Play uses a split context. Reward-bearing mining is sent directly to the standalone Chunk Program GnVKn442KDTDgCyjVG7SEtCQQLjaCiLvrEZDWSU13wbj, while Backpack, Smelting, and Marketplace instructions are routed through the unified Game Program 6CurnvneezBuHwPUnrCiFg1QMWeUF67ufQxYebyr2UP7. The mining instruction therefore derives ChunkBroken, PlayerProgress, ResourceDropTable, and SurfaceDecorationTable under the Chunk Program ID, then invokes the Game Program's Backpack namespace for storage.
At finalized slot 476,371,044, the active ResourceDropTable was Hf3MpkMq5E3f6uCR1RQKLw2DiC4TgcvhDkmuSvttdhHT. A second 867-byte ResourceDropTable exists at FBdf5NXSL7R7YQK52j8sc4NeuJ2i9qjfYt4TyRdq9SR2 under the Game Program. Their 851 rule bytes matched exactly, but the Game-owned account is not supplied to the current mining transaction. Equal contents today do not make the accounts interchangeable.
The browser sends un-namespaced tag 8 directly to the standalone Chunk Program.
Derived from resource-drops-v2 plus GlobalConfig under the Chunk Program ID; owner and PDA are checked by the program.
The accepted mining instruction invokes namespace 1 of the unified Game Program to append Backpack records.
BOUNDED PDA DATA
Thirty-seven ordered rows encode twelve kinds of exploration extra
The account begins with NCKDRP02, version 2, its PDA bump, and a row count inside a 16-byte header. Every 23-byte row stores source block ID, drop block ID, base chance in basis points, signed altitude bounds, signed depth bounds, one-byte salt, and inclusive minimum and maximum volume. Validation rejects an empty or oversized table, a wrong exact length, forbidden air, water, or bedrock IDs, chance above 10,000, reversed ranges, zero minimum volume, and minimum volume above maximum.
The audited account contained 37 rows across 16 source block types and 12 extra types. Base chances ranged from 10 to 900 basis points and encoded volumes ranged from 4,000 to 1,627,120,000 cubic millimeters. Its rule-body SHA-256 was 5fc213f6ed94777fbc0aeaa99cbea53282743a03d8f27e7498de2b9ef6be55ca, exactly matching the current local encoder output.
- Lava, ice, toxic water, coral, dead coral, reed, vine, dry grass, dead bush, thorn, dead wood, and giant root are ResourceDropTable outputs.
- Cotton and the five color flowers belong to the separate SurfaceDecorationTable path, not this exploration-extra table.
- The v2 header has no revision or updated-slot field, so a historical version must be named by an observed slot plus its account or rule-body hash.
- A development-wallet signer can initialize each program-derived table only while its PDA is still an empty system account.
- The local JavaScript rule fixture is initialization and presentation input; after governance changes, public PDA bytes remain the runtime authority.
ORDERED COORDINATE HASHING
The same accepted inputs replay the same roll without a random oracle
Before reading an exploration row, the mining program validates the player session and accounts, derives the target chunk, checks foundation protection, recalculates the canonical block at the submitted coordinate, rejects a mismatched expected block, and rejects air, water, or bedrock. GlobalConfig is the PDA identity anchor here, while GlobalConfigView substitutes the Chunk Program's compiled canonical seed, height limits, and sea level for terrain evaluation.
The resolver computes altitude and generated depth once, then scans stored rows from index zero. Each eligible row hashes the canonical seed, integer x, y, z, and 700 plus its salt into a value from 0 through 9,999. A failed eligible roll continues; the first successful row returns one block ID and one volume. The transaction slot, blockhash, signer, wallet, and browser RNG are absent.
- Recalculate the source
Derive the canonical generated block from the integer coordinate and reject a client mismatch.
- Filter the row
Require the source block ID, altitude range, and generated-depth range to match.
- Compare the threshold
Hash the coordinate in the chance salt domain and compare its 0-to-9,999 roll with the player-weighted row threshold.
- Return the first winner
Use the volume salt domain for an inclusive size and stop scanning immediately.
PLAYER-SPECIFIC THRESHOLDS
Exploration doubles the row's own chance by level ten
Exploration has eleven cumulative XP thresholds from level 0 through 10: 0, 1,250, 4,961, 11,975, 22,994, 38,636, 59,462, 85,991, 118,707, 158,068, and 204,510. The program selects the greatest reached level, multiplies the row's base threshold by 100 plus ten times that level, divides by 100 with integer truncation, and caps the result at 10,000.
Every resolved ResourceDropTable extra adds one Exploration XP after the Backpack CPI returns, while every successful ordinary tag 8 mine adds one Precision Gathering XP. The Exploration increment checks extra_drop.is_some(), not whether the lossy secondary append had room. Mining order can therefore affect later coordinates: an earlier committed hit can cross a level threshold, raising the deterministic comparison threshold for a later transaction. If the strict base append or any later operation errors, Solana transaction atomicity rolls back both XP changes with the other writes.
The current 10-to-900 basis-point table range remains 10 to 900.
The current range becomes 20 to 1,800 basis points before the universal cap.
The program advances XP even when Backpack capacity prevents the extra record from being written.
STRICT BASE, LOSSY SECONDARIES
Confirmation proves the transaction, not that every produced secondary fit
The instruction first records the mined coordinate, then performs a strict Backpack CPI for the canonical base block. If that append can use neither compatible stack headroom nor a free record, the CPI errors and the entire transaction rolls back. Base volume comes from Precision Gathering: 1,000,000 cubic millimeters multiplied by ten plus ten times Precision level, then divided by 100, so level 0 stores 100,000 and level 10 stores 1,000,000. It next prepares up to two secondary records: a visible SurfaceDecorationTable drop first and the ResourceDropTable extra second. Decoration inherits gathered base volume; only the exploration extra uses the inclusive volume range in its own table row. The Backpack routine tries each present record in order, merges it when compatible headroom exists, opens a record when available, and independently skips it otherwise.
Before ordinary mining, Play calls the stack-aware capacity helper for one canonical base unit rather than merely checking for an empty slot. A full record table may therefore mine into matching base-stack headroom. If the base consumes the last free record, either secondary may still enter its own compatible stack. When both secondaries require the same last free record, decoration is attempted first and takes it; when decoration cannot fit but the later exploration extra has matching headroom, the extra can still be stored. The transaction can confirm and Exploration XP can increase even when the resolved extra itself was skipped.
After confirmation, Play retries the full Backpack PDA using successive waits of 0, 180, 500, and 1,200 milliseconds until its updated slot advances and at least the required base-count increment is visible. Ignoring RPC time, those cumulative attempts begin near 0, 180, 680, and 1,880 milliseconds. That full refresh reveals every secondary that actually fit. The local pending reward animation and resources-collected counter are based on planned base blocks, so they do not independently report the real exploration result.
- The Backpack program validates a ChunkBroken PDA signer, GlobalConfig, PlayerProfile ownership, the player owner, and a correctly derived Backpack PDA.
- The chain accepts a player-owned Backpack selected by the client; it does not compare that address with the Profile equipped-backpack pointer.
- A raw ResourceDropTable block record is not yet a forge material item. The current production path is raw Backpack resource, Smelting conversion, then material-aware Forging.
REACHABILITY AND SCHEMA LIMITS
Not every configured row is reachable through every mining action
Ordinary single-block mining passes both rule tables to tag 8. A normal multi-block natural tree instead selects the tree-fell plan and sends tag 9. That instruction has no ResourceDropTable account and never calls the exploration resolver; it records tree blocks and base tree rewards only, and it does not add Exploration XP. Five current rows involving trunk or pineTrunk to vine, dead wood, or giant root are therefore normally bypassed by natural-tree felling. An isolated trunk that falls back to tag 8 can still resolve them, and a separately mined leaves block can still resolve its vine row.
Tag 20 reads both rule tables for each of its one or two same-Chunk blocks, but a resolved ResourceDropTable extra becomes a candidate only when a second coordinate hash passes the 50 percent batch-extra threshold. Base and surface-decoration candidates independently use 35 and 25 percent thresholds. Precision Gathering gains one XP per submitted block; Exploration gains one XP only for each extra candidate that passes both the table resolver and the batch-extra threshold, even if lossy Backpack storage later omits it.
Tag 21 is narrower still. Every newly accepted coordinate can enter the 5 percent base-candidate test, but only the first two coordinates that pass a separate 1 percent secondary-proof test can reach table and decoration resolution. A resolved extra then needs the 50 percent extra threshold, a decoration needs 25 percent, and the combined base-first candidate list is truncated to 16 before lossy storage. Precision Gathering follows newly accepted coordinates. Exploration follows extra candidates created before final truncation and Backpack loss, not every table match that might have existed outside the two-proof budget.
Support collapse is also selective. Its primary block and only the capacity-selected reward blocks use reward-bearing tag 8; other confirmed collapse removals use tag 5 without ResourceDropTable evaluation. The rule table therefore applies per reward-bearing instruction, not automatically to every block removed by a larger local mining plan.
The current table's largest drop block ID is 45, which the present Backpack packing and Play decoder can represent. Table validation does not itself restrict a future Civilization patch to the browser's known render map or safe packed-ID range. A syntactically valid higher ID could become an on-chain slot that the current client decodes as unknown or omits from the visible Backpack.
Reads ResourceDropTable and SurfaceDecorationTable and can resolve one exploration extra.
Does not receive or resolve ResourceDropTable rows.
A table match still needs its path-specific candidate threshold.
Only a bounded subset can evaluate secondary rules in one range.
Safe for the current decoder; future governed IDs need an explicit cross-program and renderer compatibility rule.
MUTABILITY AND PROOF SCOPE
Civilization can replace bounded bytes, but the target program and PDA must be exact
The Chunk source exposes a Civilization adapter for ResourceDropTable replacement. It validates the existing program-owned PDA, the new 37-row payload, the target program and target PDA committed by the RuleBook, a threshold-met tally, an executed receipt, and the adapter authority. It then rewrites the same-sized table atomically. Because the account cannot be resized in this path, the replacement row count must equal the existing count.
The current civilization-resource-drops E2E script explicitly derives and updates the Game Program-owned FBdf5... table. Current Play mining reads the standalone Chunk-owned Hf3M... table instead. The script demonstrates a real adapter path for its chosen target, but it is not evidence that current mining rules changed. Its initialization fallback also forces the Civilization power authority as payer, while tag 7 requires the different GlobalConfig development wallet; that branch would fail if the shadow table did not already exist. A live governance proposal must bind to the Chunk Program and active PDA if it is meant to affect current mining.
At the audited slot, both deployed program ELF hashes matched the current local artifacts. Both programs also retained upgrade authority 9XuoVVwqP2jipt3jpJVXCSS2N2jr9vDuV3d6K73FKVud, so table governance is not the only mutability boundary. Program upgrades can change derivation, validation, hashing, reward ordering, or storage behavior.
- Re-derive the target PDA from seed, GlobalConfig, and the intended program ID.
- Read owner, magic, version, count, exact length, and rule-body hash from finalized RPC bytes.
- Decode every row and validate output IDs against the Backpack schema, Game dispatcher, and current Chunk.js render map before publishing a patch.
- Record both finalized slot and rule-body hash because the v2 ResourceDropTable header has no revision or updated-slot field.
- Test ordinary mining, near-full Backpack capacity, simultaneous decoration and extra hits, and the separate tree-fell path.
- After execution, re-read the active PDA and a real Backpack mutation instead of relying on the static resource atlas or a successful shadow-table receipt.
RECOMPUTABLE DROP MATH
Rebuild the result from bytes, coordinates, and player progress
These equations model the implemented resolver. They preserve integer arithmetic, ordered first-hit semantics, and the distinction between producing an extra and actually storing it.
Active PDA and bounded account length
P_drop = PDA(["resource-drops-v2", GlobalConfig], ChunkProgram); bytes(N) = 16 + 23N, 1 <= N <= 64The active table address is derived under the standalone Chunk Program ID. The audited table has N = 37, so its exact account length is 867 bytes.
- P_drop
- The ResourceDropTable account supplied to the current reward-bearing mining instruction.
- N
- The row count stored in byte 10 of the 16-byte header.
Spatial eligibility for one ordered row
a = y - seaLevel; d = surface(x,z) - y; eligible_i = (source = source_i) AND (a_min_i <= a <= a_max_i) AND (d_min_i <= d <= d_max_i)Altitude is relative to the canonical sea level and depth is relative to the generated surface above the coordinate. A row that fails any bound is skipped before its probability is tested.
- a
- Signed altitude above or below the program's canonical sea level.
- d
- Generated surface height minus the mined world Y coordinate.
- i
- The current row in stored table order.
Exploration level and effective threshold
L(xp) = max { k in [0,10] : xp >= T_k }; c_eff_i = min(10000, floor(c_i x (100 + 10L) / 100))The program maps Exploration XP through eleven cumulative thresholds. Each level adds ten percent of the base basis-point threshold; level 10 doubles it, subject to the 10,000 basis-point cap.
- T_k
- The cumulative Exploration XP threshold for level k.
- c_i
- The row's base chance in basis points.
- c_eff_i
- The integer threshold after the player's Exploration multiplier.
Coordinate roll and first-hit selection
r_i = H(seed,x,y,z,700 + salt_i) mod 10000; winner = first i where eligible_i AND r_i < c_eff_iEvery eligible row uses its own salt. A failed roll continues to the next row; the first passing row returns immediately, so overlapping row probabilities must not be added and table order is part of the rule.
- H
- The program's 32-bit seed-and-coordinate hash with fixed wrapping arithmetic.
- winner
- At most one ResourceDropTable extra returned for this mined block.
Deterministic extra volume
v = v_min + (H(seed,x,y,z,900 + salt_winner) mod (v_max - v_min + 1))A second salt domain selects an inclusive integer volume in cubic millimeters. Equal minimum and maximum values bypass the modulo and return that fixed volume.
- v
- The volume encoded into the extra Backpack block record.
- v_min, v_max
- The inclusive volume bounds stored in the winning 23-byte row.
Ordinary tag 8 produced extras versus stored extras
S0=strictStore(backpack,base); C=filter_present([decorationHit,extraHit]); for c_j in C: a_j=canStore(S_(j-1),c_j), S_j=a_j?store(S_(j-1),c_j):S_(j-1); secondaryWritten={c_j|a_j}; deltaXP_exploration=1 if transactionCommits AND extraHit else 0This compact model applies specifically to ordinary reward mining. After the strict base append, it removes absent candidates and attempts the visible decoration before the exploration extra. canStore is stack-aware: matching block ID, category, flags, and metadata may absorb a unit without a new record. A failed candidate is skipped independently rather than terminating the loop, so a later extra can still merge even when the earlier decoration cannot fit. XP tests the resolved extra rather than storage, but any later instruction error rolls the entire transaction back. Tags 20 and 21 use the separate bounded candidate rules described below.
- S_j
- The stack and record state after the first j present secondary candidates have been attempted.
- canStore(S,c)
- Whether candidate c can merge into a compatible block stack below quantity 99 or open one free active record in state S.
- filter_present
- Removal of any secondary type that did not resolve, before capacity is applied.
- extraHit
- The ResourceDropTable resolver returned an extra before the Backpack CPI.
The table format fixes header, row, count, and denominator bounds
Rustprograms/nicechunk_chunk/src/state.rspub const RESOURCE_DROP_TABLE_MAGIC: [u8; 8] = *b"NCKDRP02";
pub const RESOURCE_DROP_TABLE_VERSION: u8 = 2;
pub const RESOURCE_DROP_TABLE_SEED: &[u8] = b"resource-drops-v2";
pub const RESOURCE_DROP_TABLE_HEADER_LEN: usize = 16;
pub const RESOURCE_DROP_RULE_LEN: usize = 23;
pub const RESOURCE_DROP_RULE_MAX_COUNT: usize = 64;
pub const RESOURCE_DROP_CHANCE_DENOMINATOR: u32 = 10_000;
These constants make malformed magic, version, row count, and exact account length fail closed before any row is resolved.
The resolver filters spatial bounds, rolls each row, and returns the first hit
Rustprograms/nicechunk_chunk/src/state.rs let rule_count = ResourceDropTableState::validate_header(data)?;
let altitude = world_y.saturating_sub(global_config.sea_level);
let depth = surface.saturating_sub(world_y);
for index in 0..rule_count {
let offset = RESOURCE_DROP_TABLE_HEADER_LEN + index * RESOURCE_DROP_RULE_LEN;
let rule = ResourceDropRule::unpack(&data[offset..offset + RESOURCE_DROP_RULE_LEN])?;
if rule.source_block_id != source_block_id
|| altitude < rule.min_altitude
|| altitude > rule.max_altitude
|| depth < rule.min_depth
|| depth > rule.max_depth
{
continue;
}
let roll = hash_coord3(
&global_config.world_seed,
world_x,
world_y as i32,
world_z,
700_u32.saturating_add(rule.salt as u32),
) % RESOURCE_DROP_CHANCE_DENOMINATOR;
let chance_bps =
PlayerProgressState::exploration_chance_bps(rule.chance_bps, exploration_level);
if roll < chance_bps as u32 {
let span = rule.max_volume_mm3.saturating_sub(rule.min_volume_mm3);
let volume_mm3 = if span == 0 {
rule.min_volume_mm3
} else {
let volume_roll = hash_coord3(
&global_config.world_seed,
world_x,
world_y as i32,
world_z,
900_u32.saturating_add(rule.salt as u32),
) % span.saturating_add(1);
rule.min_volume_mm3.saturating_add(volume_roll)
};
return Ok(Some(ResourceExtraDrop {
block_id: rule.drop_block_id,
volume_mm3,
}));
}
}
Ok(None)
}
Stored rule order matters because the first successful row returns immediately. Exploration is a chain-owned skill level; no browser random value, slot, wallet, or signature enters the roll.
Exploration changes the threshold with integer arithmetic
Rustprograms/nicechunk_chunk/src/state.rs pub fn exploration_chance_bps(chance_bps: u16, exploration_level: u8) -> u16 {
let level = u32::from(exploration_level.min(10));
let weighted = (chance_bps as u32)
.saturating_mul(100_u32.saturating_add(level.saturating_mul(10)))
/ 100;
weighted.min(RESOURCE_DROP_CHANCE_DENOMINATOR) as u16
}
The chain level is clamped to ten. Each level multiplies the row's own threshold by ten percent; it does not add ten percentage points.
Decoration precedes exploration in the lossy secondary batch
Rustprograms/nicechunk_chunk/src/lib.rs let mut secondary_rewards = Vec::with_capacity(2);
// Visible surface decoration has priority over an invisible exploration
// bonus when only one slot remains after the mined block is stored.
if let Some(decoration) = surface_decoration_drop {
secondary_rewards.push(BackpackBlockReward {
world_x: args.world_x,
packed_y: pack_backpack_resource_y(
decoration.surface_y.saturating_add(1),
decoration.drop_block_id,
global_config_view.min_build_y,
),
world_z: args.world_z,
volume_mm3: gathered_volume_mm3,
metadata: pack_surface_decoration_metadata(
decoration.rule_id,
decoration.decoration_id,
),
});
}
if let Some(drop) = extra_drop {
secondary_rewards.push(BackpackBlockReward {
world_x: args.world_x,
packed_y: pack_backpack_resource_y(
args.world_y,
drop.block_id,
global_config_view.min_build_y,
),
world_z: args.world_z,
volume_mm3: drop.volume_mm3,
metadata: 0,
});
}
append_backpack_block_resources_lossy(
program_id,
backpack_program,
chunk_broken,
global_config,
player_profile,
backpack,
material_physics,
chunk_x,
chunk_z,
bump,
&secondary_rewards,
action_id,
)?;
This runs only after the required base append. The Backpack routine attempts every present candidate in order, merges compatible block stacks where possible, skips each candidate that cannot fit, and still returns success. Transaction confirmation therefore does not prove that the exploration row was stored.
The browser sends the Chunk-owned rule accounts to tag 8
JavaScriptsrc/chain/nicechunkChain.jsexport function createMineBlockWithRewardsInstruction({ authority, block, owner, backpack, actionId, expectedBlockId, context = gameContext }) {
if (!owner) throw new Error("owner is required for canonical mining");
if (!backpack) throw new Error("backpack is required for reward mining");
if (!Number.isInteger(expectedBlockId)) throw new Error("expectedBlockId is required for canonical mining");
const [chunkBrokenPda] = deriveChunkBrokenPdaForContext(blockChunkX(block.x), blockChunkZ(block.z), context);
const [foundationChunkPda] = deriveFoundationChunkPdaForContext(blockChunkX(block.x), blockChunkZ(block.z), context);
const [resourceDropTable] = deriveResourceDropTablePdaForContext(context);
const [surfaceDecorationTable] = deriveSurfaceDecorationTablePdaForContext(context);
const [playerProfile] = derivePlayerProfilePda(owner);
const [playerSession] = derivePlayerSessionPda(owner, authority);
const [playerProgress] = derivePlayerProgressPdaForContext(owner, context);
const [materialPhysics] = deriveMaterialPhysicsPda(context.backpackProgramId);
const [playerSkills] = derivePlayerSkillsPda(owner);
const normalizedActionId = normalizeMiningActionId(actionId);
const data = Buffer.alloc(21);
data.writeUInt8(8, 0);
data.writeBigUInt64LE(normalizedActionId, 1);
data.writeInt32LE(block.x, 9);
data.writeInt16LE(block.y, 13);
data.writeInt32LE(block.z, 15);
data.writeUInt16LE(expectedBlockId, 19);
return new TransactionInstruction({
programId: context.chunkProgramId,
keys: [
{ pubkey: authority, isSigner: true, isWritable: true },
{ pubkey: playerProfile, isSigner: false, isWritable: false },
{ pubkey: playerSession, isSigner: false, isWritable: false },
{ pubkey: playerProgress, isSigner: false, isWritable: true },
{ pubkey: chunkBrokenPda, isSigner: false, isWritable: true },
{ pubkey: foundationChunkPda, isSigner: false, isWritable: false },
{ pubkey: deriveGlobalConfigPda(), isSigner: false, isWritable: false },
{ pubkey: resourceDropTable, isSigner: false, isWritable: false },
{ pubkey: surfaceDecorationTable, isSigner: false, isWritable: false },
{ pubkey: context.backpackProgramId, isSigner: false, isWritable: false },
{ pubkey: backpack, isSigner: false, isWritable: true },
{ pubkey: materialPhysics, isSigner: false, isWritable: false },
{ pubkey: playerSkills, isSigner: false, isWritable: false },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
],
data: contextInstructionData(context, gameNamespaceChunk, data),
});
}
Rule PDAs remain anchored to Chunk. The accounts also include the Game-owned Backpack, material table, and read-only PlayerSkills PDA for current skill effects.
A Civilization replacement must preserve the existing row count
Rustprograms/nicechunk_chunk/src/lib.rs let rule_count = ResourceDropTableState::validate_payload(payload)?;
let update = CivilizationTableUpdateAccounts::parse(accounts)?;
require_key_eq(
update.table.owner,
program_id,
NicechunkChunkError::InvalidResourceDropTableData,
)?;
validate_global_config(update.global_config)?;
let bump = validate_rule_table_pda(
program_id,
update.table.key,
update.global_config.key,
RESOURCE_DROP_TABLE_SEED,
NicechunkChunkError::InvalidResourceDropTablePda,
)?;
{
let table_data = update.table.try_borrow_data()?;
let existing_count = ResourceDropTableState::validate_header(&table_data)?;
if existing_count != rule_count {
return Err(NicechunkChunkError::InvalidResourceDropTableData.into());
}
}
update.execute(program_id, payload)?;
let mut data = update.table.try_borrow_mut_data()?;
ResourceDropTableState::pack_payload(&mut data, bump, payload)
The adapter checks the program-owned PDA, validates a matching Civilization receipt flow, and rewrites the same-sized payload. It cannot resize a 37-row table to another count.
The current E2E script explicitly derives the Game Program shadow table
TypeScriptscripts/civilization-resource-drops-e2e.tsconst [globalConfig] = deriveGlobalConfigPda();
const [resourceDropTable] = deriveResourceDropTablePda({
globalConfig,
programId: NICECHUNK_GAME_PROGRAM_ID,
});
This address is not the Chunk-owned table passed by current Play mining. An executed receipt against this shadow PDA proves that adapter target only, not a live rule change for the standalone mining path.
IMPLEMENTATION EVIDENCE
Where these claims come from
Each claim is intentionally scoped to a concrete implementation path. These references are for verification, not decoration.
docs/audits/resource-drop-rules-devnet-2026-07-15.json
Records finalized Devnet account bytes, PDA derivations, owners, table hashes, active runtime mapping, deployed artifact parity, image metadata, and explicit scope notes.
docs/media/resource-drop-rules-overview-v1.webp
Provides the text-free villager quest scene using voxel strata, baked material language, and a calm translucent game-water plane.
public/mainnet.json
Declares the current Devnet cluster and split Chunk versus unified Backpack, Smelting, and Market program addresses.
programs/nicechunk_chunk/src/state.rs
Defines canonical world constants, the ResourceDropTable binary schema, row validation, Exploration thresholds, coordinate hashing, ordered resolution, and volume selection.
programs/nicechunk_chunk/src/lib.rs
Implements ordinary reward mining, tag 20 and tag 21 candidate gates, account and PDA checks, strict and lossy Backpack paths, path-specific Exploration XP updates, tree felling, table initialization, and Civilization replacement.
programs/nicechunk_chunk/src/errors.rs
Enumerates explicit invalid table PDA, invalid table data, rule authority, and mining validation errors.
programs/nicechunk_chunk/src/cluster_config.rs
Pins the Core, Player, Backpack/Game, Civilization, and other program identities trusted by the standalone Chunk Program.
programs/nicechunk_chunk/src/civilization_adapter.rs
Decodes Civilization RuleBook, tally, receipt, patch hash, target program, target PDA, status, and adapter-authority requirements.
programs/nicechunk_backpack/src/lib.rs
Validates Chunk reward authority and dispatches strict single-resource and lossy batch append instructions.
programs/nicechunk_backpack/src/state.rs
Implements stack-aware Backpack capacity checks, strict append failure, and ordered lossy candidate attempts that skip individual failures while continuing the batch.
programs/nicechunk_backpack/src/cluster_config.rs
Pins the standalone Chunk Program identity accepted as the mined-resource authority.
programs/nicechunk_game/src/lib.rs
Routes namespace 1 to Backpack logic and defines the unified Game Program dispatch boundary.
sdk/nicechunk-chunk.ts
Derives table PDAs, encodes 23-byte rows, builds initialization and mining instructions, and builds Civilization replacement payloads.
src/data/resourceDropRules.js
Defines the current 37-row local fixture, drop size profiles, source and output IDs, chance bounds, altitude, depth, salts, and encoded volumes.
src/world/blocks.js
Maps canonical block IDs to render and resource identities used by the local fixture.
src/chain/nicechunkChain.js
Defines the split game context, derives the active table, performs the limited readiness precheck, builds tag 8, signs mining, reads PlayerProgress, and decodes Backpack records.
src/rpcConfig.js
Defines the public Devnet RPC endpoint used by the browser when no private override is configured.
play/mining-controller.js
Creates local pending base-reward groups after physical tool contact without attempting to resolve the authoritative extra table.
play/play-chain-adapter.js
Selects ordinary mining, tree felling, or support collapse and delegates the signed transaction to the chain module.
play/tree-mining-plan.js
Selects the multi-block natural-tree path that routes trunk mining away from ordinary tag 8.
play/play-chain-session.js
Confirms local deltas only after the chain adapter succeeds and creates animations from local planned reward groups.
play/play-chain-backpack.js
Retries full Backpack reads after mutations and converts only recognized, decodable chain slots into visible Play inventory entries.
play/main.js
Requests the post-confirmation Backpack refresh using an advanced updated slot and a minimum base-count increment.
play/game-state.js
Treats merged chain Backpack slots as authoritative and disables local mining-resource insertion.
play/play-surface-decoration-sync.js
Separately reads and resolves the active SurfaceDecorationTable used for cotton, flowers, and visible surface identity.
resource_rule/resource_rule.js
Builds the public resource atlas from local fixtures, illustrating why that presentation is not a replacement for live PDA reads.
scripts/civilization-resource-drops-e2e.ts
Exercises a real Civilization receipt flow but explicitly targets the Game Program-owned ResourceDropTable rather than the active standalone Chunk table.
tests/nicechunk_player_chunk.ts
Tests 37-row PDA derivation, encoding, initialization, and Civilization replacement instruction shape; ordered first-hit behavior is established by the Rust resolver source.
docs/audits/global-config-genesis-devnet-2026-07-15.json
Records the current GlobalConfig development wallet used to distinguish table initialization authority from the Civilization power authority.
scripts/update-locales.mjs
Contains the sole editable non-English locale dictionary source used to generate page-specific documentation locale files.
scripts/check-docs-i18n.mjs
Checks English-only sources, page-specific locale generation, exact verbatim snippets, referenced evidence, raster media, and absence of image captions.
forging/chain-adapter.js
Reads the equipped Backpack but exposes only material-category item slots to the forging transaction path.
src/data/smeltingRules.js
Defines the conversion layer from raw resource identities into material items consumed by later crafting workflows.
target/deploy/nicechunk_chunk.so
Matches the 214,816-byte ELF hash recovered from the finalized Chunk ProgramData account.
target/deploy/nicechunk_game.so
Matches the 396,592-byte ELF hash recovered from the finalized unified Game ProgramData account.
