Custom Trees
FORMAT & MIN ENGINE VERSION 1.21.40
This tutorial assumes an advanced understanding of blocks. Check out the blocks guide before starting.
Creating your own tree with decaying leaves is complex, but possible! Follow this tutorial and you'll have your own in no time.
Features:
- Decaying leaves
- Tree Feature compatible
- Leaves will drop itself when broken by a shear
- Leaves don't decay if placed by player
- Logs are strippable and rotatable
- Stripping logs is compatible with tools from other add-ons (if they have the
minecraft:is_axe
tag) - Saplings can be bonemealed and grow into a tree
Decaying Leaves
You will notice straight away that our custom leaves have a long list to search for a vanilla log/custom log by its block tag, although the code example uses the custom logs for this tutorial. The value is 4 and this method is used to search for the nearest log in a circular radius.
Our custom leaves disables ticking when placed by the player which doesn't make the leaves decay and this removes the requirements for another duplicate leave block.
Basic JSON
Let's get started. We'll start with the JSON code for the leaf block.
{
"format_version": "1.21.40",
"minecraft:block": {
"description": {
"identifier": "wiki:custom_leaves"
},
"components": {
"tag:wiki:custom_leaves": {},
"minecraft:loot": "loot_tables/empty.json",
"minecraft:geometry": {
"identifier": "minecraft:geometry.full_block"
},
"minecraft:custom_components": [
"wiki:leaves_stop_decay",
"wiki:leaves_on_destroyed",
"wiki:leaves_check"
],
"minecraft:destructible_by_explosion": {
"explosion_resistance": 1
},
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 0.3
},
"minecraft:map_color": "#DDDDDD",
"minecraft:light_dampening": 0,
"minecraft:material_instances": {
"*": {
"texture": "custom_leaves",
"render_method": "blend"
}
}
}
}
}
Block States
We have defined the basics our custom leaf blocks need. Our custom leaf is still missing a few features such as states, permutations and the JS code for the custom components. Let's add the following block states.
"states": {
"wiki:decay_tier": [4, 3, 2, 1, 0], // Distance in blocks to find the log
"wiki:should_decay": [true, false], // Used when placed by the player or with features
"wiki:opaque": [false, true] // Optional; makes the leaves opaque when surrounded
}
Permutations
Let's add our permutation code that will help shape our block's behaviour.
"permutations": [
{
"condition": "q.block_state('wiki:decay_tier') == 0",
"components": {
"minecraft:custom_components": [
"wiki:leaves_decay"
],
"tag:decay_tier_0": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 1",
"components": {
"tag:decay_tier_1": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 2",
"components": {
"tag:decay_tier_2": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 3",
"components": {
"tag:decay_tier_3": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 4",
"components": {
"tag:decay_tier_4": {}
}
},
{
"condition": "q.block_state('wiki:opaque')",
"components": {
"minecraft:material_instances": {
"*": {
"texture": "custom_leaves",
"render_method": "opaque"
}
}
}
}
]
Code
{
"format_version": "1.21.40",
"minecraft:block": {
"description": {
"identifier": "wiki:custom_leaves",
"states": {
"wiki:decay_tier": [4, 3, 2, 1, 0], // Distance in blocks to find the log
"wiki:should_decay": [true, false], // Used when placed by the player or with features
"wiki:opaque": [false, true] // Optional; makes the leaves opaque when surrounded
}
},
"components": {
"tag:wiki:custom_leaves": {},
"minecraft:loot": "loot_tables/empty.json",
"minecraft:geometry": {
"identifier": "minecraft:geometry.full_block"
},
"minecraft:custom_components": [
"wiki:leaves_stop_decay",
"wiki:leaves_on_destroyed",
"wiki:leaves_check"
],
"minecraft:destructible_by_explosion": {
"explosion_resistance": 1
},
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 0.3
},
"minecraft:map_color": "#DDDDDD",
"minecraft:light_dampening": 0,
"minecraft:material_instances": {
"*": {
"texture": "custom_leaves",
"render_method": "blend"
}
}
},
"events": {
// Defines the loot for the tool
"wiki:on_destroyed": {
"sequence": [
{
"condition": "q.is_item_name_any('slot.weapon.mainhand','minecraft:shears')",
"spawn_loot": {
"table": "loot_tables/blocks/custom_leaves_shears.json"
}
},
{
"condition": "!q.is_item_name_any('slot.weapon.mainhand','minecraft:shears')",
"spawn_loot": {
"table": "loot_tables/blocks/custom_leaves.json"
}
}
]
},
// Checks for the log
"wiki:check": {
"sequence": [
{
"condition": "q.block_state('wiki:should_decay')",
"set_block_state": {
"wiki:decay_tier": "(q.block_neighbor_has_any_tag(0,0,-1,'log') || q.block_neighbor_has_any_tag(0,0,1,'log') || q.block_neighbor_has_any_tag(-1,0,0,'log') || q.block_neighbor_has_any_tag(1,0,0,'log') || q.block_neighbor_has_any_tag(0,-1,0,'log') || q.block_neighbor_has_any_tag(0,1,0,'log')) ? 4 : ((q.block_neighbor_has_any_tag(0,0,-1,'decay_tier_4') || q.block_neighbor_has_any_tag(0,0,1,'decay_tier_4') || q.block_neighbor_has_any_tag(-1,0,0,'decay_tier_4') || q.block_neighbor_has_any_tag(1,0,0,'decay_tier_4') || q.block_neighbor_has_any_tag(0,-1,0,'decay_tier_4') || q.block_neighbor_has_any_tag(0,1,0,'decay_tier_4')) ? 3 : ( (q.block_neighbor_has_any_tag(0,0,-1,'decay_tier_3') || q.block_neighbor_has_any_tag(0,0,1,'decay_tier_3 ') || q.block_neighbor_has_any_tag(-1,0,0,'decay_tier_3') || q.block_neighbor_has_any_tag(1,0,0,'decay_tier_3') || q.block_neighbor_has_any_tag(0,-1,0,'decay_tier_3') || q.block_neighbor_has_any_tag(0,1,0,'decay_tier_3')) ? 2 : ( (q.block_neighbor_has_any_tag(0,0,-1,'decay_tier_2') || q.block_neighbor_has_any_tag(0,0,1,'decay_tier_2') || q.block_neighbor_has_any_tag(-1,0,0,'decay_tier_2') || q.block_neighbor_has_any_tag(1,0,0,'decay_tier_2') || q.block_neighbor_has_any_tag(0,-1,0,'decay_tier_2') || q.block_neighbor_has_any_tag(0,1,0,'decay_tier_2')) ? 1 : 0 ) ) )"
}
},
{
"set_block_state": {
"wiki:opaque": "q.block_neighbor_has_any_tag(0,0,-1,'log','stone','custom_leaves') && q.block_neighbor_has_any_tag(0,0,1,'log','stone','custom_leaves') && q.block_neighbor_has_any_tag(0,1,0,'log','stone','custom_leaves') && q.block_neighbor_has_any_tag(0,-1,0,'log','stone','custom_leaves') && q.block_neighbor_has_any_tag(-1,0,0,'log','stone','custom_leaves') && q.block_neighbor_has_any_tag(1,0,0,'log','stone','custom_leaves')"
}
}
]
},
// When placed
"wiki:stop_decay": {
"set_block_state": {
"wiki:should_decay": false
}
},
// When decayed
"wiki:decay": {
"die": {},
"spawn_loot": {
"table": "loot_tables/blocks/custom_leaves.json"
}
}
},
"permutations": [
{
"condition": "q.block_state('wiki:decay_tier') == 0",
"components": {
"minecraft:random_ticking": {
"on_tick": {
"event": "wiki:decay"
}
},
"tag:decay_tier_0": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 1",
"components": {
"tag:decay_tier_1": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 2",
"components": {
"tag:decay_tier_2": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 3",
"components": {
"tag:decay_tier_3": {}
}
},
{
"condition": "q.block_state('wiki:decay_tier') == 4",
"components": {
"tag:decay_tier_4": {}
}
},
{
"condition": "q.block_state('wiki:opaque')",
"components": {
"minecraft:material_instances": {
"*": {
"texture": "custom_leaves",
"render_method": "opaque"
}
}
}
}
]
}
}
Custom Log
Code
{
"format_version": "1.21.40",
"minecraft:block": {
"description": {
"identifier": "wiki:custom_log",
"menu_category": {
"category": "nature",
"group": "itemGroup.name.log"
},
"states": {
// Log direction state
"wiki:axis": [0, 1, 2]
}
},
"components": {
"tag:log": {},
"minecraft:unit_cube": {},
// Sets different textures for sides and top/bottom of log
"minecraft:material_instances": {
"*": {
"texture": "custom_log"
},
"ends": {
"texture": "custom_log_top"
},
"up": "ends",
"down": "ends"
},
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 1
},
// Sets log rotation on player placing
"minecraft:on_player_placing": {
"event": "wiki:set_axis"
},
// Make log strippable
"minecraft:on_interact": {
"condition": "q.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_axe')",
"event": "wiki:strip"
}
},
"events": {
"wiki:set_axis": {
"set_block_state": {
"wiki:axis": "Math.floor(q.block_face / 2)"
}
},
"wiki:strip": {
"sequence": [
{
"run_command": {
"command": "playsound hit.wood @a ~~~"
},
// Damages axe of player who stripped the log
"damage": {
"type": "durability",
"amount": 1,
"target": "item"
}
},
{
"condition": "q.block_state('wiki:axis') == 0",
"run_command": {
"command": "setblock ~~~ wiki:custom_stripped_log [\"wiki:axis\"=0]"
}
},
{
"condition": "q.block_state('wiki:axis') == 1",
"run_command": {
"command": "setblock ~~~ wiki:custom_stripped_log [\"wiki:axis\"=1]"
}
},
{
"condition": "q.block_state('wiki:axis') == 2",
"run_command": {
"command": "setblock ~~~ wiki:custom_stripped_log [\"wiki:axis\"=2]"
}
}
]
}
},
"permutations": [
{
"condition": "q.block_state('wiki:axis') == 0",
"components": {
"minecraft:transformation": { "rotation": [0, 0, 0] }
}
},
{
"condition": "q.block_state('wiki:axis') == 1",
"components": {
"minecraft:transformation": { "rotation": [90, 0, 0] }
}
},
{
"condition": "q.block_state('wiki:axis') == 2",
"components": {
"minecraft:transformation": { "rotation": [0, 0, 90] }
}
}
]
}
}
Stripped Log
Here all components are the same
Code
{
"format_version": "1.21.40",
"minecraft:block": {
"description": {
"identifier": "wiki:custom_stripped_log",
"menu_category": {
"category": "nature",
"group": "itemGroup.name.log"
},
"states": {
// Log direction state
"wiki:axis": [0, 1, 2]
}
},
"components": {
"tag:log": {},
"minecraft:unit_cube": {},
// Sets different textures for sides and top/bottom of log
"minecraft:material_instances": {
"*": {
"texture": "custom_stripped_log"
},
"ends": {
"texture": "custom_stripped_log_top"
},
"up": "ends",
"down": "ends"
},
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 1
},
// Sets log rotation on player placing
"minecraft:on_player_placing": {
"event": "wiki:set_axis"
}
},
"events": {
"wiki:set_axis": {
"set_block_state": {
"wiki:axis": "Math.floor(q.block_face / 2)"
}
}
},
"permutations": [
{
"condition": "q.block_state('wiki:axis') == 0",
"components": {
"minecraft:transformation": { "rotation": [0, 0, 0] }
}
},
{
"condition": "q.block_state('wiki:axis') == 1",
"components": {
"minecraft:transformation": { "rotation": [90, 0, 0] }
}
},
{
"condition": "q.block_state('wiki:axis') == 2",
"components": {
"minecraft:transformation": { "rotation": [0, 0, 90] }
}
}
]
}
}
Custom Sapling
For the sapling we will need structures of our tree to make the sapling semi-realistic as features cannot currently be placed with commands on Minecraft Bedrock.
Code
{
"format_version": "1.21.40",
"minecraft:block": {
"description": {
"identifier": "wiki:custom_sapling",
"states": {
// Sapling's growth stage
"wiki:growth_stage": [0, 1, 2]
}
},
"components": {
"minecraft:collision_box": false,
"minecraft:selection_box": {
"origin": [-6, 0, -6],
"size": [12, 13, 12]
},
"minecraft:light_dampening": 0,
"minecraft:geometry": "geometry.custom_sapling",
"minecraft:material_instances": {
"*": {
"texture": "custom_sapling",
"render_method": "alpha_test",
"face_dimming": false,
"ambient_occlusion": false
}
},
// Add loot component so it will drop sapling placer item
"minecraft:loot": "loot_tables/blocks/custom_sapling.json",
// Allows to place block only on these blocks
"minecraft:placement_filter": {
"conditions": [
{
"allowed_faces": ["up"],
"block_filter": ["minecraft:dirt", "minecraft:grass", "minecraft:podzol"]
}
]
},
// Trigger growth on each random tick
"minecraft:random_ticking": {
"on_tick": {
"event": "wiki:grow"
}
},
// Trigger growth when bone meal is used
"minecraft:on_interact": {
"condition": "q.is_item_name_any('slot.weapon.mainhand', 'minecraft:bone_meal')",
"event": "wiki:fertilize"
}
},
"events": {
"wiki:grow": {
"sequence": [
{
"condition": "q.block_state('wiki:growth_stage') < 2",
"set_block_state": {
"wiki:growth_stage": "q.block_state('wiki:growth_stage') + 1"
}
},
{
"condition": "q.block_state('wiki:growth_stage') == 2",
"run_command": {
"command": "structure load custom_tree ~-2~~-2"
}
}
]
},
"wiki:fertilize": {
// Removes item that was used to interact
"decrement_stack": {},
// Trigger growth
"trigger": {
"event": "wiki:grow"
},
// Trigger effects
"run_command": {
"command": [
"particle minecraft:crop_growth_emitter ~~~",
"playsound item.bone_meal.use @a ~~~"
]
}
}
}
}
}
Sapling Placer
Code
{
"format_version": "1.21.40",
"minecraft:item": {
"description": {
"identifier": "wiki:custom_sapling_placer",
"menu_category": {
"category": "nature",
"group": "itemGroup.name.sapling"
}
},
"components": {
"minecraft:max_stack_size": 64,
"minecraft:block_placer": {
"block": "wiki:custom_sapling"
},
"minecraft:icon": {
"texture": "custom_sapling_placer"
}
}
}
}
Loot Tables
Code
This loot will spawn leaves block (when you break it using shears)
{
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "item",
"name": "wiki:custom_leaves"
}
]
}
]
}
Leaves default loot
{
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "item",
"name": "minecraft:apple",
"weight": 1
},
{
"type": "item",
"name": "wiki:custom_sapling_placer",
"weight": 5
},
{
// Nothing will drop
"type": "empty",
"weight": 10
}
]
}
]
}
This will spawn wiki:custom_sapling
{
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "item",
"name": "wiki:custom_sapling_placer"
}
]
}
]
}
Exporting Structures
Build a tree for your sapling to grow into!
Tree Features
TIP
Tree Features are a really great way to get actual custom trees. You need some understanding on how they work but for this tutorial you can uses these templates.
Feature
{
"format_version": "1.13.0",
"minecraft:tree_feature": {
"description": {
"identifier": "wiki:custom_tree_feature"
},
"trunk": {
"trunk_block": "wiki:custom_log",
"trunk_height": {
"range_min": 4,
"range_max": 7
}
},
"canopy": {
"leaf_block": "wiki:custom_leaves",
"canopy_offset": {
"min": -3,
"max": 0
},
"variation_chance": [
{
"numerator": 1,
"denominator": 2
},
{
"numerator": 1,
"denominator": 2
},
{
"numerator": 1,
"denominator": 2
},
{
"numerator": 1,
"denominator": 1
}
]
},
"base_block": [
"minecraft:dirt",
{
"name": "minecraft:dirt",
"states": {
"dirt_type": "coarse"
}
}
],
"may_grow_on": [
"minecraft:dirt",
"minecraft:grass",
"minecraft:podzol",
{
"name": "minecraft:dirt",
"states": {
"dirt_type": "coarse"
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 0
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 1
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 2
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 3
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 4
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 5
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 6
}
},
{
"name": "minecraft:farmland",
"states": {
"moisturized_amount": 7
}
}
],
"may_replace": [
"minecraft:air",
{
"name": "minecraft:leaves",
"states": {
"old_leaf_type": "oak"
}
},
{
"name": "minecraft:leaves",
"states": {
"old_leaf_type": "spruce"
}
},
{
"name": "minecraft:leaves",
"states": {
"old_leaf_type": "birch"
}
},
{
"name": "minecraft:leaves",
"states": {
"old_leaf_type": "jungle"
}
},
{
"name": "minecraft:leaves2",
"states": {
"new_leaf_type": "acacia"
}
},
{
"name": "minecraft:leaves2",
"states": {
"new_leaf_type": "dark_oak"
}
}
],
"may_grow_through": [
"minecraft:dirt",
"minecraft:grass",
{
"name": "minecraft:dirt",
"states": {
"dirt_type": "coarse"
}
}
]
}
}
Feature Rule
{
"format_version": "1.13.0",
"minecraft:feature_rules": {
"description": {
"identifier": "wiki:custom_tree_feature_rule",
"places_feature": "wiki:custom_tree_feature"
},
"conditions": {
"placement_pass": "surface_pass",
"minecraft:biome_filter": [
{
"test": "has_biome_tag",
"operator": "==",
"value": "plains"
}
]
},
"distribution": {
"iterations": 1,
"x": {
"distribution": "uniform",
"extent": [0, 16]
},
"y": "q.heightmap(v.worldx, v.worldz)",
"z": {
"distribution": "uniform",
"extent": [0, 16]
}
}
}
}
Resource Pack (optional guide)
Now it is time to make a resource pack!
Make translations for blocks:
tile.wiki:custom_log.name=Custom Log
tile.wiki:custom_leaves.name=Custom Leaves
tile.wiki:custom_stripped_log.name=Custom Stripped Log
tile.wiki:custom_sapling.name=Custom Sapling
item.wiki:custom_sapling_placer=Custom Sapling
Make terrain_texture.json and textures.
{
"resource_pack_name": "custom-trees",
"texture_name": "atlas.terrain",
"num_mip_levels": 4,
"padding": 8,
"texture_data": {
"custom_leaves": {
"textures": "textures/blocks/leaves_oak"
},
"custom_log": {
"textures": "textures/blocks/log_oak"
},
"custom_log_top": {
"textures": "textures/blocks/log_oak_top"
},
"custom_stripped_log": {
"textures": "textures/blocks/stripped_oak_log"
},
"custom_stripped_log_top": {
"textures": "textures/blocks/stripped_oak_log_top"
},
"custom_sapling": {
"textures": "textures/blocks/sapling_oak"
}
}
}
Make geometry for sapling:
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.custom_sapling",
"texture_width": 16,
"texture_height": 16,
"visible_bounds_width": 2,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "sapling",
"pivot": [0, 0, 0],
"cubes": [
{
"origin": [-8, 0, 0],
"size": [16, 16, 0],
"pivot": [0, 0, 0],
"rotation": [0, 45, 0],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] }
}
},
{
"origin": [-8, 0, 0],
"size": [16, 16, 0],
"pivot": [0, 0, 0],
"rotation": [0, -45, 0],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] }
}
}
]
}
]
}
]
}
Make item_texture file
{
"resource_pack_name": "custom-trees",
"texture_name": "atlas.items",
"texture_data": {
"custom_sapling_placer": {
"textures": "textures/blocks/sapling_oak"
}
}
}
Add sounds to blocks
{
"format_version": "1.21.40",
"wiki:custom_leaves": {
"sound": "grass"
},
"wiki:custom_log": {
"sound": "wood"
},
"wiki:custom_stripped_log": {
"sound": "wood"
},
"wiki:custom_sapling": {
"sound": "grass"
}
}
Result
What you have created:
- 📝custom_leaves.json
- 📝custom_log.json
- 📝custom_stripped_log.json
- 📝custom_sapling.json
- 📝custom_tree_feature.json
- 📝custom_tree_feature_rule.json
- 📝custom_sapling_placer.json
- 📝custom_leaves.json
- 📝custom_leaves_shears.json
- 📝custom_sapling.json
- 🏛custom_tree.mcstructure
- 📝blocks.json
- 🈵en_US.lang
- 📝terrain_texture.json
- 📝item_texture.json
- 📝custom_sapling.geo.json
Download Example Pack
Template Pack to use in-game to get the idea.
Download MCADDON