Files
brass-and-sigil/docs/bnstoolkit-architecture.md
T
Matt 25107efcf1 docs: bnstoolkit architecture + detailed perk specifications
New companion-mod design doc covering:

Architecture
- Purpose & scope (what's in the mod vs what stays in KubeJS)
- High-level diagram showing client/server/KubeJS/FTB-stack roles
- Full Java package layout under uk.sijbers.bnstoolkit
- Six GUI screens specified individually with layouts + network calls
  (Quest Log, Bounty Board, Tier Upgrade, Plot Purchase, Shop Browser,
   Quest Progress HUD)
- Three mixin targets into FTB Chunks' ChunkScreenPanel (drawBackground,
  ChunkButton.addMouseOverText, ChunkButton.onClicked) -- no FTB fork
- Network packet contract (7 S2C + 5 C2S packets, versioned)
- Data persistence model (SavedData for plots + sethomes, in-memory
  for death locations, KubeJS for quest state)
- Two config files documented (tiers.json + plots.json) with example
  JSON5 schemas
- KubeJS integration surface (8 /bnstoolkit_internal commands)
- Build & release setup (separate Gitea repo, standard NeoForge
  ModDevGradle, semver)
- 6 mod implementation phases (M0-M6), each independently shippable

Detailed perk specifications
- Wilderness chunks: FTB Ranks permission node, native FTB Chunks
  enforcement, no mod-side work
- Plot slots: SavedData-backed ownership tracking, 50% refund on
  release
- Sethomes: full sethome system built in bnstoolkit (no other sethome
  mod exists in pack). Per-tier cap, 30s cooldown, /sethome /home
  /delhome /listhomes commands
- Daily bounty slots: enforced in KubeJS engine, UI greys Accept when
  at cap
- Shop fee discount: base 25% Bazaar fee reduced by tier discount.
  Only applies to NPC Bazaar shop, not player-to-player Numismatics.
  Worked example showing -25% Sovereign = 0% fee = full 10 spurs/diamond
- Chat colour: full colour ladder per tier (grey to rainbow at
  Sovereign with character-by-character cycling)
- Join broadcast: 6 levels documented (none, simple, fancy, epic,
  epic+particles, epic+spectacular) with example ASCII
- /back after death: in-memory storage, 60s cooldown, dimension-aware
- Future perk dimensions: 7 candidates the schema supports without
  code changes (particle trails, custom join sounds, custom title
  prefix, priority bounty access, tier-gated vendors, daily login
  bonus, keep-inventory chance)

Six open implementation questions flagged for resolution during
build, none blocking.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:09:34 +00:00

28 KiB

bnstoolkit — Architecture & Perk Specification

Status: design draft (v0.1). Not yet implemented. Owner: matt Last updated: 2026-06-06

bnstoolkit is the custom companion mod for the Brass and Sigil economy system. It provides the UI layer (GUI screens, HUD), the FTB Chunks map mixins for spawn plot integration, and the data models the economy needs. All gameplay logic (bounty rotation, state machine, villager trades, Numismatics integration, etc.) lives in KubeJS and is called into by the mod via network packets.

This doc is the source of truth for the mod design. It must be reviewed before any Java is written.

See also: economy-system.md for the gameplay side of the design.


1. Purpose & scope

In scope

  • GUI screens built on FTB Library's UI framework (matches FTB Quests / FTB Chunks visual language)
  • Mixins into FTB Chunks' map UI for spawn-plot cost overlay, hover tooltips, and click-to-purchase popups
  • Custom HUD render layer for quest progress (replaces stacked vanilla bossbars)
  • Data persistence for plot ownership (server-side, saved with world)
  • Sethome system (/sethome, /home, /delhome, /listhomes) since the pack has no other sethome mod
  • Network packets for client↔server state sync
  • Admin commands: /bnstoolkit reload, debugging commands
  • Config-driven tier perks (tiers.json) and plot definitions (plots.json)

Out of scope

  • Bounty quest engine (lives in KubeJS)
  • Villager trade rebalance (lives in KubeJS)
  • Numismatics direct integration (lives in KubeJS — mod calls KubeJS commands to debit/credit)
  • FTB Quests integration (FTB Quests handles its own UI for the progression campaign)
  • FTB Ranks admin (FTB Ranks handles permissions directly; mod just reads them)

2. High-level architecture

                 ┌──────────────────────┐
                 │   Player (client)    │
                 └──────────┬───────────┘
                            │ keybind / NPC click / chunk click
                            ▼
            ┌───────────────────────────────────┐
            │       bnstoolkit (client)          │
            │   • FTB Library UI screens         │
            │   • FTB Chunks map mixin           │
            │   • Quest progress HUD             │
            └───────────────┬───────────────────┘
                            │ network packets
                            ▼
            ┌───────────────────────────────────┐
            │       bnstoolkit (server)          │
            │   • Plot ownership data            │
            │   • Sethome data                   │
            │   • Network packet handlers        │
            │   • /bnstoolkit reload command     │
            └─────┬───────────────────────┬─────┘
                  │                       │
       reads      │                       │ calls KubeJS commands /
   FTB Ranks /    │                       │ fires events for KubeJS
   FTB Chunks /   │                       │ to react to
   Numismatics    ▼                       ▼
            ┌───────────────┐    ┌──────────────────────┐
            │ FTB / NeoForge │    │     KubeJS scripts   │
            │     stack      │    │ • Bounty engine      │
            └───────────────┘    │ • Quest state         │
                                  │ • Numismatics calls   │
                                  │ • Villager trades    │
                                  │ • Tier promotion     │
                                  └──────────────────────┘

Key invariant: the mod owns UI + plot data + sethomes. KubeJS owns gameplay logic. They communicate via network packets and KubeJS commands. The mod never directly mutates Numismatics balances or quest state — it asks KubeJS to do that via commands.


3. Package layout

bnstoolkit/
├── build.gradle                       NeoForge 1.21.1 + FTB Library dep
├── src/main/java/uk/sijbers/bnstoolkit/
│   ├── BnsToolkit.java                Mod entry, lifecycle
│   ├── client/
│   │   ├── ClientEvents.java          Keybinds, client setup
│   │   ├── screen/
│   │   │   ├── QuestLogScreen.java
│   │   │   ├── BountyBoardScreen.java
│   │   │   ├── TierUpgradeScreen.java
│   │   │   ├── PlotPurchaseScreen.java
│   │   │   ├── ShopBrowserScreen.java
│   │   │   └── widgets/               (subclass FTB Library widgets)
│   │   ├── hud/
│   │   │   └── QuestProgressHud.java  IGuiOverlay
│   │   └── mixin/
│   │       ├── ChunkScreenPanelMixin.java
│   │       └── ChunkButtonMixin.java
│   ├── server/
│   │   ├── command/
│   │   │   ├── BnsToolkitCommand.java   /bnstoolkit reload, debug
│   │   │   ├── SethomeCommand.java      /sethome, /home, etc.
│   │   │   └── BackCommand.java         /back
│   │   ├── data/
│   │   │   ├── PlotRegistry.java        loads plots.json
│   │   │   ├── PlotOwnership.java       SavedData, plot owner UUIDs
│   │   │   ├── SethomeData.java         SavedData, per-player homes
│   │   │   └── DeathLocations.java      transient, /back support
│   │   ├── event/
│   │   │   ├── PlayerJoinHandler.java   tier-based join broadcast
│   │   │   ├── PlayerDeathHandler.java  remember death location for /back
│   │   │   └── ChatColourHandler.java   tier-based chat name colouring
│   │   └── net/
│   │       └── (packet implementations — see §6)
│   ├── common/
│   │   ├── data/
│   │   │   ├── TierConfig.java          loads tiers.json
│   │   │   ├── BountyDef.java           DTO mirrored from KubeJS
│   │   │   ├── QuestStateView.java      snapshot for UI display
│   │   │   └── PlotDef.java             plot definition (region, price)
│   │   └── net/
│   │       └── BnsPacket.java           network channel + payload base
│   └── resources/
│       ├── META-INF/neoforge.mods.toml
│       ├── bnstoolkit.mixins.json
│       └── assets/bnstoolkit/lang/en_us.json
└── src/main/resources/
    └── data-config/                     packed defaults, copied on first run
        ├── tiers.json
        └── plots.json

4. Screen specifications

All screens extend FTB Library's BaseScreen. They share a common header (player name, current tier, spur balance) so navigation feels consistent.

4.1 Quest Log

Opened by: keybind (default Q+B?) or right-clicking a Quest Log block placed at any guild building.

Layout: three tabs across the top — Active / Available / Completed.

  • Active tab: list of currently-accepted bounties with progress bars. Each row clickable; click expands a detail panel with description, source guild, reward, and a Cancel quest button. Cancel triggers a confirmation modal warning about cooldown.
  • Available tab: list of bounties currently offered (rotated daily by the KubeJS engine). Each row shows the bounty source, reward, cooldown remaining (if any). Click → detail panel with Accept button.
  • Completed tab: historical log of completed bounties this week, for satisfaction value. No interaction beyond viewing.

Network calls:

  • On open: client requests current quest state from server (S2CQuestSnapshot)
  • On accept/cancel click: C2SAcceptBounty(id) / C2SCancelQuest(id)

4.2 Bounty Board

Opened by: right-clicking the Adventurer's Guild Quartermaster NPC (Easy NPC dialog action runs /bnstoolkit openboard adventurers_guild) OR clicking an in-world bnstoolkit:bounty_board block.

Layout: poster-board style — the day's available bounties as visual "cards" laid out in a grid, each with mob icon, name, description, reward, accept button. Friendly to non-tech users.

Network calls:

  • On open: S2CBountyBoardSnapshot(guild_id) returns today's bounty list
  • On accept: same C2SAcceptBounty(id) as Quest Log

4.3 Tier Upgrade Screen

Opened by: right-clicking the Civic Office Magistrate NPC.

Layout: full ladder shown as a vertical or horizontal track. Your current tier highlighted (glowing badge). Next tier shows cost + delta perks (e.g. "+50 chunks, +1 plot slot, +2 sethomes, +1 bounty, -2% shop fee, chat colour: yellow"). Big Upgrade to <Tier> button at the bottom, greyed out if you don't have the spurs.

Hovering any future tier shows its full perk list in a side panel.

Network calls:

  • On open: S2CTierSnapshot returns current tier + balance
  • On upgrade click: C2SRequestTierUpgrade → server verifies balance, calls KubeJS /bnstoolkit_internal upgrade_rank <uuid> which charges spurs and runs ftbranks add <player> <tier>

4.4 Plot Purchase Popup

Opened by: clicking an unowned plot region in the FTB Chunks map UI (via the mod's mixin into ChunkScreenPanel).

Layout: modal overlay on top of the FTB Chunks map. Shows: plot ID, plot type (standard/premium), region size in chunks, owner (none), price. Your current spur balance. Your remaining plot slots (e.g. "2 of 3 used"). Purchase and Cancel buttons. If you're at your slot cap or don't have enough spurs, Purchase is greyed out with the reason shown.

Network calls:

  • On purchase: C2SBuyPlot(plot_id) → server checks slot capacity, asks KubeJS to charge spurs, on success records ownership in PlotOwnership SavedData.

4.5 Shop Browser

Opened by: right-clicking the Bazaar Master NPC at the Merchant's Bazaar (provides a curated view of all currently-listed shop blocks

  • NPC sell shop).

Layout: searchable item list with current prices, sort by category. Click an item to see who's selling it / where the shop block is located. The NPC sell shop (diamonds, netherite etc.) shows as a special "Official Bazaar" category with fixed prices and the current diminishing-return multiplier per item.

Note: individual Numismatics shop blocks keep their native UI when right-clicked — this Bazaar Master is the curated central view, not a replacement for shop block interaction.

Network calls:

  • On open: S2CShopBrowserSnapshot (asks KubeJS for current listings)
  • Selecting an item → S2CShopItemDetail(item_id) for full info

4.6 Quest Progress HUD

Render layer: IGuiOverlay, drawn over the vanilla HUD.

Layout: small panel in top-right (configurable position) showing each active quest as a row — quest name + progress bar + N/M numeric. Fades on inactive (no progress in last 30s) so it doesn't visually clutter when you're not actively bounty-hunting. Re-appears the moment any quest progresses.

State source: KubeJS pushes updates via S2CHudQuestUpdate packet when any quest's progress changes (debounced to once per second maximum per quest). The HUD reads from a client-side cache.


5. Mixin targets

Minimal — we don't fork FTB Chunks, we inject only what we need.

Target Method Purpose Mixin file
ChunkScreenPanel drawBackground (TAIL) Overlay drawing — cost preview for the currently-hovered or selected chunk, "Your plot slots: N of M" text in a corner ChunkScreenPanelMixin.java
ChunkScreenPanel$ChunkButton addMouseOverText (TAIL) Append "Cost: N spurs" or "Plot: " to the per-chunk hover tooltip ChunkButtonMixin.java
ChunkScreenPanel$ChunkButton onClicked (HEAD, with cancellation if applicable) If the clicked chunk is a plot region, open PlotPurchaseScreen instead of triggering a regular claim ChunkButtonMixin.java

That's it. Three injection points across two mixin files. No modification of FTB Library, FTB Quests, FTB Ranks, or FTB Teams.


6. Network packet contract

NeoForge PayloadRegistrar. All packets versioned via a single PROTOCOL_VERSION constant; bump on schema change.

Server → Client

Packet Payload When sent
S2CQuestSnapshot List<QuestStateView> On Quest Log open, on any quest-state change
S2CBountyBoardSnapshot List<BountyDef> (5-10 entries) On Bounty Board open
S2CTierSnapshot (currentTier, balance, perksByTier) On Tier Upgrade Screen open
S2CShopBrowserSnapshot List<ShopListing> On Shop Browser open
S2CHudQuestUpdate (questId, progress, target) On quest progress (debounced 1s)
S2CPlotPurchaseResult (success, message) After C2SBuyPlot resolves
S2CTierUpgradeResult (success, message) After C2SRequestTierUpgrade resolves

Client → Server

Packet Payload What server does
C2SAcceptBounty questId Call /bnstoolkit_internal accept_bounty <uuid> <questId> (KubeJS)
C2SCancelQuest questId Call /bnstoolkit_internal cancel_quest <uuid> <questId> (KubeJS)
C2SBuyPlot plotId Verify slot capacity, ask KubeJS to debit spurs, record ownership
C2SRequestTierUpgrade (none — server knows player) Verify balance, ask KubeJS to debit + promote
C2SOpenBoard guildId (optional context) Reply with appropriate snapshot

All C2S packets include the player implicitly (NeoForge passes the ServerPlayer in the handler).


7. Data persistence

Data Storage Lifetime
Plot ownership bnstoolkit:plots — vanilla NeoForge SavedData attached to overworld Persists with world. Authoritative source.
Sethomes bnstoolkit:sethomes — per-player attached data Persists with world
Death locations (for /back) In-memory only, evicted after teleport or on logout Transient
Quest state KubeJS-managed JSON at world/data/bns_economy/quests/<uuid>.json Not the mod's concern — the mod only reads via packets
Tier configuration config/bnstoolkit/tiers.json (hot-reloadable) Until edited
Plot definitions config/bnstoolkit/plots.json (hot-reloadable via /bnstoolkit reload) Until edited

Plot ownership and sethomes are server-authoritative. Clients only get views via packets — they never write to these stores directly.


8. Configuration files

config/bnstoolkit/tiers.json

Defines the 13-tier ladder. Hot-reloadable.

{
  "tiers": [
    {
      "id": "peasant",
      "displayName": "Peasant",
      "cost": 0,
      "perks": {
        "wildernessChunks": 9,
        "plotSlots": 0,
        "sethomes": 1,
        "dailyBountySlots": 3,
        "shopFeeDiscount": 0,
        "chatColour": "grey",
        "joinBroadcast": "none",
        "backAfterDeath": false
      }
    },
    /* ... 12 more tiers ... */
  ]
}

config/bnstoolkit/plots.json

Defines spawn plot regions. Each plot has a unique ID, region bounds (chunk coordinates), type (standard/premium), and price.

{
  "plots": [
    {
      "id": "bazaar_stall_01",
      "displayName": "Bazaar Stall 1",
      "type": "standard",
      "price": 2000,
      "chunks": [[10, 20], [10, 21]],   // chunk coords, inclusive
      "world": "minecraft:overworld"
    },
    {
      "id": "bazaar_corner_premium",
      "displayName": "Premium Corner Plot",
      "type": "premium",
      "price": 5000,
      "chunks": [[15, 25], [15, 26], [16, 25], [16, 26]],
      "world": "minecraft:overworld"
    }
  ]
}

9. KubeJS integration surface

The mod calls into KubeJS via custom commands registered by KubeJS (ServerEvents.commandRegistry). All have the bnstoolkit_internal prefix to mark them as not-for-player-use:

Command Purpose
/bnstoolkit_internal accept_bounty <uuid> <questId> Mark quest as ACTIVE in KubeJS state
/bnstoolkit_internal cancel_quest <uuid> <questId> Cancel quest, apply cooldown
/bnstoolkit_internal complete_quest <uuid> <questId> Mark quest READY (for testing/manual)
/bnstoolkit_internal turn_in_quest <uuid> <questId> Pay reward via Numismatics
/bnstoolkit_internal debit <uuid> <amount> <reason> Charge spurs (used by plot purchase, tier upgrade)
/bnstoolkit_internal credit <uuid> <amount> <reason> Pay spurs
/bnstoolkit_internal upgrade_rank <uuid> <tierId> Promote via FTB Ranks
/bnstoolkit_internal get_balance <uuid> Returns current spur balance (used for screen header)

All commands return a JSON result via the command output that the mod parses. KubeJS handles the actual Numismatics + FTB Ranks calls (it already has the Java.loadClass helpers from the economy KubeJS scripts).

KubeJS in turn pushes events to the mod via custom payload packets when quest state changes (so the HUD can update without polling).


10. Build & release

  • Repo: new private Gitea repo minecraft/bnstoolkit (separate from the modpack repo for clean release-versioning, but mirrored to the modpack's pack/overrides/mods/ on each release)
  • Build: standard NeoForge 1.21.1 ModDevGradle template
  • Dependencies: Architectury API (provided), FTB Library (provided), Numismatics (compileOnly), FTB Chunks (compileOnly)
  • CI: Gitea Actions runs ./gradlew build on push to main, uploads the jar as a release artifact
  • Modpack integration: the modpack's bump-version flow includes pulling the latest bnstoolkit release jar and updating pack.lock.json / manifest like any other mod
  • Versioning: semantic — 1.0.0 for V1 ship, 1.x.y for patches, 2.0.0 if we ever change the network protocol or data format

11. Perk specifications (detailed)

Every perk listed in the 13-tier ladder, expanded with mechanics, implementation, and edge cases.

11.1 Wilderness chunks

What it does: caps how many wilderness chunks (outside spawn) a player can claim via the FTB Chunks map. Claiming within the cap is free; over the cap is refused with an in-game message.

Implementation: FTB Ranks permission node ftbchunks.max_claimed_chunks set per rank in the FTB Ranks config (written by the mod on first launch from tiers.json). FTB Chunks reads this permission natively — no mod-side enforcement needed.

Edge case: if a player downgrades (which they can't normally, but might happen via op command), they keep already-claimed chunks over the new cap, but can't claim more until they free some.

11.2 Plot slots

What it does: caps how many spawn plots (predefined regions at spawn, see plots.json) a player can own concurrently. Independent of wilderness chunks.

Implementation: stored in PlotOwnership SavedData. On purchase, mod checks playerOwnedPlots.size() < tier.plotSlots. If at cap, the Plot Purchase Popup shows the slot count and disables the Purchase button.

Releasing a plot: players can sell their plot back via a "Release" button in the plot-detail screen (opens when they click their own plot in the map). Releases the slot. Refund: 50% of purchase price.

11.3 Sethomes

What it does: how many /sethome <name> locations a player can save. /home <name> teleports there; /listhomes lists; /delhome <name> removes.

Implementation: the pack currently has no sethome mod. We build it in bnstoolkit:

  • /sethome <name> saves current player position + world + name
  • /home <name> teleports (validates dimension load)
  • /listhomes shows owned homes
  • /delhome <name> removes
  • Cap enforced from the player's tier (tiers.jsonsethomes)
  • Unlimited = represented as -1 in the JSON

Cooldown: 30-second cooldown between teleports to prevent combat-evasion. Configurable in tiers.json per-tier (low tiers have longer cooldown).

Edge case: moving a sethome out of a now-claimed plot or a private base is allowed — sethomes are positional, not contextual.

11.4 Daily bounty slots

What it does: how many bounties a player can have ACTIVE simultaneously. Once the slot is freed (by completion or cancel), the player can accept another from any guild board.

Implementation: enforced in KubeJS bounty engine. The mod's Bounty Board and Quest Log screens read the slot count via packet and grey out the Accept button when at cap.

Edge case: a quest in READY state still counts against your active slots until you turn it in. This is intentional — pushes players to actually visit the NPC to claim.

11.5 Shop fee discount

What it does: reduces the "merchant cut" deducted when you sell items at the Bazaar's NPC sell shop. The Bazaar charges a base 25% fee on all sales; your tier provides a discount that reduces this toward zero.

Worked example: you sell a diamond worth 10 spurs at the Bazaar.

  • Peasant (0% discount): 25% fee → you receive 7.5 spurs (rounded down to 7).
  • Knight (-5% discount): 20% fee → 8 spurs.
  • Sovereign (-25% discount): 0% fee → full 10 spurs.

Implementation: KubeJS sell-shop handler reads the seller's tier and computes effective payout. Rounded down to nearest integer.

Edge case: player-to-player Numismatics shop blocks do NOT apply this fee — those are direct peer transactions, no Bazaar middleman. The fee only applies to the official Bazaar sell shop.

11.6 Chat colour

What it does: the player's name in chat appears in this colour, visible to everyone. Visual rank marker.

Implementation: KubeJS PlayerEvents.chat event modifies the chat component for the player's display name based on their tier permission (read from FTB Ranks). The mod also colours the player's nameplate above their head (via a small client packet on tier change that other clients use to set the display name colour locally).

Colour ladder:

  • 1-2 Peasant/Farmer: grey
  • 3 Citizen: white
  • 4 Merchant: yellow
  • 5 Knight: green
  • 6 Baron: cyan
  • 7 Viscount: blue
  • 8 Earl: purple
  • 9 Marquess: gold
  • 10 Duke: orange
  • 11 Archduke: red
  • 12 Grand Duke: bright red
  • 13 Sovereign: rainbow (animated via colour-cycling text component)

Edge case: the Founder cosmetic [Founder] prefix sits before the coloured name, in a distinct colour (probably bright yellow or white-bold). Sovereign + Founder is visually busy but acceptable — only one player on the server will have both.

11.7 Join broadcast

What it does: when the player logs in, this controls what message goes to everyone else on the server.

Levels:

  • none: standard vanilla <player> joined the game.
  • simple: rank-prefixed message in their chat colour. Example:
    [Knight] Matt has logged in.
    
  • fancy: multi-line, with a separator. Example:
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
     [Viscount] Matt has arrived
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
  • epic: multi-line, with a sound effect (e.g. trumpet fanfare, configurable per-tier). Larger ASCII separator. Possibly an ASCII art banner of the rank.
  • epic + particles: as epic, plus a 5-second particle effect at the player's spawn location (firework spark, end-rod sparkle, etc.) for everyone nearby to see.
  • epic + spectacular: as epic + particles, plus a server-wide effect — actionbar message visible to everyone, brief light-up of the sky if Sovereign joins.

Implementation: KubeJS PlayerEvents.loggedIn reads tier and dispatches the appropriate message. Particle/sound effects are server-side commands (/particle, /playsound).

11.8 /back after death

What it does: the /back command teleports the player to where they last died. Tiers without this perk get "You don't have access to /back yet" if they try.

Implementation: mod listens to LivingDeathEvent for players, stores (world, x, y, z, timestamp) in DeathLocations (in-memory only, evicted on logout or after /back use). /back command verifies tier perm + reads the entry.

Cooldown: 60 seconds. Prevents combat reinsertion.

Edge case: dying again clears the previous death location. You only get one /back per death. Logging out clears it too — intentional, to prevent abuse.

11.9 Future perk dimensions (not in V1, but easy to add later)

Architecture supports adding new perk columns in tiers.json without code changes (the schema is open-ended). Candidates for later expansion:

  • Particle trail — high tiers leave a visible particle wake when walking
  • Custom join sound — different sound effect per tier on login
  • Custom title prefix — text added before chat name beyond the colour (e.g. ⚔ Knight Matt)
  • Priority bounty access — higher tiers see a larger pool of daily bounties to pick from
  • Tier-gated vendor stock — specific Numismatics shops only visible to Baron+ etc.
  • Daily login bonus — small spur reward for logging in, scaling by tier
  • Death keep-inventory chance — RNG % to keep inventory on death (controversial, gate carefully)

12. Open implementation questions

These can be deferred until they become blocking, but worth flagging:

  1. Sovereign tier rainbow chat name — Minecraft text components don't natively support gradient text. Implementation options: (a) cycle through colours character by character, or (b) animate via packet on a tick interval. Choose during Phase 0c scaffolding.
  2. Plot release refund percentage — proposed 50%. Tune via playtest.
  3. Sethome cooldown values per tier — proposed scaling from 60s (low tiers) to 5s (Sovereign). Confirm in tiers.json schema.
  4. /back interaction with dimension changes — does dying in the End and /backing return you to the End or to overworld? Default: returns to wherever you died including the dimension.
  5. Founder cosmetic prefix colour — bright yellow? Bold white? Animated? Settle during implementation.
  6. Sovereign spectacular join effect — exact effects need design pass (sky flash? Server-wide actionbar text?). Tune in tiers.json.

13. Implementation phases (mod-specific)

Aligned with the economy doc's Phase 0c (mod scaffolding):

Mod phase Deliverable
M0 Gradle project, mod metadata, FTB Library dep wired, network channel registered, empty placeholder for each screen class. Builds + loads cleanly into the running pack.
M1 Tier system: TierConfig loads from tiers.json, TierUpgradeScreen works, perks applied via FTB Ranks promotion command. Founder cosmetic prefix. Chat colour. Join broadcast at all tiers.
M2 Sethome system: /sethome, /home, /delhome, /listhomes, /back. SavedData persistence. Per-tier cap enforcement.
M3 Plot system: PlotRegistry + PlotOwnership, FTB Chunks mixins, PlotPurchaseScreen. KubeJS integration for spur debit.
M4 Quest UI: QuestLogScreen, BountyBoardScreen, QuestProgressHud. Network packets between KubeJS bounty engine and the mod.
M5 Shop browser: ShopBrowserScreen.
M6 Polish — animations, sound effects, particle effects for high tiers, theming pass on all screens.

Each phase is independently shippable as a 1.x.0 release of the mod jar.


See also

  • economy-system.md — gameplay-side design (currency, quest mechanics, villager rebalance, etc.)
  • MEMORY.md entries — KubeJS Rhino gotchas, defaultconfigs pattern