pack: KubeJS Waystones policy (1-per-player + ban share/portstones)
Adds pack/overrides/kubejs/server_scripts/waystones_policy.js which: - Caps regular waystones at 1 per player. Per-player count is stored in player.persistentData and decremented on break (works correctly because restrictedWaystones = ["PLAYER"] means only owners can break). - Bans all 16 sharestone variants. They defeat the "build transport" intent (solo pair-teleport) and can be placed just outside a claim for stealth proximity access. - Bans all 16 portstone variants pending separate design review. - Leaves warp plates and warp scrolls untouched. Bumps to 0.17.0 so launcher re-syncs.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
// Brass & Sigil — Waystones placement policy
|
||||
//
|
||||
// Rules:
|
||||
// - Regular waystones (6 stone variants): 1 per player. Forces players to
|
||||
// build actual transport infrastructure (trains/roads/canals) for
|
||||
// long-distance routes instead of waystone-spamming.
|
||||
// - Sharestones (16 colors): banned. Pair-teleport between solo-placed
|
||||
// sharestones defeats the "build transport" intent, and a sharestone
|
||||
// placed just outside someone's claim gives an unrestricted teleport-
|
||||
// adjacent vector.
|
||||
// - Portstones (16 colors): banned pending separate design discussion.
|
||||
// - Warp plates: not restricted (single-block teleport pad; revisit if
|
||||
// it becomes a workaround).
|
||||
// - Warp scrolls / warp stones: untouched (consumable / cooldown-bound).
|
||||
//
|
||||
// Per-player count lives in player.persistentData.bnsWaystoneCount.
|
||||
// Decrement on break works because waystones-common.toml has
|
||||
// restrictedWaystones = ["PLAYER"] -- only the owner can break their own
|
||||
// waystone, so breaker == owner in normal play.
|
||||
|
||||
const WAYSTONE_CAP = 1;
|
||||
|
||||
const REGULAR_WAYSTONES = new Set([
|
||||
'waystones:waystone',
|
||||
'waystones:mossy_waystone',
|
||||
'waystones:sandy_waystone',
|
||||
'waystones:blackstone_waystone',
|
||||
'waystones:deepslate_waystone',
|
||||
'waystones:end_stone_waystone',
|
||||
]);
|
||||
|
||||
// Build the colored-block ban list once instead of typing 32 strings.
|
||||
const COLORS = [
|
||||
'white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime',
|
||||
'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue',
|
||||
'brown', 'green', 'red', 'black',
|
||||
];
|
||||
const BANNED_BLOCKS = new Set();
|
||||
COLORS.forEach(c => {
|
||||
BANNED_BLOCKS.add(`waystones:${c}_sharestone`);
|
||||
BANNED_BLOCKS.add(`waystones:${c}_portstone`);
|
||||
});
|
||||
|
||||
// Helper: replace the just-placed block with air and refund the item.
|
||||
function refund(event, blockId) {
|
||||
event.block.set('minecraft:air');
|
||||
if (event.player) {
|
||||
event.player.give(Item.of(blockId));
|
||||
}
|
||||
}
|
||||
|
||||
BlockEvents.placed(event => {
|
||||
const blockId = event.block.id;
|
||||
const player = event.player;
|
||||
|
||||
// Skip non-player placements (dispensers, mob events) -- nothing to refund.
|
||||
if (!player) return;
|
||||
|
||||
if (BANNED_BLOCKS.has(blockId)) {
|
||||
refund(event, blockId);
|
||||
player.tell(Text.red(
|
||||
'That block is disabled. Use a regular Waystone (1 per player) ' +
|
||||
'and build transport between distant bases.'
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (REGULAR_WAYSTONES.has(blockId)) {
|
||||
const data = player.persistentData;
|
||||
const current = data.getInt('bnsWaystoneCount');
|
||||
if (current >= WAYSTONE_CAP) {
|
||||
refund(event, blockId);
|
||||
player.tell(Text.red(
|
||||
`You already have ${WAYSTONE_CAP} waystone. Break your existing one ` +
|
||||
`to relocate, or build infrastructure to reach distant bases.`
|
||||
));
|
||||
return;
|
||||
}
|
||||
data.putInt('bnsWaystoneCount', current + 1);
|
||||
}
|
||||
});
|
||||
|
||||
BlockEvents.broken(event => {
|
||||
const blockId = event.block.id;
|
||||
if (!REGULAR_WAYSTONES.has(blockId)) return;
|
||||
const player = event.player;
|
||||
if (!player) return; // explosion / world clear -- accept count drift, rare
|
||||
const data = player.persistentData;
|
||||
const current = data.getInt('bnsWaystoneCount');
|
||||
if (current > 0) {
|
||||
data.putInt('bnsWaystoneCount', current - 1);
|
||||
}
|
||||
});
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "Brass-and-Sigil pack.lock.json - generated, do not edit by hand unless you know what you are doing",
|
||||
"name": "Brass and Sigil",
|
||||
"version": "0.16.3",
|
||||
"version": "0.17.0",
|
||||
"minecraft": "1.21.1",
|
||||
"loader": {
|
||||
"type": "neoforge",
|
||||
|
||||
Reference in New Issue
Block a user