🔣 Block States
Introduction
In Minecraft's block system, each block can have one or more block states. For example, wood can have different orientations, and leaves can detect their "distance" from a tree. These states collectively determine the block's appearance and physical behavior in the game.
To better understand how plugins operate, we first need to distinguish two core concepts:
🎨 Visual Block States
This refers to the block states that players actually see on the client side, hence also known as vanilla block states.
- Plugins achieve various unique block rendering effects by attaching custom models to these specific vanilla states (e.g., a note block with a specific note and instrument).
- In simple terms, visual states determine "what it looks like."
⚙️ Internal Block States
This refers to the block states that are actually stored and processed on the server side, hence also known as server-side block states.
- It handles all the logic and physical behaviors of blocks, such as collision boxes, redstone signals, and entity interactions.
- The server "maps" or "converts" this internal state into a visual state through specific network protocols and sends it to the client for rendering.
- In simple terms, internal states determine "how it actually works."

Single-State Blocks
Most blocks can function properly with only one block state. The following example demonstrates how to configure a single-state block.
blocks:
default:chinese_lantern:
state:
auto-state: note_block
model:
path: "minecraft:block/custom/chinese_lantern"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/chinese_lantern_top"
"side": "minecraft:block/custom/chinese_lantern"
Visual States
The visual representation of a block is controlled by either the auto-state or state option. You can choose one of them based on your precision requirements.
🛠️ Using auto-state: Let the Plugin Choose for You
The parameter of auto-state points to a predefined set of visual states in the plugin. These states share key characteristics, such as identical collision boxes and consistent rendering properties (e.g., whether transparency is supported).
- What is its purpose?
When creating a new block, we typically only care about its core characteristics (such as collision box size) and not which specific block state is used. auto-state was designed for this purpose: the plugin will automatically assign you an available state from the group that meets the characteristics.
- An example
For a note block, minecraft:note_block[instrument=hat,note=0,powered=false] and minecraft:note_block[instrument=hat,note=1,powered=false] are identical in terms of core characteristics. You don’t need to remember or type such long state parameters. Simply write auto-state: note_block, and the plugin will automatically select an available note block state for you.
Currently available auto-state options:
- tintable_leaves - Tintable leaves block without water
- waterlogged_tintable_leaves - Tintable leaves block with water
- non_tintable_leaves - Non-tintable leaves block without water
- waterlogged_non_tintable_leaves - Non-tintable leaves block with water
- leaves - Any leaves block without water
- waterlogged_leaves - Any leaves block with water
- lower_tripwire - Tripwire with a smaller collision box
- higher_tripwire - Tripwire with a larger collision box
- tripwire - Any tripwire
- note_block - Note block
- mushroom_stem - Mushroom stem
- red_mushroom_block - Red mushroom block
- brown_mushroom_block - Brown mushroom block
- mushroom - Mushroom block
- solid - Any solid block (including note blocks and mushroom blocks)
- sapling - Any sapling
- cactus - Any cactus
- sugar_cane - Any sugar cane
If multiple block appearances reference the same id, they will ultimately be assigned the same visual block state. This is helpful if you need multiple block states to share the same visual state.
auto-state:
type: solid
id: namespace:id
🎯 Using state: Precise Control Over Every Detail
When you need to precisely specify a particular state, you should use the state parameter. This is crucial for blocks with multiple variants such as doors, fences, and trapdoors, as only precise control can achieve the expected collision box and appearance.
The state parameter supports two formats:
- Full Block State
Directly use the complete state identifier from vanilla Minecraft.
Example:minecraft:note_block[instrument=hat,note=0,powered=false]
- Mapped Shorthand
Use the shorthand format block_name:ID defined in the block-state-mappings configuration.
Example:
note_block:100(This indicates using the 101st mapped note block state)
Below is a complete single-state block configuration example using state:
blocks:
default:chinese_lantern:
state:
state: minecraft:note_block[instrument=hat,note=0,powered=false]
model:
path: "minecraft:block/custom/chinese_lantern"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/chinese_lantern_top"
"side": "minecraft:block/custom/chinese_lantern"
⚠️ Note: Avoid duplicate binding of states and models
When you use the state option to specify a block state precisely, ensure that this state is bound to only one unique custom model.
❌ What is a conflict?
For example:
- You set the state
minecraft:note_block[instrument=hat,note=0,powered=false]for Block A and bind it to Model A. - Then, you set the exact same state
minecraft:note_block[instrument=hat,note=0,powered=false]for Block B but attempt to bind it to Model B.
This creates a conflict because the same vanilla block state cannot represent two different custom models simultaneously.
🔍 What happens in case of a conflict?
When the plugin detects such duplicate bindings, it will log warning messages in the console. Be sure to pay attention to these warnings and adjust your configuration promptly. Otherwise, unexpected issues may arise with model display.
Model
Basic Model Configuration
blocks:
default:chinese_lantern:
state:
auto-state: note_block
model:
path: "minecraft:block/custom/chinese_lantern"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/chinese_lantern_top"
"side": "minecraft:block/custom/chinese_lantern"
The model determines what your chosen visual state will ultimately look like on the client side.
If you're unsure about how to configure properties like path (model path) and generation (model generation), we strongly recommend first completing the Getting Started Tutorial, which will help you systematically understand the basic workflow.
Of course, here’s a simple guideline to help you get started quickly:
- Scenario 1: I already have a pre-made model file
If you already have a model file in .json format ready, simply fill in the path field in the configuration to directly specify the path to this model.
- Scenario 2: I need the plugin to automatically create a basic model
If you don’t have a model file yet and want the plugin to generate a basic model for you, you should use the generation option and fill in the corresponding generation parameters.
Weighted Model Configuration
The weight parameter is used to set the probability weight for a model to be randomly selected from the candidate list, with a default value of 1.
🎲 How It Works
- Trigger Condition:When a block has multiple candidate models, the game calculates which model to use based on its position. For the same position, the calculation result is fixed.
- Probability Calculation:The probability of each model being selected is determined by the ratio of its own
weightvalue to the total weight of all candidate models.
The specific calculation formula is: Probability of selecting a single model = Model's own weight / Sum of weights of all candidate models
state:
models: # model(s)
- path: "minecraft:block/custom/fairy_flower_1"
weight: 8
- path: "minecraft:block/custom/fairy_flower_2"
weight: 5
- path: "minecraft:block/custom/fairy_flower_3"
weight: 2

Rotating Model Configuration
If you need to apply basic rotations to a model without modifying the model file itself, you can directly use the following options in the configuration instead of creating new model files:
🔧 Available Options
- x Rotation angle of the model around the X-axis. Unit: Degrees (°) Restriction: Must be a multiple of 90.
- y Rotation angle of the model around the Y-axis. Unit: Degrees (°) Restriction: Must be a multiple of 90.
- uvlock Whether to lock the rotation direction of the block texture. Default value: false Effect: When set to true, the block texture will not rotate with the model and will retain its original orientation.
model:
path: "minecraft:block/custom/chinese_lantern"
x: 90
y: 180
uvlock: false
Multi-State Blocks
warning The following content may be challenging to understand. I will explain it in as much detail as possible. Please be sure to read it word by word carefully.
Step 1: Define Properties
In this example, we define a property named axis:
blocks:
default:palm_log:
states: # state(s)
properties:
axis:
type: "axis"
default: "y"
✍️ Property Definition Notes
- Property Name:Be sure to use a combination of lowercase English letters and underscores for naming.
- type:Specifies the type of the property. You can view all available property types in the ℹ️ Properties subpage.
- default:(Optional)Sets the default value for this property. When the block state does not explicitly specify this property, the default value will be used.
Behavior of Special Names
Property names can be set with considerable flexibility, but it's important to note a special mechanism: the plugin hardcodes specific placement behaviors for certain reserved property names.
For example, when a property is named axis:
- The plugin will automatically align its orientation during placement to match the direction the player is facing.
- This process is fully automated and requires no additional configuration.
If the property name is not one of these reserved names (e.g., custom_axis as shown below):
custom_axis:
type: axis
default: y
- The plugin will not apply any automatic rotation during placement.
- Regardless of the placement direction, the block will always use the default state defined in the configuration (in this case,
custom_axis=y).
Step 2: Define Visual Appearance
In the second step, we need to configure the possible visual appearances of the custom block. For example, a log block requires three orientations, so we need to specify three vanilla block states as its visual representations.
In the configuration below, state names such as axisX, axisZ, and axisY can be freely defined:
- Naming Freedom:You can use any names that clearly describe the corresponding visual states, without restrictions such as lowercase letters.
- Uniqueness Requirement:The only requirement is to ensure that the names of each state are unique and not duplicated within the same block.
The state(s) and model(s) configurations under each state follow the exact same rules as those for single-state blocks.
If you are unsure about any specific details of these configurations, it is recommended to review the documentation section on single-state blocks.
blocks:
default:palm_log:
states:
appearances:
axisY:
# You can also use "auto-state: note_block" here
state: "note_block:0"
model:
path: "minecraft:block/custom/stripped_palm_log"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
axisX:
state: "note_block:1"
model:
x: 90
y: 90
path: "minecraft:block/custom/stripped_palm_log_horizontal"
generation:
parent: "minecraft:block/cube_column_horizontal"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
axisZ:
state: "note_block:2"
model:
x: 90
path: "minecraft:block/custom/stripped_palm_log_horizontal"
generation:
parent: "minecraft:block/cube_column_horizontal"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
Step 3: Configure Variants (Optional)
This final step is optional, but in most practical scenarios, you will need to configure it.
In this part, you need to assign corresponding visual appearances (defined in Step 2) and properties (block settings) to all possible internal block states (i.e., real block variants).
💡 Variant Key Format
Under variants, the key for each entry must be constructed by concatenating the property name and its corresponding value:
- Single Property:The format is property_name=value, e.g.,
axis=y. - Multiple Properties:Separate them with English commas, e.g.,
axis=y,age=7. The order of properties does not affect matching.
Under each variant key, there are two optional configuration options: appearance (used to assign the visual appearance) and settings (used to override settings). Below, we use a leaves block configuration example to help you understand how variants work:
Complete states section configuration
blocks:
default:palm_leaves:
states:
properties:
waterlogged:
type: boolean
default: false
persistent:
type: boolean
default: true
distance:
type: int
default: 7
range: 1~7
appearances:
default:
auto-state: leaves
model:
path: minecraft:block/custom/palm_leaves
generation:
parent: minecraft:block/leaves
textures:
all: minecraft:block/custom/palm_leaves
waterlogged:
auto-state: waterlogged_leaves
model:
path: minecraft:block/custom/palm_leaves
variants:
waterlogged=false:
appearance: default
waterlogged=true:
appearance: waterlogged
settings:
resistance: 1200.0
burnable: false
fluid-state: water
distance=7,persistent=false:
settings:
is-randomly-ticking: true
- Basic Waterlogged States
I first defined the appearance models for all leaves states when waterlogged and non-waterlogged using waterlogged=true and waterlogged=false.
- Dynamically Adjusting Block Settings
Subsequently, by configuring states such as distance=7,persistent=false, leaves that meet the conditions (e.g., sufficiently far from a tree and not permanently retained) can participate in random ticks, enabling natural decay behavior in the game.
Inheritance and Override Rules for Settings
A key feature is that you can configure settings for different variant keys, and the application of these settings follows clear priority rules:
- Inheritance First: Variants first inherit the global
settingsdefined at the root of the block configuration. - Layering Next: Then, the settings defined for the variant itself are layered on top of the inherited settings. For the same configuration item, the variant settings will override the previously inherited global settings.
For example, in this case, I configured certain settings for waterlogged=true and other settings for distance=7,persistent=false. When a block's actual state matches both conditions (i.e., waterlogged=true,distance=7,persistent=false), it will inherit and apply all settings from both variant keys. This mechanism allows you to flexibly combine block attributes and ensure that visual effects correspond precisely to block behaviors.
Configuring Real Block ID (Optional)
If you wish to specify the real block ID used on the server side, you can configure it as follows. However, please note:
- Global Uniqueness:The specified ID must be globally unique across the entire server.
- Quantity Limit:The number of IDs cannot exceed the
serverside-blockslimit set inconfig.yml.
💡 In most cases, you do not need to manually configure the ID. Only when you need to ensure that the internal ID remains fixed (for example, when using data packs or other systems that rely on strict ID mapping) should you set it manually.
ID Configuration for Single-State Blocks
blocks:
default:chinese_lantern:
state:
id: 0 # Set the internal ID of this block to craftengine:custom_0.
auto-state: note_block
model:
path: "minecraft:block/custom/chinese_lantern"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/chinese_lantern_top"
"side": "minecraft:block/custom/chinese_lantern"
Multi-State Block ID Configuration
For multi-state blocks, you only need to specify a starting ID. The plugin will automatically allocate a continuous range of IDs based on the total number of variants for that block.
In the example below, this leaves block has a total of 2 (waterlogged) × 2 (persistent) × 7 (distance) = 28 variants. With the starting ID configured as 100, the plugin will automatically assign IDs 100 to 127 (a total of 28 consecutive IDs) to it.
blocks:
default:palm_leaves:
states:
id: 100 # The starting id
properties:
waterlogged:
type: boolean
default: false
persistent:
type: boolean
default: true
distance:
type: int
default: 7
range: 1~7