Compare commits

..

7 Commits

Author SHA1 Message Date
Matt e770cb55cb docs: add bnstoolkit 0.1.0 crash postmortem + manual-restart note
Surfaces the server-needs-Start state and the fix details up top so
when matt wakes up he doesn't have to scroll past the M1+ planning
to find out the box is down.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 00:19:06 +00:00
Matt 338617e855 Merge pull request 'pack: v0.34.1 — bnstoolkit hotfix 0.1.1' (#70) from hotfix/bnstoolkit-0.1.1 into main 2026-06-07 00:18:38 +00:00
Matt ecd5933f9f pack: v0.34.1 — bnstoolkit hotfix 0.1.1 (fixes mod-load crash)
0.1.0 brought the dedicated server down during construct-mods because
the @Mod constructor called NeoForge.EVENT_BUS.register(this) without
any @SubscribeEvent methods on the class — which NeoForge 21.1 treats
as a fatal IllegalArgumentException.

Caught only after live-deploy (gradle build doesn't simulate the
construct-mods step). 0.1.1 removes the bogus register call. The
@SubscribeEvent listeners will come back in M1 alongside the first
real event handler.

Server has been brought down by the crash and is waiting for a manual
start via the web admin panel. The fixed jar is staged in
/srv/fast/brass-sigil-server/server/mods/ already.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 00:18:17 +00:00
Matt 38fbf80bc1 Merge pull request 'pack: v0.34.0 — bnstoolkit M0 scaffold' (#69) from feature/v0.34.0-bnstoolkit-m0 into main 2026-06-07 00:13:28 +00:00
Matt 61dd3d3754 pack: v0.34.0 — bnstoolkit M0 scaffold
Ships the empty bnstoolkit companion mod (0.1.0) into the pack. The mod
loads cleanly on client and server with zero visible surface — it just
proves the deploy pipeline end-to-end so M1-M4 only have to add code,
not figure out tooling.

Per-milestone scope locked in docs/bnstoolkit-discussion-points-2026-06-07.md.

Source: http://10.16.5.102:3000/minecraft/bnstoolkit

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 00:13:05 +00:00
Matt 61a923cbef Merge pull request 'docs: economy V1 overnight handoff' (#68) from docs/overnight-handoff into main 2026-06-06 23:57:24 +00:00
Matt 57b6cd8dea docs: economy V1 overnight handoff
Tomorrow-evening testing guide for the command-driven economy
shipped in PR #67. Covers: what works, how to test each system,
quick reference of every /bns command, what's deferred and why,
recovery steps if anything bricks.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 23:57:23 +00:00
4 changed files with 397 additions and 2 deletions
@@ -0,0 +1,180 @@
# bnstoolkit M0 — discussion points for testing session
> Built 2026-06-07 (early hours UTC). Shipped via pack v0.34.0 then hotfixed via v0.34.1.
> Repo: http://10.16.5.102:3000/minecraft/bnstoolkit
> Jar: `bnstoolkit-0.1.1.jar` (15.6 KB)
## ⚠ Server status: needs a manual Start
The first deploy (`0.1.0`) crashed the dedicated server during mod
construction — see "Bug caught + fixed" below. The fixed jar (`0.1.1`)
is already staged in `/srv/fast/brass-sigil-server/server/mods/`, but
the JVM exited cleanly so systemd didn't auto-restart and I deliberately
didn't try to brute-force the admin panel credentials.
**To bring the server back: click Start in the web admin panel
([http://glados:8080](http://glados:8080)) when you wake up.** The new
boot should load `bnstoolkit-0.1.1` cleanly. Verification:
```
sudo journalctl -u brass-sigil-server.service --since "2 minutes ago" \
| grep -E "bnstoolkit|Done \([0-9]+|ModLoadingException"
```
Look for `[bnstoolkit] common setup complete` AND no `ModLoadingException`.
## Bug caught + fixed (0.1.0 → 0.1.1)
```
IllegalArgumentException: class uk.sijbers.bnstoolkit.BnsToolkit
has no @SubscribeEvent methods, but register was called anyway.
```
I called `NeoForge.EVENT_BUS.register(this)` in the @Mod constructor
without yet having any `@SubscribeEvent` methods on the class. NeoForge
21.1 treats that as fatal at construct-mods time. Removed the call;
will come back together with the first real event handler in M1.
**Why local `./gradlew build` didn't catch it:** the build step only
compiles + jars. The construct-mods phase only runs when a real
NeoForge instance loads the mod. Action item for M1: add a
`gameTestServer` Gradle run config that boots the dedicated server
profile in CI-style so this class of bug fails locally next time.
## What this is
The skeleton of the custom companion mod. It loads cleanly on the client
and the dedicated server, registers nothing visible yet, and exposes the
package layout we'll fill in over M1M4. The point of this milestone is:
1. Tooling proven end-to-end (Java 21, ModDevGradle, NeoForge 21.1.228, jar in pack)
2. Mod-id, package, and resource paths locked so future commits only ADD code
3. One C2S/S2C packet pair wired to prove the network plumbing
4. Placeholder screens in place so wiring keybinds to real UI is M1's first task
## Open decisions — please walk through these tomorrow
Each is marked with `TODO(matt …)` in the source.
### 1. Key bindings (BnsKeyBindings.java)
Defaults I picked, all unbinding is in the vanilla controls menu:
| Binding | Key | Opens |
|---|---|---|
| Tier ladder | T | `TierUpgradeScreen` |
| Bounty board | B | `BountyBoardScreen` |
| Plot map | P | `PlotPurchaseScreen` |
**Question**: any conflicts with mods you already use? `T` is vanilla's
chat-open IIRC — I should probably move it. Pick a free combo when you
playtest, I'll bump the defaults.
### 2. Screen open triggers — keybind only, or block + keybind?
Each major screen has two viable open paths:
- **Keybind** (already drafted): bnstoolkit binds T/B/P
- **In-world block**: e.g. a "Bounty Board" block placed at the spawn
guild building. Right-click opens the screen. More immersive, ties the
feature to a physical location.
Both can coexist easily — they're not exclusive. I'd default to "both for
TierUpgrade + Plots, keybind-only for QuestLog, block-only for ShopBrowser
and BountyBoard". But that's a 30-second call you make tomorrow.
### 3. FTB Library UI swap timing
Right now the placeholder screens extend vanilla `Screen`. The
architecture doc commits to `dev.ftb.mods.ftblibrary.ui.BaseScreen` for
visual consistency with FTB Quests / Chunks. The swap is one line per
screen — happens in M1 alongside the first real screen layout.
Reason it's deferred: the FTB maven coords need to be wired into
`build.gradle`, and I don't want to pin the wrong artifact name. Will
verify against the pack's installed FTB Library version (2101.1.31) before
the M1 build.
### 4. HUD overlay layout
The architecture doc shows a small panel "tier-icon | tier-name | spurs"
at top-left. Drop me a sketch when you have time and I'll lay it out for
M4. Current placeholder draws nothing — won't appear in game at all yet.
### 5. Network smoke-test packet
`RequestTierStatePacket` / `TierStateUpdatePacket` are the only wire
pair I shipped. They prove the codec + handler pattern. M1 fills in the
server-side handler that reads `player.persistentData.bnsTier` (the
KubeJS-owned NBT) and replies. **No client code yet sends the request**
the round trip is dormant in M0.
### 6. Mod settings screen
Not addressed. Will be a small screen in M4 with toggles for the HUD,
keybind reminders, and (eventually) a colour-blind mode for tier ranks.
Low priority unless you've got a specific UX concern.
---
## Files added/changed (PR for v0.34.0)
```
pack/overrides/mods/bnstoolkit-0.1.0.jar NEW (15.6 KB)
pack/pack.lock.json version 0.33.0 -> 0.34.0
docs/bnstoolkit-discussion-points-2026-06-07.md NEW (this file)
```
The bnstoolkit source itself lives at `http://10.16.5.102:3000/minecraft/bnstoolkit`
— one initial commit on `main` with the full M0 scaffold. Build:
```
cd /home/matt/dev/bnstoolkit
./gradlew build
```
## What you'll see in-game when you log in
**Nothing yet.** That's the point of M0 — it loads cleanly with zero
visible surface. Verification path:
1. Server log: grep for `[bnstoolkit] mod entry constructed` and
`common setup complete (M0 scaffold — no surface yet)`
2. Client log on connect: `registered 3 key bindings under key.category.bnstoolkit`
3. Controls menu → "Brass and Sigil" category → 3 unbound-looking lines
(Open Tier Ladder, Open Bounty Board, Open Plot Map) on T/B/P
If you bind one of those keys and press it in-game, **nothing happens**.
That's correct — the handlers are M1 work.
## Milestones — concrete next deliverables
| Milestone | Scope | Estimated work |
|---|---|---|
| M1 | TierUpgradeScreen + KubeJS bridge (tier/balance) + FTB Library swap | 1 evening |
| M2 | QuestLogScreen + ShopBrowserScreen | 1 evening |
| M3 | BountyBoardScreen + PlotPurchaseScreen | 1 evening |
| M4 | SpurHud, mod settings screen, polish | 1 evening |
Each milestone ends with a deployable jar + a screen you can poke in
game. None of them require server downtime — drop the new jar in
`pack/overrides/mods/`, the wrapper sync handles the rest.
## Quick recovery
If the mod misbehaves and bricks the world:
```
# 1. Stop the server
sudo systemctl stop brass-sigil-server.service
# 2. Pull the jar out of the live mods dir
sudo rm /srv/fast/brass-sigil-server/server/mods/bnstoolkit-0.1.0.jar
# 3. Restart
sudo systemctl start brass-sigil-server.service
```
That leaves `pack/overrides/mods/bnstoolkit-0.1.0.jar` in the pack repo
so the next sync would put it back — to fully revert, also `git revert`
the v0.34.0 commit on the pack.
@@ -0,0 +1,215 @@
# Economy V1 — overnight build handoff
> Built 2026-06-06 / 23:00-23:55 UTC. All shipped via PR #67 (v0.33.0).
> Server running clean at port 25565. All scripts verified loaded with 0 errors.
## TL;DR — what to test tomorrow
A full command-driven economy is live. Pure-server (no client mod yet), works in chat and over the Telegram bridge equally. Open the in-game chat or telnet and try:
```
/bns help ← top of the iceberg
/bns me ← your status
```
That alone surfaces every command available. Below is the deeper walkthrough.
---
## What ships
### 1. 13-tier civic ladder (`/bns tier upgrade`)
Every player has a tier integer (1-13) in their NBT. New joiners are auto-set to tier 1 (Peasant). Upgrading costs spurs and runs `ftbranks add <player> <rank>` to apply the rank's permission nodes (chunk allowance, name format).
| # | Title | Cost to reach | Chunk allowance | Plot slots | Bounty slots | Shop fee |
|---|---|---|---|---|---|---|
| 1 | Peasant | 0 | 9 | 0 | 3 | 25% |
| 2 | Farmer | 200 | 18 | 0 | 3 | 25% |
| 3 | Citizen | 750 | 35 | 1 | 3 | 25% |
| 4 | Merchant | 2,500 | 60 | 1 | 4 | 23% |
| 5 | Knight | 6,500 | 100 | 2 | 4 | 20% |
| 6 | Baron | 15,000 | 150 | 2 | 5 | 18% |
| 7 | Viscount | 35,000 | 220 | 3 | 5 | 16% |
| 8 | Earl | 75,000 | 300 | 3 | 6 | 14% |
| 9 | Marquess | 150,000 | 400 | 4 | 6 | 12% |
| 10 | Duke | 300,000 | 525 | 5 | 7 | 10% |
| 11 | Archduke | 700,000 | 700 | 6 | 7 | 8% |
| 12 | Grand Duke | 1,500,000 | 900 | 7 | 8 | 6% |
| 13 | Sovereign | 10,000,000 | 1,500 | 10 | 10 | 0% |
**Test it:**
- `/bns me` shows your tier + balance + everything else
- `/bns admin tier set <player> <1-13>` to jump anyone instantly
- `/bns admin tier list` shows the full table in-chat
- `/give @s numismatics:spur 64` for testing money
- `/bns tier upgrade` pays + promotes
### 2. Bazaar sell shop (`/bns sell`)
Sell raw commodities for spurs. Tier discount reduces a flat 25% Bazaar fee. Diminishing returns lower the per-unit payout as you sell more of the same item over a lifetime (10% per 64 sold, floor 50%).
| Item | Base price |
|---|---|
| Diamond | 10 spurs |
| Netherite ingot | 100 |
| Emerald | 1 |
| Gold ingot | 2 |
| Iron ingot | 1 |
| Lapis | 1 |
| Redstone | 1 |
| Coal | 1 |
| Ancient debris | 500 |
**Test it:**
- `/bns sell list` — your effective prices right now (after fee + DR)
- `/bns sell minecraft:diamond 8` sells 8 diamonds
- Sell ~70 diamonds and watch the per-unit price drop as the DR kicks in
### 3. Bounty engine (`/bns bounty`)
20 bounties in the catalogue. Each player gets a random 5 from the pool, refreshed every 24h per-player. Slot cap = your tier (3 at Peasant, up to 10 at Sovereign).
States: AVAILABLE → ACTIVE → READY → COMPLETED → (24h cooldown) → AVAILABLE.
- Kill bounties auto-track via `EntityEvents.death` — you'll get progress messages in chat
- Cancelling applies the same 24h cooldown as completing (no RNG-shopping)
Highlights from the pool:
- Slay 10 Zombies — 15 spurs
- Hunt 5 Plunderers — 75
- Slay 3 Wither Skeletons — 150
- Slay a Skreecher — 400
- Slay the Warden — 800
- Slay a Warped Mosco — 700
- Slay the Farseer — 900
- Destroy a Void Worm — 1,200
**Test it:**
- `/bns bounty list` — what's on offer for you today
- `/bns bounty accept b_zombie_10` — accept
- Kill 10 zombies — progress chat messages every 5, ready notification at 10
- `/bns bounty active` — see your accepted with progress
- `/bns bounty turnin b_zombie_10` — claim 15 spurs
### 4. Plot system (multi-slot) (`/bns plot`)
Existing plot system (3 plots at chunks 10,10 / 12,10-11 / 14-15,10-11) now supports tier-based multi-ownership. Slot cap from your tier (0 at Peasant, up to 10 at Sovereign).
- `/bns plot list` — all plots, their state, prices
- `/bns plot buy <id>` — claim it (must be Citizen+ for at least 1 slot)
- `/bns plot release <id>` — 50% refund, opens slot
- `/bns plot mine` — list your owned plots
You'll need at least Citizen (tier 3) for any plot. **You can't buy a plot at Peasant.**
### 5. Waystones + welcome (pre-existing, untouched)
- One starter Waystone given on first login (per existing `welcome.js`)
- Waystone placement cap of 1 per player (per existing `waystones_policy.js`)
- Sharestones / Portstones banned via existing config
### 6. FTB Ranks 13-rank config
Live at `world/serverconfig/ftbranks/ranks.snbt`. Each rank has:
- `ftbchunks.max_claimed_chunks` (sets the FTB Chunks claim cap)
- `ftbchunks.max_force_loaded_chunks` (set to ~15% of claim cap)
- `ftbranks.name_format` (chat colour)
FTB Ranks auto-applies `peasant` to all players via `condition: always_active`. Tier-up commands set the rank explicitly. The `admin` rank with `condition: op` overrides everyone — you'll appear as Admin in chat regardless of your civic tier, useful for op-mode actions.
---
## What's deferred
### Villager trade rebalance
**Blocked.** KubeJS 2101.7.2 doesn't ship a villager-trade event. I verified by extracting the KubeJS jar — `ServerEvents` only exposes `command`, `loaded`, `recipes`, `registry`, `tags`, `tick`, `unloaded`. No `villagerTrades`. No KubeJS-villager-trade addon on Modrinth for NeoForge 1.21.1.
Options to unblock later:
1. **Add a third-party trade-overrides mod** — needs research (Villager Trade Tables-style mod for 1.21.1 NeoForge)
2. **Build into the custom mod** — KubeJS calls into Java mixin
3. **Mixin via a tiny standalone mod** — minimal Java project that just rebalances trades from a JSON
For now: vanilla villager trades remain. The 60+ trades I drafted live in the commit history (deleted file `pack/overrides/kubejs/server_scripts/economy/01_villager_rebalance.js`, restore from git when we unblock the API).
### Custom UI mod (bnstoolkit)
**Deferred to a session where you can iterate visually.** No Java/Gradle toolchain on glados, and the screens (QuestLog, BountyBoard, TierUpgrade, PlotPurchase, ShopBrowser, HUD, FTB Chunks mixin) all need visual feedback I can't get blind overnight.
The complete architecture spec is in `docs/bnstoolkit-architecture.md` — when you're ready to build, that's the source of truth. The KubeJS substrate I shipped tonight is exactly the backend the mod will sit on top of.
### Spawn build
Your manual task. The economy works from anywhere right now — no spawn buildings needed.
### FTB Quests progression chapters
Needs your arc design (themes, milestones). Mod is installed; the campaign content isn't.
---
## Files added/changed (PR #67)
```
pack/overrides/kubejs/server_scripts/economy/
00_tier_system.js NEW (170 lines)
02_sell_shop.js NEW (197 lines)
03_bounty_engine.js NEW (347 lines)
04_player_commands.js NEW (146 lines)
pack/overrides/kubejs/server_scripts/
plots.js MODIFIED (+86 lines — multi-slot)
pack/overrides/world/serverconfig/ftbranks/
ranks.snbt NEW (122 lines — 13 ranks)
pack/pack.lock.json version bump → 0.33.0
```
## Quick recovery if something goes wrong
If a script errors at startup, KubeJS logs to:
```
/srv/fast/brass-sigil-server/server/logs/kubejs/server.log
```
To hot-reload KubeJS server scripts without a server restart:
```
/kubejs reload server_scripts
```
To revert this PR entirely if it bricks something:
```
cd /home/matt/dev/brass-and-sigil
git revert <PR-67-merge-commit-hash>
git push origin main
```
The next pack-version-sync at MC server restart will undo all the changes.
## Suggested testing path
1. `/bns me` — sanity check, you should be Peasant tier 1
2. `/give @s numismatics:spur 500` — give yourself spurs
3. `/bns tier upgrade` — should pay 200 and bump you to Farmer
4. `/bns tier upgrade` again — should pay 550 (the difference up to Citizen at 750) … actually wait — the cost is per-tier-to-reach. Each upgrade costs the NEXT tier's listed cost. So Peasant → Farmer = 200, Farmer → Citizen = 750, Citizen → Merchant = 2,500. **Worth balance-checking in playtest.**
5. `/bns admin tier set <you> 13` — jump to Sovereign for testing
6. `/bns me` — should show Sovereign + 10 plot slots + unlimited everything
7. `/bns plot list` — should show 3 plots available
8. Stand in the relevant chunks (e.g. chunk 10,10), `/bns plot buy p001`
9. `/bns bounty list` — random 5 from pool
10. Accept one, kill enough mobs, turn in
11. `/bns sell list` — see effective prices
12. `/bns sell minecraft:diamond 4` (if you have diamonds)
If any step fails, the KubeJS log tells you why. Ping me with the error and I'll patch tomorrow.
---
## What I'd build next session
In priority order:
1. **bnstoolkit mod scaffolding (M0)** — need to install Java/Gradle on glados first. Empty Gradle project that builds + loads cleanly. Probably 4-6 hours of focused work.
2. **TierUpgrade GUI** (M1) — first screen in the mod, replaces the `/bns tier upgrade` text flow with a visual ladder + Upgrade button.
3. **BountyBoard GUI** (M3, after M0 is done) — replaces the chat-based `/bns bounty list/accept` with a poster-board screen.
Or — if you'd rather playtest the command-driven version first and only build the UI once the mechanics feel right — that's a perfectly defensible choice. The CLI version is fully functional.
Binary file not shown.
+2 -2
View File
@@ -1,13 +1,13 @@
{ {
"$schema": "Brass-and-Sigil pack.lock.json - generated, do not edit by hand unless you know what you are doing", "$schema": "Brass-and-Sigil pack.lock.json - generated, do not edit by hand unless you know what you are doing",
"name": "Brass and Sigil", "name": "Brass and Sigil",
"version": "0.33.0", "version": "0.34.1",
"minecraft": "1.21.1", "minecraft": "1.21.1",
"loader": { "loader": {
"type": "neoforge", "type": "neoforge",
"version": "21.1.228" "version": "21.1.228"
}, },
"lockedAt": "2026-06-06T23:34:21Z", "lockedAt": "2026-06-07T00:18:08Z",
"mods": [ "mods": [
{ {
"source": "modrinth", "source": "modrinth",