Bedrock Snippets

Precise Interaction

View Source

precise_interaction > bp > scripts > blocks > double_flower_pot.js

import { system, ItemStack, EquipmentSlot, GameMode } from "@minecraft/server";
import SelectionBoxes from "../utilities/selection_boxes"; // Import the SelectionBoxes class to use it

// Support orientation along both horizontal axes
const pots = {
    x: new SelectionBoxes(
        { origin: [-7, 0, -3], size: [6, 6, 6] },
        { origin: [1, 0, -3], size: [6, 6, 6] }
    ),
    z: new SelectionBoxes(
        { origin: [-3, 0, -7], size: [6, 6, 6] },
        { origin: [-3, 0, 1], size: [6, 6, 6] }
    ),
};

// The state value and sound associated with each plant
const plants = {
    "minecraft:dandelion": {
        value: "dandelion",
        sound: "dig.grass",
    },
    "minecraft:cactus": {
        value: "cactus",
        sound: "dig.cloth",
    },
};

const getAxis = (direction) =>
    direction === "west" || direction === "east" ? "z" : "x";

// Get the selected pot for the appropriate axis
function getSelectedPot(block, faceLocation) {
    const direction = block.permutation.getState(
        "minecraft:cardinal_direction"
    );
    const axis = getAxis(direction);

    return pots[axis].getSelected(faceLocation);
}

const isPotOccupied = (block, pot) =>
    block.permutation.getState(`wiki:pot_${pot}_plant`) !== "none";

const setPotPlant = (block, pot, plant) =>
    block.setPermutation(
        block.permutation.withState(`wiki:pot_${pot}_plant`, plant)
    );

/** @type {import("@minecraft/server").BlockCustomComponent} */
const BlockDoubleFlowerPotComponent = {
    onPlayerInteract({ block, dimension, faceLocation, player }) {
        if (!player) return;

        const equippable = player.getComponent("minecraft:equippable");
        if (!equippable) return;

        const mainhand = equippable.getEquipmentSlot(EquipmentSlot.Mainhand);

        const selectedPot = getSelectedPot(block, faceLocation);
        if (selectedPot === undefined) return;

        if (mainhand.hasItem() && !isPotOccupied(block, selectedPot)) {
            const plant = plants[mainhand.typeId];
            if (!plant) return;

            if (player.getGameMode() !== GameMode.creative) {
                if (mainhand.amount > 1) mainhand.amount--;
                else mainhand.setItem(undefined);
            }

            setPotPlant(block, selectedPot, plant.value);
            dimension.playSound(plant.sound, block.center(), { volume: 0.5 });
        } else if (!mainhand.hasItem() && isPotOccupied(block, selectedPot)) {
            const plantValue = block.permutation.getState(
                `wiki:pot_${selectedPot}_plant`
            );
            const plantId = Object.keys(plants).find(
                (key) => plants[key].value === plantValue
            );

            setPotPlant(block, selectedPot, "none");
            dimension.playSound("random.pop", block.center());

            mainhand.setItem(new ItemStack(plantId));
        }
    },
    onPlayerBreak: releasePlants,
};

system.beforeEvents.startup.subscribe(({ blockComponentRegistry }) => {
    blockComponentRegistry.registerCustomComponent(
        "wiki:double_flower_pot",
        BlockDoubleFlowerPotComponent
    );
});

// -------------------------------
//  Release plants on destruction
// -------------------------------
function releasePlants({ block, brokenBlockPermutation, dimension }) {
    const states = brokenBlockPermutation.getAllStates();

    // Array of plant state values e.g. ["cactus", "dandelion"]
    const storedPlants = Object.entries(states)
        .filter(
            ([state, value]) => state.startsWith("wiki:pot") && value !== "none"
        )
        .map(([state, value]) => value);

    if (storedPlants.length === 0) return;

    // Create an item entity for every potted plant
    for (const plant of storedPlants) {
        const plantId = Object.keys(plants).find(
            (key) => plants[key].value === plant
        );

        dimension.spawnItem(new ItemStack(plantId), block.center());
    }
}
Copied to Clipboard