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>
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 questbutton. 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
Acceptbutton. - 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:
S2CTierSnapshotreturns current tier + balance - On upgrade click:
C2SRequestTierUpgrade→ server verifies balance, calls KubeJS/bnstoolkit_internal upgrade_rank <uuid>which charges spurs and runsftbranks 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 inPlotOwnershipSavedData.
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'spack/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 buildon 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.0for V1 ship,1.x.yfor patches,2.0.0if 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)/listhomesshows owned homes/delhome <name>removes- Cap enforced from the player's tier (
tiers.json→sethomes) - Unlimited = represented as
-1in 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:
- 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.
- Plot release refund percentage — proposed 50%. Tune via playtest.
- Sethome cooldown values per tier — proposed scaling from 60s
(low tiers) to 5s (Sovereign). Confirm in
tiers.jsonschema. /backinteraction 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.- Founder cosmetic prefix colour — bright yellow? Bold white? Animated? Settle during implementation.
- 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.mdentries — KubeJS Rhino gotchas, defaultconfigs pattern