pack: economy MVP -- Numismatics + Patchouli + welcome flow, bump to 0.18.0

Adds the currency layer and the first-join experience.

Mods:
- Create: Numismatics 1.0.20  (currency, vendor blocks, piggy banks)
- Patchouli 1.21.1-93         (kept in pack for future rich manual book)

KubeJS scripts (server_scripts/):
- economy_policy.js  remove ALL Waystones recipes; remove coin recipes
                     only (piggy banks etc. stay craftable for now)
- welcome.js         first-login grant: 1 waystone + vanilla written-book
                     "Brass & Sigil Manual v1" (5 pages: welcome,
                     waystones, money, spawn plots, rules). Per-player
                     flag bnsWelcomeGranted in persistentData gates it.

KubeJS scripts (client_scripts/):
- jei_hides.js       hide all Waystones items + 4 coin denominations from
                     the JEI ingredient list. Combined with the recipe
                     removal players never encounter these items via
                     normal play -- only via the welcome grant or the
                     bank exchange.

The written-book manual is the MVP placeholder. When more content lands
(plot system, dynamic exchange, etc.) it'll be replaced by a proper
Patchouli book authored as a tweak jar -- Patchouli's already in the
lockfile so no mod-add will be needed at that point.
This commit is contained in:
2026-05-23 14:16:45 +00:00
parent d60c0176dd
commit 2ac4b2f2cd
4 changed files with 152 additions and 1 deletions
@@ -0,0 +1,52 @@
// Brass & Sigil — JEI hides
//
// Hides all Waystones items + all Numismatics coin items from the JEI
// item list. Combined with the server-side recipe removal in
// economy_policy.js, players don't see crafting recipes OR the item
// icons in the JEI ingredient list -- they only ever encounter these
// items through the welcome grant or the bank exchange.
const COLORS = [
'white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime',
'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue',
'brown', 'green', 'red', 'black',
];
const WAYSTONE_ITEMS = [
// regular waystone variants
'waystones:waystone',
'waystones:mossy_waystone',
'waystones:sandy_waystone',
'waystones:blackstone_waystone',
'waystones:deepslate_waystone',
'waystones:end_stone_waystone',
// handheld + plate
'waystones:warp_stone',
'waystones:warp_scroll',
'waystones:bound_scroll',
'waystones:return_scroll',
'waystones:warp_plate',
// sharestones (16 colors) + shards
'waystones:sharestone', // base id if registered
];
COLORS.forEach(c => {
WAYSTONE_ITEMS.push(`waystones:${c}_sharestone`);
WAYSTONE_ITEMS.push(`waystones:${c}_portstone`);
});
const COIN_ITEMS = [
'numismatics:spur',
'numismatics:bevel',
'numismatics:sundial',
'numismatics:sun',
];
JEIEvents.hideItems(event => {
[...WAYSTONE_ITEMS, ...COIN_ITEMS].forEach(id => {
try { event.hide(id); } catch (e) {
// Some IDs may not exist (e.g. base 'waystones:sharestone' isn't
// registered if only colored variants are). Swallow per-item
// failures so one bad id doesn't break the whole pass.
}
});
});
@@ -0,0 +1,24 @@
// Brass & Sigil — economy policy (recipe removal)
//
// Players can't craft Waystones items (they're distributed by the welcome
// grant -- see welcome.js -- and any replacements come from the bank
// vendor in the future). Players also can't manufacture currency: coins
// only enter circulation through the bank exchange (item-in / coin-out).
//
// Other Numismatics blocks (piggy banks, bank tellers, vendor blocks) stay
// craftable -- those are infrastructure, not currency.
ServerEvents.recipes(event => {
// Block ALL crafting of Waystones items. The welcome-grant script
// gives each new player exactly one regular waystone; any further
// recovery happens via OP /give or future bank vendor.
event.remove({ mod: 'waystones' });
// Block coin manufacturing only -- 4 denominations.
[
'numismatics:spur',
'numismatics:bevel',
'numismatics:sundial',
'numismatics:sun',
].forEach(coin => event.remove({ output: coin }));
});
@@ -0,0 +1,53 @@
// Brass & Sigil — first-join welcome grant
//
// Gives each new player exactly 1 Waystone + 1 server manual book on
// first login. Gated by a per-player persistent flag so it fires once
// even if the player relogs.
//
// Future: replace the vanilla written book with a Patchouli book in a
// custom tweak jar once we have enough content to warrant the rich
// formatting. Patchouli is already in the pack so swapping later is
// purely a content+recipe change, no mod-add needed.
const WELCOME_FLAG = 'bnsWelcomeGranted';
const MANUAL_PAGES = [
'Welcome to Brass & Sigil.\n\nThis manual covers the basics. Read it once, then keep it or toss it.',
'WAYSTONES\n\nYou have one Waystone item. Place it at your base -- it is the only one you get.\n\nNeed to travel further? Build trains, roads, or Create Aeronautics planes.',
'MONEY\n\nCoins cannot be crafted.\n\nTake valuables (diamonds etc.) to the bank at spawn. The exchange will trade them for coins.\n\nDynamic rates are planned.',
'SPAWN PLOTS\n\nComing soon: buy a small commercial plot at spawn to set up your shop. One plot per player.\n\nYour home base goes OUT in the world -- claim it with FTB Chunks (free, anywhere).',
'RULES\n\n- Be excellent to each other.\n- No griefing.\n- Lost your Waystone? Ask an OP or buy one from the bank (soon).\n- Report bugs to staff.\n\nHave fun.',
];
function giveManual(player) {
// 1.21 components-based written book: pages are filterable text
// components, title supports the same. Plain strings are accepted.
const book = Item.of('minecraft:written_book');
book.set('minecraft:written_book_content', {
title: { raw: 'Brass & Sigil Manual' },
author: 'Server Staff',
pages: MANUAL_PAGES.map(text => ({ raw: text })),
resolved: true,
});
player.give(book);
}
function giveStarterWaystone(player) {
player.give(Item.of('waystones:waystone'));
}
PlayerEvents.loggedIn(event => {
const player = event.player;
const data = player.persistentData;
if (data.getBoolean(WELCOME_FLAG)) return;
try {
giveStarterWaystone(player);
giveManual(player);
data.putBoolean(WELCOME_FLAG, true);
player.tell(Text.gold('Welcome to Brass & Sigil. Check your inventory for a Waystone and the server manual.'));
} catch (e) {
// If something goes wrong, don't set the flag -- player gets another chance.
console.error(`[bns/welcome] failed for ${player.username}: ${e}`);
}
});