Skip to content

Instantly share code, notes, and snippets.

@CorgiTaco
Last active October 19, 2023 17:35
Show Gist options
  • Save CorgiTaco/8623cc065177c3476fde30b9258e7e10 to your computer and use it in GitHub Desktop.
Save CorgiTaco/8623cc065177c3476fde30b9258e7e10 to your computer and use it in GitHub Desktop.

Custom NBT Tree Tutorial

Overview

As of 1.19.2-2.0.1.0 BYG, BYG now depends on Corgilib. This library offers a new world gen feature for creating custom trees from NBT files.

Features include but not are limited to:

  • Allows to build trees with trunk & canopy structure NBT parts.
  • Allows the use of vanilla & modded tree decorators. These include but are not limited to:
    • Vines
    • Cocoa Beans
    • Attached To Leaves blocks such as vanilla's propagules.
  • Calculates leave distance and avoids placing leaves that are too far away.
  • Much better control over tree height.
  • The ability to place other blocks found in the trunk & canopy NBTs.
  • The ability to filter what blocks may be replaced by leaves w/ vanilla & modded BlockPredicates.
  • The ability to filter what blocks the tree feature considers ground w/ vanilla & modded BlockPredicates.
  • Random tree roatation and mirroring.

How do I make my own tree?

Trunk

  1. Build a trunk.

  2. Place red wool where you want to prevent floating trees and ensure the trunk is always connected to the ground in its entirety. Red wool blocks should have NO obstructions below them in the NBT box.

  3. Place white wool. This centers the trunk on the passed position from world generation. Effects horizontal (x/z) position only.

  4. (Optional) Place yellow wool where you want to center the canopy on the trunk, if no yellow wool is placed, the canopy will use the white wool position. Effects horizontal (x/z) position only.

Your trunk should now look like this:

image

  1. Obtain a structure block and encase the trunk along with the wool. Save the trunk to a path of your choice. In this example we save it to: byg:features/trees/cika/cika_trunk3

Canopy

  1. Build a canopy

  2. Place red wool where you want to build logs down to ensure the canopy is always connected to the trunk in its entirety.

  3. Place white wool. This centers the tree on the passed position from the trunk(whether the world gen(white wool) or yellow wool) position. Effects horizontal (x/z) position only.

Your canopy should now look like this: image

  1. Obtain a structure block and encase the canopy along with the wool. Save the canopy to a path of your choice. In this example we save it to: byg:features/trees/cika/cika_canopy3

Data packing time

With our parts defined, we will now move on to the technical side which will involve a datapack.

  1. Make a new folder and title it your datapack's name. In this example we will call it byg_customtree.

  2. Create a file named pack.mcmeta in the new folder you made and add the following to it:

{
    "pack": {
        "description": "BYG Custom Tree resources",
        "pack_format": 10
    }
}

image

  1. With the folder and pack.mcmeta made, make a folder named data inside of the byg_customtree folder.

  2. Go to your world where you made and saved your trunk and canopy and copy the folder inside of generated. In this case the folder will be named byg.

image

  1. Paste the byg folder into your data folder. It should look like this:

image

IF YOU ARE REPLACING A TREE CANOPY OR TRUNK ONLY, STOP HERE.

Defining a configured feature

With the structure NBTs in their directory, let's move on to the world gen jsons and how to get these parts generating in your biomes. We will use the data pack from the previous section.

  1. In byg_customtree/data/byg make folders to the following path: byg_customtree/data/byg/worldgen/configured_feature.

  2. Make a new json file, in this example we will call it: cika_tree3.json. It should look like this:

image

  1. Add the following to the file(comments will explain what each field does.):
{
	"config": {
		"base_location": "byg:features/trees/cika/cika_trunk3", // The file path to the trunk's NBT as defined in the datapack. Exclude `structures` portion of the datapack path.
		"can_grow_on_filter": { // This checks whether or not a tree can grow here at each red wool position defined and searches down based off the defined max_log_depth.
			"tag": "byg:may_place_on/cika_sapling",
			"type": "minecraft:matching_block_tag"
		},
		"can_leaves_place_filter": { // This checks whether or not a leaves block can place at this position.
			"type": "minecraft:replaceable"
		},
		"canopy_location": "byg:features/trees/cika/cika_canopy3", // The file path to the trunk's NBT as defined in the datapack. Exclude `structures` portion of the datapack path.
		"height": { // Using a Minecraft int height provider, you can define the height range of the tree. This will offset the canopy from the bottom of the tree. 
			"type": "minecraft:biased_to_bottom", // The id of the type int height provider.
			"value": { // The defined data to use for the type of int height provider.
				"max_inclusive": 18,
				"min_inclusive": 7
			}
		},
		"leaves_provider": { // Uses a Minecraft block state provider to define the rules as to how leave block states spawn. Leaves distance is calculated automatically internally.
			"entries": [ // The defined data to use for the type of block state provider.
				{
					"data": {
						"Name": "byg:cika_leaves",
						"Properties": {
							"distance": "7",
							"persistent": "false",
							"waterlogged": "false"
						}
					},
					"weight": 1
				}
			],
			"type": "minecraft:weighted_state_provider" // The id of the type block state provider.
		},
		"leaves_target": [ // What blocks in the trunk & canopy NBT to replace with the leaves_provider.
			"byg:cika_leaves"
		],
		"log_provider": { // Uses a Minecraft block state provider to define the rules as to how log block states spawn. Log rotation is preserved from the NBT when generating.
			"state": {
				"Name": "byg:cika_log",
				"Properties": {
					"axis": "y"
				}
			},
			"type": "minecraft:simple_state_provider" // The id of the type block state provider.
		},
		"log_target": [ // What blocks in the trunk & canopy NBT to replace with the log_provider.
			"byg:cika_log"
		],
		"max_log_depth": 14, // How deep the search for ground can go when iterating down from positions defined by red wool.
		"place_from_nbt": [] // Any addditional blocks in the NBT you'd like to place. Blocks are placed with the state defined in the NBT.
	},
	"type": "corgilib:tree_from_nbt" // Our feature that enables us to make trees from NBT parts.
}

Other trees can define tree decorators as well! Let's take a look at BYG's mahogany_tree4.json:

{
	"config": {
		"base_location": "byg:features/trees/mahogany/mahogany_tree_trunk4",
		"can_grow_on_filter": {
			"tag": "byg:may_place_on/mahogany_sapling",
			"type": "minecraft:matching_block_tag"
		},
		"can_leaves_place_filter": {
			"type": "minecraft:replaceable"
		},
		"canopy_location": "byg:features/trees/mahogany/mahogany_tree_canopy4",
		"decorators": [ // A list of tree decorators. Accepts vanilla and modded tree decorators.
			{
				"probability": 0.4000000059604645,
				"type": "byg:leave_vine",
				"vine_block": "minecraft:vine"
			},
			{
				"probability": 1.0,
				"type": "byg:trunk_vine",
				"vine_block": "minecraft:vine"
			},
			{
				"probability": 0.20000000298023224,
				"type": "minecraft:cocoa"
			}
		],
		"height": {
			"type": "minecraft:biased_to_bottom",
			"value": {
				"max_inclusive": 15,
				"min_inclusive": 5
			}
		},
		"leaves_provider": {
			"state": {
				"Name": "byg:mahogany_leaves",
				"Properties": {
					"distance": "7",
					"persistent": "false",
					"waterlogged": "false"
				}
			},
			"type": "minecraft:simple_state_provider"
		},
		"leaves_target": [
			"byg:mahogany_leaves"
		],
		"log_provider": {
			"state": {
				"Name": "byg:mahogany_log",
				"Properties": {
					"axis": "y"
				}
			},
			"type": "minecraft:simple_state_provider"
		},
		"log_target": [
			"byg:mahogany_log"
		],
		"place_from_nbt": []
	},
	"type": "corgilib:tree_from_nbt"
}

Other examples:

BYG's fungal_imparius4.json

{
	"config": {
		"base_location": "byg:features/fungi/imparius/imparius_trunk4",
		"can_grow_on_filter": {
			"tag": "byg:may_place_on/fungal_imparius",
			"type": "minecraft:matching_block_tag"
		},
		"can_leaves_place_filter": {
			"type": "minecraft:replaceable"
		},
		"canopy_location": "byg:features/fungi/imparius/imparius_canopy4",
		"height": {
			"type": "minecraft:biased_to_bottom",
			"value": {
				"max_inclusive": 6,
				"min_inclusive": 4
			}
		},
		"leaves_provider": {
			"entries": [
				{
					"data": {
						"Name": "byg:fungal_imparius_block"
					},
					"weight": 1
				}
			],
			"type": "minecraft:weighted_state_provider"
		},
		"leaves_target": [
			"byg:fungal_imparius_block"
		],
		"log_provider": {
			"state": {
				"Name": "byg:fungal_imparius_stem",
				"Properties": {
					"axis": "y"
				}
			},
			"type": "minecraft:simple_state_provider"
		},
		"log_target": [
			"byg:fungal_imparius_stem"
		],
		"place_from_nbt": [
			"byg:fungal_imparius",
			"byg:fungal_imparius_filament_block"
		]
	},
	"type": "corgilib:tree_from_nbt"
}

BYG's white_mangrove_tree4.json

{
	"config": {
		"base_location": "byg:features/trees/white_mangrove_tree4_base",
		"can_grow_on_filter": {
			"tag": "byg:may_place_on/white_mangrove_sapling",
			"type": "minecraft:matching_block_tag"
		},
		"can_leaves_place_filter": {
			"type": "minecraft:replaceable"
		},
		"canopy_location": "byg:features/trees/white_mangrove_tree4_canopy",
		"decorators": [
			{
				"probability": 1.0,
				"type": "minecraft:leave_vine"
			},
			{
				"type": "minecraft:trunk_vine"
			},
			{
				"block_provider": {
					"state": {
						"Name": "minecraft:moss_carpet"
					},
					"type": "minecraft:simple_state_provider"
				},
				"directions": [
					"up"
				],
				"exclusion_radius_xz": 0,
				"exclusion_radius_y": 0,
				"probability": 0.8999999761581421,
				"required_empty_blocks": 1,
				"type": "byg:attached_to_logs"
			}
		],
		"height": {
			"type": "minecraft:biased_to_bottom",
			"value": {
				"max_inclusive": 15,
				"min_inclusive": 5
			}
		},
		"leaves_provider": {
			"state": {
				"Name": "byg:white_mangrove_leaves",
				"Properties": {
					"distance": "7",
					"persistent": "false",
					"waterlogged": "false"
				}
			},
			"type": "minecraft:simple_state_provider"
		},
		"leaves_target": [
			"byg:white_mangrove_leaves"
		],
		"log_provider": {
			"state": {
				"Name": "byg:white_mangrove_log",
				"Properties": {
					"axis": "y"
				}
			},
			"type": "minecraft:simple_state_provider"
		},
		"log_target": [
			"byg:white_mangrove_log"
		],
		"place_from_nbt": []
	},
	"type": "corgilib:tree_from_nbt"
}

BYG's skyris_tree6.json

{
	"config": {
		"base_location": "byg:features/trees/skyris/skyris_trunk_6",
		"can_grow_on_filter": {
			"tag": "byg:may_place_on/skyris_sapling",
			"type": "minecraft:matching_block_tag"
		},
		"can_leaves_place_filter": {
			"type": "minecraft:replaceable"
		},
		"canopy_location": "byg:features/trees/skyris/skyris_canopy_6",
		"decorators": [
			{
				"probability": 0.10000000149011612,
				"type": "byg:leave_vine",
				"vine_block": "byg:skyris_vine"
			},
			{
				"probability": 0.30000001192092896,
				"type": "byg:trunk_vine",
				"vine_block": "byg:skyris_vine"
			},
			{
				"block_provider": {
					"property": "age",
					"source": {
						"state": {
							"Name": "byg:green_apple_fruit_block",
							"Properties": {
								"age": "0"
							}
						},
						"type": "minecraft:simple_state_provider"
					},
					"type": "minecraft:randomized_int_state_provider",
					"values": {
						"type": "minecraft:uniform",
						"value": {
							"max_inclusive": 3,
							"min_inclusive": 0
						}
					}
				},
				"directions": [
					"down"
				],
				"exclusion_radius_xz": 2,
				"exclusion_radius_y": 0,
				"probability": 0.10000000149011612,
				"required_empty_blocks": 2,
				"type": "minecraft:attached_to_leaves"
			}
		],
		"height": {
			"type": "minecraft:biased_to_bottom",
			"value": {
				"max_inclusive": 15,
				"min_inclusive": 5
			}
		},
		"leaves_provider": {
			"entries": [
				{
					"data": {
						"Name": "byg:skyris_leaves",
						"Properties": {
							"distance": "7",
							"persistent": "false",
							"waterlogged": "false"
						}
					},
					"weight": 10
				},
				{
					"data": {
						"Name": "byg:flowering_skyris_leaves",
						"Properties": {
							"distance": "7",
							"persistent": "false",
							"waterlogged": "false"
						}
					},
					"weight": 2
				},
				{
					"data": {
						"Name": "byg:green_apple_skyris_leaves",
						"Properties": {
							"distance": "7",
							"persistent": "false",
							"waterlogged": "false"
						}
					},
					"weight": 1
				}
			],
			"type": "minecraft:weighted_state_provider"
		},
		"leaves_target": [
			"byg:skyris_leaves"
		],
		"log_provider": {
			"state": {
				"Name": "byg:skyris_log",
				"Properties": {
					"axis": "y"
				}
			},
			"type": "minecraft:simple_state_provider"
		},
		"log_target": [
			"byg:skyris_log"
		],
		"place_from_nbt": []
	},
	"type": "corgilib:tree_from_nbt"
}
@lxly9
Copy link

lxly9 commented Mar 4, 2023

Hiya, does this allow me to completely replace other trees from different mods/vanilla as well, or is it limited to BYG?

@CorgiTaco
Copy link
Author

CorgiTaco commented Mar 4, 2023

@lxly9

Hiya, does this allow me to completely replace other trees from different mods/vanilla as well, or is it limited to BYG?

You can replace trees in any mod/vanilla or make your own and use it in your mod. All you need is Corgilib

@lxly9
Copy link

lxly9 commented Mar 6, 2023

Omg, thats amazing,,,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment