Files
brass-and-sigil/docs/economy-system.md
Matt 9eb8f540c4 pack: v0.32.0 — FTB Quests + XMod Compat + Ranks; restrictive travel design
Mods added (Phase 0a substrate for the bnstoolkit economy work):
  - FTB Quests 2101.1.25 (progression quest UI for Phase 5+)
  - FTB XMod Compat 21.1.8 (KubeJS hooks for FTB Chunks/Quests events)
  - FTB Ranks 2101.1.3 (tier system via permission nodes)

Design revision: restrictive travel.

This is a Create Aeronautics pack — the journey is the point. Removed
all instant-teleport perks from the tier ladder. Players get one
starter Waystone and use it for spawn↔base; further travel means
building airships, trains, vehicles. Pressure on real movement is
intentional.

Removed perks: sethomes, /back after death.
Removed system: the full sethome subsystem (commands, SavedData,
cooldowns) from the bnstoolkit mod scope.

Tier table reduced from 10 columns to 8: cost, wilderness chunks,
plot slots, daily bounties, shop fee, chat colour, join broadcast.

Mod phasing collapsed from 7 phases to 6 (M2 sethome system removed,
later phases shift up).

Future perk dimensions list updated with two waystone-related
candidates (slot cap, XP cost reduction) as the natural travel-
progression hooks for later tier-perk revisions.

Verified live: all 3 mods discovered + loaded, port 25565 binds,
no FATAL/Crashed/Exception lines in startup log. Server resumed
to 0.32.0 cleanly.

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

518 lines
31 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Brass and Sigil — Economy & Quest System Design
> Status: 13-tier ladder locked (v0.4). Architecture + UI confirmed in v0.3.
> Owner: matt
> Last updated: 2026-06-06
---
## 1. Goals
- **One unified currency** — spurs (Numismatics).
- **Multiple ways to earn, each one bounded.** No infinite money printer.
- **Multiple sinks that scale with progression.** Money disappears as you advance, so wealth never dwarfs the cost of new ambitions.
- **Spatial design that gives spawn personality.** Themed guild buildings, each with a clear purpose, each tied to the same wallet.
- **Forward-compat with a proper quest line** via FTB Quests, while supporting daily/repeatable activities at spawn.
- **Anti-automation by design**, not by patches.
---
## 2. Core architecture
```
┌────── MONEY IN (bounded) ──────┐
│ │
Adventurer's Guild — Daily bounties (cooldowns, scaling)
Merchant's Bazaar — Sell shop (fixed + DR), dynamic exchange
Mint — Capped emerald → spur conversion *
First-time milestones — One-shot per player
FTB Quests — Progression milestone payouts
┌───────────────────┐
│ Player wallet │ ← Numismatics
│ (spurs) │
└───────────────────┘
┌────── MONEY OUT (scaling) ──────┐
│ │
Civic Office — Plot claim costs (FTB Chunks override)
Civic Office — Tier upgrades (FTB Ranks integration)
Merchant's Bazaar — Player-to-player job board (no minting)
Villagers — Re-priced trades, net sink
Custom services — Warps, sethomes, premium cosmetics
```
\* Only if we keep emeralds; see §5 — we're moving villagers to spurs, which probably retires the Mint as a currency-conversion station and repurposes it as a wallet/info hub.
---
## 3. Spawn — themed guild buildings
Each guild is a destination. The guild's NPC is both the **entry point** (accept work) and **exit point** (return to claim reward). This pattern applies universally — see §4.
| Building | Purpose | Primary mechanics inside |
|---|---|---|
| **Adventurer's Guild** | Combat & exploration | Bounty board (daily mob hunts), boss-kill quests, dungeon-delve quests (future) |
| **Merchant's Bazaar** | Trade & raw-mat economy | Numismatics sell shop, dynamic exchange counter, player-driven job board |
| **Civic Office** | Land & status | Tier upgrade screen, spawn plot registry (purchase / view your plots), sethome/warp services. NOTE: regular wilderness chunk claiming uses the FTB Chunks map and is tier-allocated, not paid per chunk — see §4. |
| **Library / Academy** | Knowledge & magic | FTB Quests anchor NPC, Ars Nouveau themed quests, lore terminals |
| **Tavern** | Social & onboarding | First-time newbie quests, casual NPCs, food/buff vendor |
| **Foundry / Workshop** | Crafting & commissions | Create-themed contracts, crafting orders, raw-material market |
| **Mint** | Currency information | Wallet info, currency tutorial, possibly emerald exchange |
### Forward-compat with a full quest line
The architecture is naturally dual-track:
- **FTB Quests** = the *progression* backbone — chapter-by-chapter pack content, one-time rewards, story arcs. The campaign.
- **Spawn-building NPCs** (Easy NPC + KubeJS) = the *daily/repeatable* layer — bounties, sell shops, services. The live activities.
Both pay into the same wallet. Players run the campaign at their pace and the daily content for income/replay value. They reinforce each other rather than compete.
---
## 4. Tier system & spawn plots
Two distinct land/status systems that often get conflated. Keeping them clean:
### 4a. Civic tier ladder
Every player has a Civic rank. Higher rank unlocks perks. Players spend spurs at the Civic Office NPC to upgrade. Powered by FTB Ranks under the hood (permission nodes drive what each rank unlocks).
The ladder is intentionally long (13 tiers) so endgame ranks feel rare and aspirational. Top tiers represent months of dedicated play; Sovereign is "you've finished the game."
| # | Title | Cost to reach | Wilderness chunks | Plot slots | Daily bounties | Shop fee | Chat colour | Join broadcast |
|---|---|---|---|---|---|---|---|---|
| 1 | **Peasant** | free (starter) | 9 | 0 | 3 | 0% | grey | — |
| 2 | **Farmer** | 200 | 18 | 0 | 3 | 0% | grey | — |
| 3 | **Citizen** | 750 | 35 | 1 | 3 | 0% | white | — |
| 4 | **Merchant** | 2,500 | 60 | 1 | 4 | -2% | yellow | — |
| 5 | **Knight** | 6,500 | 100 | 2 | 4 | -5% | green | simple |
| 6 | **Baron** | 15,000 | 150 | 2 | 5 | -7% | cyan | simple |
| 7 | **Viscount** | 35,000 | 220 | 3 | 5 | -9% | blue | fancy |
| 8 | **Earl** | 75,000 | 300 | 3 | 6 | -11% | purple | fancy |
| 9 | **Marquess** | 150,000 | 400 | 4 | 6 | -13% | gold | fancy |
| 10 | **Duke** | 300,000 | 525 | 5 | 7 | -15% | orange | epic |
| 11 | **Archduke** | 700,000 | 700 | 6 | 7 | -17% | red | epic |
| 12 | **Grand Duke** | 1,500,000 | 900 | 7 | 8 | -19% | bright red | epic + particles |
| 13 | **Sovereign** | 10,000,000 | 1,500 | 10 | 10 | -25% | rainbow | epic + spectacular |
**Travel philosophy:** this is a Create Aeronautics pack — the journey is the point. We deliberately do **not** give players sethomes, `/back`, or other instant-teleport conveniences. The intended travel system is **Waystones** (mod already in pack):
- Players get **one waystone** at the start of the game. It anchors their base.
- They can teleport between spawn ↔ their own waystone(s).
- Beyond that, real travel means building airships, trains, vehicles — the actual gameplay.
This is restrictive by design. We can layer **waystone-related perks** into the tier ladder in a later revision (e.g. "tier N unlocks 2nd waystone slot", or "tier M reduces waystone XP cost"). For V1 the ladder stays as above and travel pressure remains intentionally high.
**Notable shape choices:**
- **Knight (tier 5)** is the gentry threshold — first colored chat (green), first join broadcast, meaningful jump in plot slots
- **Duke → Archduke jump** is the late-game wall (300k → 700k, ~2.3×) — Archduke is the start of "I've really committed to this server" territory
- **Sovereign is dramatic** — 6.7× the Grand Duke cost. Real "finished the game" status. -25% shop fee is a step-change leap; spectacular join effects.
Numbers are first-pass calibration. The full perk table lives in a single JSON (`config/bnstoolkit/tiers.json`) that's hot-reloadable via `/bnstoolkit reload`. Easy to tune any column without code changes.
### 4a.1 Founder flag (admin cosmetic)
The server owner / admin has a permanent **`[Founder]`** cosmetic prefix in chat that sits alongside their normal rank. It carries no gameplay perks — it's just visible identification so friends know who runs the server. The Founder still grinds the regular tier ladder like everyone else (good for playtesting balance + sharing the experience). Op commands are the actual admin tool; the Founder tag is purely visual.
**Wilderness claims:** at every tier above Peasant, you get a flat allowance of N chunks you can claim anywhere outside spawn via the FTB Chunks map. Claiming is **free** within your allowance, refused above. No per-chunk pricing. Driven by FTB Ranks → FTB Chunks permission nodes (`ftbchunks.max_claimed_chunks`).
### 4b. Spawn plots
Spawn plots are a **separate system** from wilderness claims.
- **Pre-defined regions** at spawn — single chunks or small fixed clusters — designated by admins as "plots." Visible as fenced/bordered areas on the spawn map.
- **Purchased with spurs** at additional cost per plot (separate from tier upgrade cost). Indicative pricing: standard plot ~2,000 spurs, premium (corner / prime location) ~5,000 spurs.
- **Primary use:** shops. Players set up Numismatics shop blocks on their plots and sell to other players. Residence is allowed but secondary.
- **Slot-limited by tier:** your civic rank determines how many spawn plots you can own simultaneously (column above). Hit the limit, you can't buy another until you upgrade or release a plot.
- **Purchase happens inside the FTB Chunks map UI** — clicking a plot region in the map opens a confirmation screen (provided by our custom mod's mixin) showing cost + your remaining slots. Same UI you use for wilderness claims, integrated.
- **Plot data lives in the custom mod** (`bnstoolkit:plots`), not in FTB Chunks. Plots are a separate ownership system that uses the FTB Chunks map as its visual surface.
---
## 5. Quest & bounty flow (universal pattern)
**Core principle:** for any guild, the player **accepts** work from an NPC, **completes** it in the world, then **returns** to that NPC to **turn it in** and claim the reward. No instant payouts. This:
- Anchors guilds as destinations
- Creates risk/reward tension (die on the return, lose the reward)
- Encourages waypoint use and travel
- Lets the server centrally control payouts and detect cheating
### State machine
Each quest, per player, lives in one of these states:
```
AVAILABLE ─[player accepts]─► ACTIVE ─[objective met]─► READY ─[turned in]─► COMPLETED
▲ │
└──────────────────────[cooldown elapses]───────────────────────────────────────────┘
```
- **AVAILABLE** — NPC offers the quest in dialog. Player has no current copy of it.
- **ACTIVE** — Player accepted. KubeJS tracks objective progress via relevant events (`EntityEvents.death` for kills, `ItemEvents.firstRightClicked` for explorations, etc.).
- **READY** — Objective met. Reward is *promised but not yet paid.* NPC dialog now offers a turn-in option.
- **COMPLETED** — Reward paid out. Quest goes on cooldown for this player.
- **AVAILABLE** (again) — after the cooldown, the NPC will offer it again.
### Worked example — daily bounty
1. **Adventurer's Guild NPC** has 5 randomized daily quests (e.g. "Slay 10 Plunderers — 50 spurs").
2. Player right-clicks NPC → Easy NPC dialog → "Accept: Slay 10 Plunderers."
3. KubeJS writes `quest:plunderer_10` to the player's quest state with `count: 0`.
4. Player kills Plunderers in the world. `EntityEvents.death` for `supplementaries:plunderer` increments the count.
5. At count=10, KubeJS flips state to **READY** and notifies the player ("Return to the Adventurer's Guild to claim your reward.").
6. Player returns. Right-click NPC. Easy NPC dialog detects READY state and offers "Turn in: Slay 10 Plunderers."
7. KubeJS pays 50 spurs into the player's Numismatics wallet, flips state to **COMPLETED**, sets cooldown to 24h.
### Universal applicability
The same accept → complete → return pattern works for every guild:
| Guild | Accept | Complete | Return |
|---|---|---|---|
| **Adventurer's** | "Hunt 10 plunderers" | kill them | NPC pays bounty |
| **Merchant's** | "Procure 32 diamonds for our buyer" | gather them | NPC pays inflated price + completes |
| **Civic** | "Survey 5 unclaimed chunks" | walk through them | NPC pays survey fee |
| **Library** | "Recover this lost tome" | find the book in a structure | NPC pays + grants reputation |
| **Foundry** | "Craft 10 Andesite Casings" | craft them | NPC pays commission |
### Player-facing UI (locked)
Polished, integrated, no chat commands to memorise. All player interaction happens through GUIs and NPC dialogue. Custom companion mod (working name `bnstoolkit`) provides the screens; FTB Library's UI framework is the visual basis so our screens match FTB Quests, FTB Chunks, and FTB Teams natively.
| Surface | Implementation |
|---|---|
| **Quest Log screen** | Custom mod screen. Tabs: Active / Available / Completed. Click a quest to inspect, cancel from the detail panel. Opened via keybind or by clicking a Quest Log block at any guild. |
| **Bounty Board screen** | Custom mod screen, opened by right-clicking the Adventurer's Guild Quartermaster NPC OR clicking the in-world Bounty Board block. Lists today's available daily bounties with descriptions, rewards, and "Accept" buttons. |
| **Tier upgrade screen** | Custom mod screen, opened at the Civic Office NPC. Visual ladder, your current tier highlighted, next-tier cost, perks unlocked at each rank, big Upgrade button. |
| **Plot purchase popup** | Custom mod mixin into the FTB Chunks map UI. Hover a plot region → cost + slots tooltip. Click → confirmation popup. Owned plots also clickable to see plot info. |
| **Shop browser** | Numismatics shop blocks render their existing inventory UI by default; optional richer browser screen for the central Merchant's Bazaar inventory. |
| **Quest progress HUD** | Custom mod render layer — styled HUD element showing active quest names + progress bars. NOT stacked vanilla bossbars. |
| **NPC dialogue + buttons** | Easy NPC handles all NPC interactions: accept/turn-in, info, tutorials, "click for details" buttons. Players learn the system through NPC dialogue, not by reading docs. |
### Why custom mod, on FTB Library's UI framework
- **Visual consistency:** FTB Quests, FTB Chunks, FTB Teams all use FTB Library's widget framework. Our screens built on the same framework will look and feel like part of the same product.
- **Already a pack dependency:** no new mod added just for the UI layer.
- **Mixin compatibility:** our spawn plot mixin into the FTB Chunks map operates on FTB Library widgets natively — no translation layer between vanilla MC widgets and FTB Library widgets.
- **Less boilerplate than vanilla MC Screen API:** Panel, BlockButton, IconButton, Tooltip, TextField widgets already exist and behave consistently with how players already know FTB UIs to work.
- **Forking FTB is off the table:** FTB mods are "All Rights Reserved" — depending on FTB Library as a library is fine (that's what libraries are for), forking FTB Quests or FTB Chunks for redistribution is not legally clean. Custom mod alongside the FTB stack is the correct architecture.
### Why NOT FTB Quests for daily bounties
FTB Quests stays for **long-form progression** (Phase 5+), not for daily bounties. Source review confirms:
- No abandon/cancel event (Ctrl+Shift+R reset fires no event we can hook)
- Cooldown is per-team, not per-player
- Visibility is per-team, not per-player — rotating "5 of 20 daily" doesn't fit cleanly
For long-form progression where one-shot rewards + team scope are fine, FTB Quests is great. Our custom bounty engine handles the daily/repeatable pattern with its own UI.
### Quest slot limit
Players have a **maximum of 3 active quests at a time.** This is the friction that makes cancel meaningful:
- Forces players to pick which quests they actually want — no "accept all 5, see what's easiest, cancel the rest" RNG-shopping.
- Keeps the state files small.
- Makes ready-to-turn-in queues meaningful (you can hold 3 unrewarded quests in your back pocket).
A quest moving to READY frees the slot for accepting a new one even before turn-in.
### KubeJS implementation — locked specifics
- **State storage:** per-player JSON in `world/data/bns_quests/<uuid>.json`. Schema:
```json
{
"active": [
{
"id": "advg_plunderer_10",
"acceptedAt": 1717684800,
"progress": 7,
"target": 10,
"rewardSpurs": 50,
"source": "adventurers_guild",
"bossbarId": "bns:quest_advg_plunderer_10_<uuid>"
}
],
"completed": {
"advg_plunderer_10": { "cooldownUntil": 1717771200, "completions": 3 }
}
}
```
- **Event tracking:** KubeJS event handlers (`EntityEvents.death`, `ItemEvents.pickedUp`, `BlockEvents.broken`) read the player's active quests and increment progress + update bossbar value.
- **Bossbar lifecycle:** on quest accept, KubeJS creates a unique per-player bossbar via `server.runCommandSilent('bossbar add <id> <name>')`, assigns it to that player only, updates `value` and `max` on progress. On turn-in or cancel: `bossbar remove`.
- **Numismatics integration (direct Java access — no events shipped, no KubeJS bindings):**
```js
const Numismatics = Java.loadClass('dev.ithundxr.createnumismatics.Numismatics');
const ReasonHolder = Java.loadClass('dev.ithundxr.createnumismatics.content.backend.ReasonHolder');
const acct = Numismatics.BANK.getAccount(player); // ServerPlayer
const balance = acct.getBalance(); // int (spurs)
acct.deposit(50); // pay quest reward
const ok = acct.deduct(100, ReasonHolder.empty()); // returns false if broke
Numismatics.BANK.markBankDirty(); // force persistence
```
- **Dialog branching:** Easy NPC dialog branches on scoreboard objective `bns.quest.<npc_tag>` that KubeJS mirrors quest state into. Dialog `Command` action triggers `/bns_quest accept <id> <npc_tag>` which routes to KubeJS.
- **Commands:** registered via `ServerEvents.commandRegistry` in KubeJS. Scoped to the player who runs them. The custom `/bns_quest` namespace handles NPC-triggered actions; `/quests` is the player-facing tracker.
- **FTB Chunks claim cost (Phase 2):** requires `FTB XMod Compat` mod. Then:
```js
FTBChunksEvents.before('claim', event => {
const player = event.source.player;
const acct = Numismatics.BANK.getAccount(player);
const cost = computeClaimCost(player);
if (acct.getBalance() < cost) {
event.setResult(ClaimResult.YOU_DO_NOT_HAVE_ENOUGH_SPURS); // custom enum value
return;
}
acct.deduct(cost, ReasonHolder.empty());
});
```
**Note:** the `.before` may fire twice (sim + real). Guard with idempotent state, or do balance check in `.before` and deduct in `.after('claim')`.
---
## 5. Villager rebalance
**Decision:** move all villagers to **spurs** (not emeralds). Thematic consistency over preserving vanilla mental model.
**Decision principles:**
- Villagers are **net money sinks** — players spend more on villagers than they earn from them.
- **Useful trades stay** — enchanted books, tools, food, decorative blocks. Reasonable spur prices.
- **Trash trades get deleted** — no one ever wanted to sell rotten flesh or buy paper.
- **Sell-to-villager trades exist but are bad** — `64 wheat → 1 spur`, `16 leather → 1 spur`. Farms still possible, but ~10× slower than any other income source.
### Price guidance (initial calibration — tune via playtesting)
#### Buy-from-villager (player pays spurs)
| Item | Tier-1 | Tier-3 | Tier-5 |
|---|---|---|---|
| Standard enchanted book (random) | 50 spurs | 120 spurs | 250 spurs |
| Mending book | — | — | 800 spurs |
| Diamond tool (unenchanted) | — | 80 spurs | — |
| Diamond tool (enchanted) | — | — | 350 spurs |
| Bookshelf | 15 spurs | — | — |
#### Sell-to-villager (player gets spurs)
| Item | Spurs per unit |
|---|---|
| Wheat | 1 per 64 |
| Paper | 1 per 32 |
| Leather | 1 per 16 |
| Iron ingot | 2 per 1 |
| Diamond | 8 per 1 *(matches sell-shop fixed price — players use whichever is closer)* |
### Scope
~60 trades × 5 profession tiers = ~300 trade entries to redesign. One-time data-design pass, implemented via `ServerEvents.villagerTrades` in KubeJS.
---
## 6. Money inflow sources (detailed)
| Source | Cap / DR mechanism | Rough rate |
|---|---|---|
| **Daily bounties** | Per-player per-quest cooldown (24h) | ~200-500 spurs/day for an active player |
| **Sell shop (fixed price + DR)** | Lifetime sales tracker per player, 10% price drop per 64 sold | ~50-200 spurs/hr while diamond stockpile lasts |
| **Dynamic exchange** | Global supply pool — price drops with sales | Self-balancing |
| **First-time milestones** | One-shot per player (`hasFlag`) | 5-50 spurs per milestone, ~10 milestones total |
| **FTB Quest progression** | One-time per quest | Varies; cluster rewards at chapter completion |
| **Villager sell trades** | Inherently slow + bad prices | ~50 spurs/hr from a serious villager farm |
---
## 7. Money outflow sinks (detailed)
| Sink | Cost curve | Why this scales right |
|---|---|---|
| **Plot claims** | Free up to 9 chunks. 50 spurs/chunk to 25. 200 spurs/chunk beyond. | New players claim free starter areas; ambitious players pay real money |
| **Tier upgrades** | Cumulative cost: 500 → 2k → 8k → 30k spurs | Endgame sink, status display |
| **Buy-from-villager** | See §5 | Constant outflow as you build up |
| **Premium cosmetics** | 100-2k spurs each | Optional sink for cash-flush players |
| **Services** | Sethome: 50 spurs, warp: 25 spurs, /back: 10 spurs | Convenience taxes |
---
## 8. Mod stack (locked)
### Already in pack
| Need | Mod | Version |
|---|---|---|
| Currency + wallets + shop blocks | Numismatics | 1.0.20 |
| NPC dialog presentation | Easy NPC | 6.16.x (6.17.0 available, minor bump) |
| Plot claims | FTB Chunks | 2101.1.14 |
| Team management | FTB Teams | 2101.1.9 |
| Core library | FTB Library | 2101.1.31 |
| Cross-mod compat | Architectury API | 13.0.8 |
| Glue, commands, state | KubeJS | 2101.7.2 |
### Adding in Phase 0a (mod-additions PR — blocks everything else)
| Mod | Version | Reason |
|---|---|---|
| **FTB Quests** | 2101.1.25 | Progression quest UI (Phase 5+) |
| **FTB XMod Compat** | latest 1.21.1 NeoForge | KubeJS hooks for FTB Chunks claim events + FTB Quests events |
| **FTB Ranks** | 2101.1.3 | Tier system. CurseForge only, no Modrinth listing. |
### Building our own (custom companion mod)
**`bnstoolkit`** (working name) — a small companion mod in our own repo. Confirmed locked-in.
- Provides all custom GUI screens (Quest Log, Bounty Board, Tier upgrade, Shop browser)
- Provides the FTB Chunks map mixins (spawn plot cost overlay, hover tooltip, purchase popup)
- Provides custom quest-progress HUD render layer
- Provides the `bnstoolkit:plots` data storage + ownership permissions
- Provides network packets for client↔server state sync
- Provides the `/bnstoolkit reload` admin command for hot-reloading tier config
- Built on FTB Library UI framework for visual consistency
- KubeJS handles all gameplay logic (bounty rotation, state machine, villager trades, Numismatics integration) — the mod is purely the UI + integration layer
Estimated scope: ~2-3k LOC, single-developer week of focused work. Bounded.
### Explicitly NOT adding
- CustomNPCs (Easy NPC covers it)
- Citizens (Bukkit-only)
- PMMO / skill mods (out of scope)
- Generic "quest giver" mods (FTB Quests + our KubeJS bounty engine cover it)
---
## 9. Phasing
Each phase is independently shippable. Earlier phases unlock value without depending on later ones.
| Phase | Deliverable | Spawn build required? |
|---|---|---|
| **0a** | **Mod additions PR:** FTB Quests + FTB XMod Compat + FTB Ranks (+ minor Easy NPC bump). New pack version. | No |
| **0b** | Spawn skeleton — 7 guild building blockouts (rough). **User does in-game when time permits.** Non-blocking. | Yes (user) |
| **0c** | **`bnstoolkit` companion mod — scaffolding pass.** Mod project set up, FTB Library UI dependency wired, network packet plumbing, build/release scripts. No screens yet. | No |
| **1** | **Sell shop:** Numismatics shop blocks for diamonds (10 spurs) + netherite ingots (100 spurs). Lifetime-sale tracker for diminishing returns. KubeJS only, no mod work needed. | No |
| **2** | **Tier upgrade flow:** FTB Ranks integrated + KubeJS `/tier upgrade` command. **`bnstoolkit` Tier upgrade screen** wired to Civic Office NPC. Tier perks driven by `tiers.json`. | No |
| **3** | **Spawn plot system:** plot region registry in `bnstoolkit`, ownership tracking, FTB Chunks map mixin (cost overlay + purchase popup). | No |
| **4** | **Bounty engine:** state machine, KubeJS-rotated dailies, `bnstoolkit` Bounty Board screen + Quest Log screen + Quest progress HUD. NPC dialog hooks via Easy NPC. 3-slot cap. | No (NPC layer activates once spawn is built) |
| **5** | **Villager rebalance:** strip vanilla, ship spur-priced trade table via `ServerEvents.villagerTrades`. | No |
| **6** | **Progression quest line:** FTB Quests anchor + first chapter. KubeJS rewards dispense spurs via Numismatics API. | No (anchor NPC at Library once spawn exists) |
| **7** | **Dynamic exchange rates:** global supply-pool pricing for raw mats. | No |
| **8+** | Lootr dungeons, Foundry crafting commissions, deeper FTB Quests chapters, player-vs-player bounties (if wanted). | TBD |
---
## 10. Risk register
| Risk | Likelihood | Mitigation |
|---|---|---|
| Bounty engine bugs out, players lose progress | Medium | Atomic state writes; logs of every state transition |
| Villager farms still profitable after rebalance | Medium | Track player sell volumes; tune prices in patches |
| KubeJS-EasyNPC dialog branching has limits | Low-Med | Verify hooks in a test world before Phase 3; fall back to command-driven NPCs if needed |
| FTB Chunks `/claim` command override gotchas | Low | Test in dev world; FTB Chunks API is stable |
| Plot cost feels punishing | Med | First 9 chunks free is the safety valve; tune from playtest |
| Players bypass the system via creative / `/give` | Op-only | Document op responsibility; consider audit logs for op spur grants |
---
## 11. Decisions made
Resolved before implementation:
| Question | Decision |
|---|---|
| Quest UI for bounties | **Custom mod with FTB Library UI widgets** — proper GUI screens, no chat commands |
| Quest UI for progression | FTB Quests |
| Plot purchase UI | Custom mod mixin into FTB Chunks map — hover preview, click-to-buy popup |
| Tier upgrade UI | Custom mod screen at Civic Office NPC |
| State storage | KubeJS-managed per-player JSON for quest state; mod-managed for plot ownership |
| Numismatics access | Direct Java via `Java.loadClass` from KubeJS; via API directly from the mod |
| Wilderness chunk allowance | Tier-driven via FTB Ranks permission nodes — no per-chunk pricing |
| Spawn plots | Predefined regions, slot-limited by tier, individually purchased with spurs |
| Tier ladder | Civic (13 tiers): Peasant → Farmer → Citizen → Merchant → Knight → Baron → Viscount → Earl → Marquess → Duke → Archduke → Grand Duke → Sovereign |
| Founder flag | Admin/owner has `[Founder]` cosmetic prefix in chat, grinds the regular ladder otherwise |
| Tier perks | JSON-configured (`config/bnstoolkit/tiers.json`), hot-reloadable |
| Custom mod | Confirmed. Built on FTB Library UI framework. Working name `bnstoolkit`. |
| Sethomes / warps | Tier-allocated count (not paid per use) |
| Daily quest count | Tier-driven (3 at Peasant, up to 6 at Sovereign), refresh per-player 24h after last accept |
| Emeralds | Retired as currency, retain as a trade material for villager-redirect trades |
| Fork FTB | Not needed — depend on FTB Library as a UI lib, FTB Chunks/Quests stay unmodified, integration via mixins + KubeJS hooks |
### Still to decide (non-blocking — pick during implementation)
- **PvP bounties** — out of scope for V1, revisit after V1 ships
- **Lootr** — add only when structured dungeons exist (Phase 8+)
- **Default-rank starting permissions** — finalised when FTB Ranks config is written
- **Spawn plot pricing** — first-pass numbers (2,000 standard / 5,000 premium), tune in playtest
---
## 12. Implementation notes
### KubeJS scripts (gameplay logic)
Organised under `pack/overrides/kubejs/server_scripts/economy/`:
- `01_numismatics_api.js` — Java.loadClass wrapper helpers (balance / deposit / deduct)
- `02_quest_state.js` — load/save `world/data/bns_economy/quests/<uuid>.json`
- `03_commands.js` — admin commands (`/tier upgrade`, `/bnstoolkit reload`, debug)
- `04_bounty_engine.js` — daily rotation, state machine, KubeJS↔mod packet handlers
- `05_sell_shop.js` — Numismatics shop tracking + diminishing returns
- `06_villager_trades.js` — Phase 5 `ServerEvents.villagerTrades` rebalance
- `07_tier_perks.js` — FTB Ranks promote/demote, perk application
- `99_dynamic_exchange.js` — Phase 7 supply-priced market
### Custom mod codebase
Repo: separate (or sub-tree of main repo, TBD).
Modid: `bnstoolkit` (working name).
Package layout:
```
bnstoolkit/
├── client/
│ ├── screen/ QuestLog, BountyBoard, Shop, Tier, PlotConfirm (FTB Library subclasses)
│ ├── mixin/ ChunkScreenPanel (cost overlay + plot button), ChunkButton (hover tooltip)
│ ├── hud/ QuestProgressHud (custom render)
│ └── ClientEvents keybind reg, screen reg, mixin loader
├── server/
│ ├── packet/ OpenScreen, UpgradeRank, BuyPlot, ClaimBounty, etc.
│ ├── command/ /bnstoolkit reload (config refresh)
│ └── data/ PlotRegistry, PlotOwnership (saved with world data)
├── common/
│ ├── data/ TierConfig (JSON-loaded), BountyDefinition, QuestState mirror
│ └── BnsToolkit.java mod entry
└── config-defaults/
├── tiers.json copied to config/bnstoolkit/tiers.json on first run
└── plots.json spawn plot region definitions
```
Architecture doc (`docs/bnstoolkit-architecture.md`) covers package layout, screen UX sketches, network packet contract, mixin targets, KubeJS↔mod integration surface — to be written before mod work begins.
### State data
- Quest state: `world/data/bns_economy/quests/<uuid>.json`. Readable JSON, easy to debug.
- Plot ownership: persisted with world via the mod's `SavedData` (vanilla NeoForge persistence). Authoritative source of truth.
- Tier config: `config/bnstoolkit/tiers.json` shipped from `pack/overrides/defaultconfigs/bnstoolkit/tiers.json`. Hot-reloadable.
- Plot definitions: `config/bnstoolkit/plots.json` shipped similarly. Defines plot region bounds, type (standard/premium), prices.
### NPC dialog
Authored in Easy NPC's in-game editor, exported as preset JSONs into `pack/overrides/world/datapacks/bns-fuel/data/easy_npc/`. Dialog `Command` actions call `/bnstoolkit <verb> ...` which routes to either the mod (for screen-opening) or KubeJS (for state changes).
### Villager rebalance
Single source file `06_villager_trades.js`. Each profession × tier has its own block. One file = one diff per balance pass.
---
## See also
- `MEMORY.md` entries:
- `project-mc-player-economy.md` — earlier higher-level notes on Numismatics + plot system
- `feedback-kubejs-rhino-gotchas.md` — KubeJS scripting constraints
- `feedback-bns-pack-version-sync.md` — pack version + sync workflow
- Existing tasks #20-#26 — to be reshuffled to mirror the phase plan above