🧱 Block#
#bs.block:help
Manage blocks, including states and NBTs, while offering advanced tools for seamless transformations.
“Architecture is the thoughtful making of space.”
—Louis Kahn
Virtual block format
To manipulate blocks and their states, Bookshelf utilizes a virtual block format stored in the block output. It’s crucial not to update it manually; instead, utilize the helper functions provided in the library.
🔧 Functions#
You can find below all functions available in this module.
Fill#
- #bs.block:fill_block
Fill all or part of a region with a specific block.
- Inputs:
Storage
bs:in block.fill_block
:- Fill block data
- block: Block to fill the region with.
- from: Starting position as a valid position string or a list of 3 elements (x, y, z).
- to: Ending position as a valid position string or a list of 3 elements (x, y, z).
- mode: Mode used to set blocks [destroy|keep|replace] (default: replace).
- limit: Limit how many blocks can be set in a single tick (default: 4096).
- masks: Determine which blocks will be replaced.
- Block mask
- block: Block acting as a filter.
- negate: Reverse the mask (default: false).
- x: Mask filter x offset (default: 0).
- y: Mask filter y offset (default: 0).
- z: Mask filter z offset (default: 0).
- Block mask
- Fill block data
- Outputs:
State: Blocks are placed in the world.
Replace the top layer of dirt by grass:
# Setup the input
data modify storage bs:in block.fill_block set value {block:"minecraft:grass_block",from:[-16,100,0],to:[-1,103,15],masks:[{block:"minecraft:dirt"},{block:"minecraft:air",y:1}]}
# Run the process
function #bs.block:fill_block
Fill an area with stone a few blocks at a time:
# Setup the input
data modify storage bs:in block.fill_block set value {block:"minecraft:stone",from:[-16,100,0],to:[-1,103,15],limit:8}
# Run the process
function #bs.block:fill_block
- #bs.block:fill_type
Fill all or part of a region with a specific block type, preserving states and NBTs.
- Inputs:
Storage
bs:in block.fill_type
:- Fill type data
- type: Block id to fill the region with.
- from: Starting position as a valid position string or a list of 3 elements (x, y, z).
- to: Ending position as a valid position string or a list of 3 elements (x, y, z).
- mode: Mode used to set blocks [destroy|keep|replace] (default: replace).
- limit: Limit how many blocks can be set in a single tick (default: 4096).
- masks: Determine which blocks will be replaced.
- Block mask
- block: Block acting as a filter.
- negate: Reverse the mask (default: false).
- x: Mask filter x offset (default: 0).
- y: Mask filter y offset (default: 0).
- z: Mask filter z offset (default: 0).
- Block mask
- Fill type data
- Outputs:
State: Blocks are placed in the world.
Replace oak stairs with spruce stairs while preserving states:
# Setup the input
data modify storage bs:in block.fill_type set value {type:"minecraft:spruce_stairs",from:[-16,100,0],to:[-1,103,15],masks:[{block:"minecraft:oak_stairs"}]}
# Run the process
function #bs.block:fill_type
- #bs.block:fill_random
Fill all or part of a region with random blocks or types.
- Inputs:
Storage
bs:in block.fill_random
:- Fill random data
- entries: List of entries to pick from randomly.
- Block or type entry
- block | type: Block or type to fill the region with.
- weight: Determine the likelihood of selecting the entry (default: 1).
- Block or type entry
- from: Starting position as a valid position string or a list of 3 elements (x, y, z).
- to: Ending position as a valid position string or a list of 3 elements (x, y, z).
- mode: Mode used to set blocks [destroy|keep|replace] (default: replace).
- limit: Limit how many blocks can be set in a single tick (default: 4096).
- masks: Determine which blocks will be replaced.
- Block mask
- block: Block acting as a filter.
- negate: Reverse the mask (default: false).
- x: Mask filter x offset (default: 0).
- y: Mask filter y offset (default: 0).
- z: Mask filter z offset (default: 0).
- Block mask
- entries: List of entries to pick from randomly.
- Fill random data
- Outputs:
State: Blocks are placed in the world.
Randomly fill an area with stone or air:
# Setup the input
data modify storage bs:in block.fill_random set value {entries:[{block:"minecraft:stone"},{block:"minecraft:air"}],from:[-16,100,0],to:[-1,103,15]}
# Run the process
function #bs.block:fill_random
Credits: Aksiome
Get#
- #bs.block:get_block
Get all data related to the block at the current location, including its state and NBTs.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position to get block data from.- Outputs:
Storage
bs:out block
:- [readonly] Block data
- group: Blocks within the same group share the same possible state (e.g., stairs).
- block: Full string representation of the block
type[state]{nbt}
. - item: Item string id associated with the block, if it exists.
- type: String representation of the id (e.g.,
minecraft:stone
). - state: Represent the state of a block (e.g.,
[shape=straight]
). - nbt: Data tags used by block entities or an empty string.
- properties: Block state as properties (used by entities like falling blocks).
- [readonly] Block data
Get all data related to a block:
# Run the get function on a block
execute positioned ~ ~ ~ run function #bs.block:get_block
# See the result
data get storage bs:out block
- #bs.block:get_type
Get the block type at the current location. Although states, NBTs, and properties will be empty, state transformation functions are still available.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position to get block data from.- Outputs:
Storage
bs:out block
:- [readonly] Block data
- group: Blocks within the same group share the same possible state (e.g., stairs).
- block: Full string representation of the block (only the type).
- item: Item string id associated with the block, if it exists.
- type: String representation of the id (e.g.,
minecraft:stone
). - state: Represent the state of a block [empty string].
- nbt: Data tags used by block entities [empty string].
- properties: Block state as properties [empty compound].
- [readonly] Block data
Get only type data related to a block (no property value is selected):
# Run the get function on a block
execute positioned ~ ~ ~ run function #bs.block:get_type
# See the result
data get storage bs:out block
Read-only output
The bs:out block
output is intended to be read-only. Modifying parts manually could lead to potential bugs. That’s why the module provides numerous functions capable of making modifications to the output while preserving its integrity.
Credits: Aksiome, theogiraudet
Manage state#
- #bs.block:keep_properties {properties:[]}
Filter properties to keep only the desired ones. This function acts on the virtual block format stored in the block output.
- Inputs:
Function macro:
- Arguments
- properties: List of properties to keep.
- Property data
- name: Name of the property (e.g.,
shape
).
- name: Name of the property (e.g.,
- Property data
- properties: List of properties to keep.
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Keep only the facing and shape properties:
# Once (on stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Run the transformation
function #bs.block:keep_properties {properties:[{name:"facing"},{name:"shape"}]}
# See the result
data get storage bs:out block.block
- #bs.block:merge_properties {properties:[]}
Merge state properties from the current location into the output. The merge occurs if the syntax is correct, regardless of logical coherence (e.g., using ‘age’ for different plants). This function acts on the virtual block format stored in the block output.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Location of the block that act as input.Function macro:
- Arguments
- properties: List of properties to merge.
- Property data
- name: Name of the property (e.g.,
shape
).
- name: Name of the property (e.g.,
- Property data
- properties: List of properties to merge.
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Merge the facing of a block onto stairs:
# Once (on stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Run the transformation (on a block with facing)
execute positioned ~ ~ ~ run function #bs.block:merge_properties {properties:[{name:"facing"}]}
# See the result
data get storage bs:out block.block
- #bs.block:remove_properties {properties:[]}
Filter properties by removing the undesired ones. This function acts on the virtual block format stored in the block output.
- Inputs:
Function macro:
- Arguments
- properties: List of properties to remove.
- Property data
- name: Name of the property (e.g.,
shape
).
- name: Name of the property (e.g.,
- Property data
- properties: List of properties to remove.
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Remove the facing and shape properties:
# Once (on stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Run the transformation
function #bs.block:remove_properties {properties:[{name:"facing"},{name:"shape"}]}
# See the result
data get storage bs:out block.block
- #bs.block:replace_properties {properties:[]}
Replace property values. Invalid values will not be replaced. This function acts on the virtual block format stored in the block output.
- Inputs:
Function macro:
- Arguments
- properties: List of properties to replace.
- Property data
- name: Name of the property (e.g.,
facing
). - value: Value of the property (e.g.,
east
).
- name: Name of the property (e.g.,
- Property data
- properties: List of properties to replace.
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Replace the facing property value:
# Once (on stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Run the transformation
function #bs.block:replace_properties {properties:[{name:"facing",value:"east"}]}
# See the result
data get storage bs:out block.block
- #bs.block:shift_properties {properties:[]}
Shift properties by any amount, allowing cycling through their values. This function acts on the virtual block format stored in the block output.
- Inputs:
Function macro:
- Arguments
- properties: List of properties to shift.
- Property data
- name: Name of the property (e.g.,
shape
). - by: Shift amount (defaults to 1).
- name: Name of the property (e.g.,
- Property data
- properties: List of properties to shift.
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Shift the facing property value by 2:
# Once (on stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Run the transformation
function #bs.block:shift_properties {properties:[{name:"facing",by:2}]}
# See the result
data get storage bs:out block.block
Credits: Aksiome
Manage type#
- #bs.block:replace_type {type:<value>}
Replace the block type while trying to conserve the state. State is preserved only if the group of the output matches the input. This function acts on the virtual block format stored in the block output.
- Inputs:
Function macro:
- Arguments
- type: String representation of the id (e.g.,
minecraft:stone
).
- type: String representation of the id (e.g.,
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Replace oak stairs with spruce stairs, preserving the current state:
# Once (on oak_stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Replace type data
function #bs.block:replace_type {type:"minecraft:spruce_stairs"}
# See the result
data get storage bs:out block.block
- #bs.block:map_type {type:<value>,mapping_registry:<value>}
Swap related block types while ensuring coherent replacements within the defined mapping registry. A mapping registry is defined as follows:
data modify storage bs:const block.mapping_registry.bs.colors set value [ \ { set: "wool", attrs: ["red"], type: "minecraft:red_wool" }, \ { set: "wool", attrs: ["green"], type: "minecraft:green_wool" }, \ { set: "carpet", attrs: ["red"], type: "minecraft:red_carpet" }, \ { set: "carpet", attrs: ["green"], type: "minecraft:green_carpet" }, \ ]
This function operates on the virtual block format stored in the block output. It replaces the type in the output with one that belongs to the same set and better matches the attributes of the inputted type.
For example, with the above mapping registry: if the input is
minecraft:red_wool
(attrs:[“red”]), and the virtual block type isminecraft:green_carpet
(set:“carpet”), the resulting block will beminecraft:red_carpet
(set:“carpet”,attrs:[“red”]).Bookshelf includes two predefined mapping registries (
bs.shapes
andbs.colors
). If these are insufficient, you can create your own.- Inputs:
Function macro:
- Arguments
- type: String representation of the id (e.g.,
minecraft:stone
). - mapping_registry: A path to the mapping registry used for the replacement (e.g.,
bs.shapes
).
- type: String representation of the id (e.g.,
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Return: Whether a type was found and the replacement occurred.
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Replace all oak-related blocks with spruce ones (the function replaces the oak stairs block with a spruce stairs block):
# Once (on oak_stairs)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Replace type data
function #bs.block:map_type { type: "minecraft:spruce_planks", mapping_registry: "bs.shapes" }
# See the result
data get storage bs:out block.block
- #bs.block:mix_type {type:<value>,mapping_registry:<value>}
Experimental
This function may sometimes behave unpredictably due to the arbitrary nature of block relationship definitions. Additionally, while the provided registries aim to cover a wide range of blocks, they are handcrafted and therefore not exhaustive.
Mix block types while ensuring coherent replacements within the defined mapping registry. A mapping registry is defined as follows:
data modify storage bs:const block.mapping_registry.bs.colors set value [ \ { set: "cube", attrs: ["stone"], type: "minecraft:stone" }, \ { set: "cube", attrs: ["brick"], type: "minecraft:bricks" }, \ { set: "cube", attrs: ["stone", "brick"], type: "minecraft:stone_bricks" }, \ { set: "stairs", attrs: ["stone"], type: "minecraft:stone_stairs" }, \ { set: "stairs", attrs: ["brick"], type: "minecraft:brick_stairs" }, \ { set: "stairs", attrs: ["stone","brick"], type: "minecraft:stone_brick_stairs" }, \ ]
This function operates on the virtual block format stored in the block output. It replaces the type in the output with one that belongs to the same set and better matches the attributes of both the output and input types while prioritizing the input type.
For example, with the above mapping registry: if the input is
minecraft:bricks
(attrs:[“brick”]), and the virtual block type isminecraft:stone_stairs
(set:“stairs”,attrs:[“stone”]), the resulting block will beminecraft:stone_brick_stairs
(set:“stairs”,attrs:[“stone”,“brick”]).Bookshelf includes two predefined mapping registries (
bs.shapes
andbs.colors
). If these are insufficient, you can create your own.- Inputs:
Function macro:
- Arguments
- type: String representation of the id (e.g.,
minecraft:stone
). - mapping_registry: A path to the mapping registry used for the replacement (e.g.,
bs.shapes
).
- type: String representation of the id (e.g.,
Storage
bs:out block
: There’s no need for manual specification; rather, employ the relevant functions, such asget_block
.- Arguments
- Outputs:
Return: Whether a type was found and the replacement occurred.
Storage
bs:out block
: Theblock
,state
andproperties
are updated to reflect this change.
Mix a mossy cobblestone block with bricks resulting in a mossy stone bricks block:
# Once (on mossy_cobblestone)
execute positioned ~ ~ ~ run function #bs.block:get_block
# Replace type data
function #bs.block:mix_type { type: "minecraft:bricks", mapping_registry: "bs.shapes" }
# See the result
data get storage bs:out block.block
- #bs.block:lookup_item {item:<value>}
Get block data from the given item string id.
- Inputs:
Function macro:
- Arguments
- item: Item string id associated to a block.
- Arguments
- Outputs:
Storage
bs:out block
: Equivalent to the#bs.block:get_type
function.
Get block data for the stone item:
# Get block type data
function #bs.block:lookup_item {item:"minecraft:stone"}
# See the result
data get storage bs:out block.block
Important
Minecraft does not perfectly map between blocks and items. Some items may correspond to multiple blocks, and this function will only return one of them.
- #bs.block:lookup_type {type:<value>}
Get block data from the given type string id.
- Inputs:
Function macro:
- Arguments
- type: Type string id associated to a block.
- Arguments
- Outputs:
Storage
bs:out block
: Equivalent to the#bs.block:get_type
function.
Get block data for the stone type:
# Get block type data
function #bs.block:lookup_type {type:"minecraft:stone"}
# See the result
data get storage bs:out block.block
Credits: Aksiome
Match#
- #bs.block:match
Determine if the block at the specified location matches the provided one.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Location of the block to check.Storage
bs:in block.match.block
: Full string representation of the block to check against.- Outputs:
Return: Whether the check is a success or a failure (1 or 0).
Check that the block at 0 0 0 matches the block at 0 1 0:
# Get block data at 0 0 0
execute positioned 0 0 0 run function #bs.block:get_block
# Setup the input
data modify storage bs:in block.match.block set from storage bs:out block.block
# Run a command if it's a match
execute positioned 0 1 0 if function #bs.block:match run say It's a match
Credits: Aksiome, theogiraudet
Set#
- #bs.block:set_block
Place a block at the current location.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position to set the block to.Storage
bs:in block.set_block
:- Set block data
- block: Full string representation of the block to set.
- mode: Mode used to set the block [destroy|keep|replace] (default: replace).
- Set block data
- Outputs:
State: A block is placed in the world.
Place a block of stone at 0 0 0 by destroying the existing one:
# Setup the input
data modify storage bs:in block.set_block set value {block:"minecraft:stone",mode:"destroy"}
# Run the function
execute positioned 0 0 0 run function #bs.block:set_block
- #bs.block:set_type
Replace the block type at the current location while trying to conserve its state and NBTs.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position to set the block to.Storage
bs:in block.set_type
:- Set type data
- type: String representation of the block id to set.
- mode: Mode used to set the block [destroy|keep|replace] (default: replace).
- Set type data
- Outputs:
State: A block is placed in the world.
Replace any stairs with oak stairs, preserving the current state:
# Setup the input
data modify storage bs:in block.set_type.type set value "minecraft:oak_stairs"
# Run the function
execute positioned 0 0 0 run function #bs.block:set_type
Credits: Aksiome, theogiraudet
Produce#
- #bs.block:spawn_block_display
Spawn a block display representing the given block.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position where the entity will be summoned.Storage
bs:in block.spawn_block_display
:- Block display data
- type: Block type (similar to block output).
- properties: Block properties (similar to block output).
- extra_nbt: Additional NBTs to summon the entity with.
- Block display data
- Outputs:
State: The entity is summoned.
Summon a block display using the block at 0 0 0:
# Get block data
execute positioned 0 0 0 run function #bs.block:get_block
# Setup the input
data modify storage bs:in block.spawn_block_display set from storage bs:out block
# Summon the block display
function #bs.block:spawn_block_display
- #bs.block:spawn_falling_block
Spawn a falling block representing the given block.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position where the entity will be summoned.Storage
bs:in block.spawn_falling_block
:- Falling block data
- type: Block type (similar to block output).
- properties: Block properties (similar to block output).
- extra_nbt: Additional NBTs to summon the entity with.
- Falling block data
- Outputs:
State: The entity is summoned.
Summon a falling block using the block at 0 0 0:
# Get block data
execute positioned 0 0 0 run function #bs.block:get_block
# Setup the input
data modify storage bs:in block.spawn_falling_block set from storage bs:out block
# Summon the block display
function #bs.block:spawn_falling_block
- #bs.block:spawn_solid_block_display
Spawn a block display with a hitbox, representing the given block.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position where the entity will be summoned.Storage
bs:in block.spawn_solid_block_display
:- Block display data
- type: Block type (similar to block output).
- properties: Block properties (similar to block output).
- extra_nbt: Additional NBTs to summon the entity with.
- Block display data
- Outputs:
State: The entity is summoned.
Summon a block display with a hitbox using the block at 0 0 0:
# Get block data
execute positioned 0 0 0 run function #bs.block:get_block
# Setup the input
data modify storage bs:in block.spawn_solid_block_display set from storage bs:out block
# Summon the block display
function #bs.block:spawn_solid_block_display
- #bs.block:emit_block_particle
Emit block particle of the given block.
- Inputs:
Execution
at <entity>
orpositioned <x> <y> <z>
: Position where the particle will be emitted.Storage
bs:in block.emit_block_particle
:- Block particle data
- type: Block type (similar to block output).
- properties: Block properties (similar to block output).
- delta: X Y Z coordinates, the motion value of the particle. Similar to the /particle command.
- speed: Speed of the particle. Similar to the /particle command.
- count: Number of particle. Similar to the /particle command.
- Block particle data
- Outputs:
State: The particle is emitted.
Emit the particle of the block at 0 0 0:
# Get block data
execute positioned 0 0 0 run function #bs.block:get_block
# Setup the input
data modify storage bs:in block.emit_block_particle set from storage bs:out block
data modify storage bs:in block.emit_block_particle merge value { delta: "0 0 0", speed: 5, count: 30 }
# Emit the block particle
function #bs.block:emit_block_particle
Credits: Aksiome, theogiraudet
🎓 Custom mapping registry#
This module allows you to create a personalized mapping registry tailored to your specific needs.
To create a new registry, you need to define an array within the bs:const block.mapping_registry
storage. Each new registry should be namespaced, and each element must include set
, attrs
, and type
. Here’s how you can define a new mapping registry:
data modify storage bs:const block.mapping_registry.<namespace>.<name> [
{ set: "cube", attrs: ["oak"], type: "minecraft:oak_planks" }, \
{ set: "cube", attrs: ["spruce"], type: "minecraft:spruce_planks" }, \
\
{ set: "stairs", attrs: ["oak"], type: "minecraft:oak_stairs" }, \
{ set: "stairs", attrs: ["spruce"], type: "minecraft:spruce_stairs" }, \
\
{ set: "slab", attrs: ["oak"], type: "minecraft:oak_slab" }, \
{ set: "slab", attrs: ["spruce"], type: "minecraft:spruce_slab" }, \
]
💬 Did it help you?
Feel free to leave your questions and feedbacks below!