From 5d9daa471dd2e37bf510acda4bc838c796b4319d Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Mon, 14 Apr 2025 12:18:35 -0700 Subject: [PATCH] easyPlace feature-complete --- scripts/classes/BlockInfo.js | 27 ++++++++++++++++++++------- scripts/rules/easyPlace.js | 26 ++++++++++---------------- scripts/utils.js | 17 +++++++++++++++-- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/scripts/classes/BlockInfo.js b/scripts/classes/BlockInfo.js index c93e56b..844c391 100644 --- a/scripts/classes/BlockInfo.js +++ b/scripts/classes/BlockInfo.js @@ -1,5 +1,6 @@ -import { system, world } from '@minecraft/server'; +import { GameMode, system, world } from '@minecraft/server'; import { Raycaster } from '../classes/Raycaster'; +import { fetchMatchingItemSlot } from '../utils'; class BlockInfo { static shownToLastTick = new Set(); @@ -20,23 +21,35 @@ class BlockInfo { } if (!block) return; - player.onScreenDisplay.setActionBar({ text: this.getFormattedBlockInfo(block.permutation) }); + player.onScreenDisplay.setActionBar({ text: this.getFormattedBlockInfo(player, block.permutation) }); this.shownToLastTick.add(player.id); } - static getFormattedBlockInfo(block) { - const header = 'Structure:\n' + static getFormattedBlockInfo(player, block) { + return 'Structure:' + this.getSupplyMessage(player, block) + '\n' + this.getBlockMessage(block); + } + + static getBlockMessage(block) { if (!block) - return header + '§7Unknown'; + return '§7Unknown'; const states = block.getAllStates(); if (Object.keys(states).length === 0) - return header + `§a${block.type.id}`; - return header + `§a${block.type.id}\n§7${this.getFormattedStates(states)}`; + return `§a${block.type.id}`; + else + return `§a${block.type.id}\n§7${this.getFormattedStates(states)}`; } static getFormattedStates(states) { return Object.entries(states).map(([key, value]) => `§7${key}: §3${value}`).join('\n'); } + + static getSupplyMessage(player, block) { + const itemStack = fetchMatchingItemSlot(player, block.getItemStack()?.typeId); + const isInSurvival = player.getGameMode() === GameMode.survival; + if (!itemStack && isInSurvival) + return ' §c[No Supply]'; + return ''; + } } system.runInterval(() => BlockInfo.onTick()); \ No newline at end of file diff --git a/scripts/rules/easyPlace.js b/scripts/rules/easyPlace.js index 0c88a38..bb33e5d 100644 --- a/scripts/rules/easyPlace.js +++ b/scripts/rules/easyPlace.js @@ -4,6 +4,7 @@ import { BlockPermutation, EntityComponentTypes, GameMode, ItemStack, system, wo import { structureCollection } from '../classes/StructureCollection'; import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions, blockIdToItemStackMap } from '../data'; +import { fetchMatchingItemSlot } from '../utils'; const ACTION_SLOT = 35; @@ -16,7 +17,7 @@ const easyPlace = new Rule({ extension.addRule(easyPlace); function onPlayerPlaceBlock(event) { - const { player, block } = event; + const { player, block, permutationBeingPlaced } = event; if (!player || !block || !hasActionItemInCorrectSlot(player)) return; const structureBlock = structureCollection.fetchStructureBlock(block.dimension.id, block.location); if (!structureBlock) @@ -33,8 +34,8 @@ function hasActionItemInCorrectSlot(player) { } function tryPlaceBlock(event, player, block, structureBlock) { - if (isBannedBlock(player, structureBlock)) - preventAction(event, player); + if (shouldPreventAction(player, structureBlock)) + return preventAction(event, player); structureBlock = tryConvertBannedToValidBlock(structureBlock); if (player.getGameMode() === GameMode.creative) { placeBlock(block, structureBlock); @@ -44,6 +45,10 @@ function tryPlaceBlock(event, player, block, structureBlock) { } } +function shouldPreventAction(player, structureBlock) { + return isBannedBlock(player, structureBlock); +} + function preventAction(event, player) { event.cancel = true; system.run(() => { @@ -92,6 +97,8 @@ function tryPlaceBlockSurvival(event, player, block, structureBlock) { if (itemSlotToUse) { event.cancel = true; placeBlock(block, structureBlock, itemSlotToUse); + } else { + preventAction(event, player); } } @@ -101,19 +108,6 @@ function getPlaceableItemStack(structureBlock) { return newItemId ? new ItemStack(newItemId) : structureBlock.getItemStack(); } -function fetchMatchingItemSlot(player, itemToMatchId) { - if (!itemToMatchId) - return void 0; - const inventory = player.getComponent(EntityComponentTypes.Inventory)?.container; - if (!inventory) - return void 0; - for (let index = 0; index < inventory.size; index++) { - const itemSlot = inventory.getSlot(index); - if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId) - return itemSlot; - } -} - function placeBlock(block, structureBlock, itemSlot) { system.run(() => { if (itemSlot) { diff --git a/scripts/utils.js b/scripts/utils.js index 49caa4e..8505af9 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -1,4 +1,4 @@ -import { system } from '@minecraft/server'; +import { system, EntityComponentTypes } from '@minecraft/server'; import { FormCancelationReason } from '@minecraft/server-ui'; export async function forceShow(player, form, timeout = Infinity) { @@ -11,4 +11,17 @@ export async function forceShow(player, form, timeout = Infinity) { return response; } throw new Error("Menu timed out."); -}; \ No newline at end of file +}; + +export function fetchMatchingItemSlot(entity, itemToMatchId) { + if (!itemToMatchId) + return void 0; + const inventory = entity.getComponent(EntityComponentTypes.Inventory)?.container; + if (!inventory) + return void 0; + for (let index = 0; index < inventory.size; index++) { + const itemSlot = inventory.getSlot(index); + if (itemSlot.hasItem() && itemSlot?.typeId === itemToMatchId) + return itemSlot; + } +} \ No newline at end of file