Line 11: |
Line 11: |
| <code><nowiki>BlockState</nowiki></code> is a flexible and powerful system, but it also has limitations. <code><nowiki>BlockState</nowiki></code>s are immutable, and all combinations of their properties are generated on startup of the game. This means that having a <code><nowiki>BlockState</nowiki></code> with many properties and possible values will slow down the loading of the game, and befuddle anyone trying to make sense of your block logic. | | <code><nowiki>BlockState</nowiki></code> is a flexible and powerful system, but it also has limitations. <code><nowiki>BlockState</nowiki></code>s are immutable, and all combinations of their properties are generated on startup of the game. This means that having a <code><nowiki>BlockState</nowiki></code> with many properties and possible values will slow down the loading of the game, and befuddle anyone trying to make sense of your block logic. |
| | | |
− | Not all blocks and situations require the usage of <code><nowiki>BlockState</nowiki></code>; only the most basic properties of a block should be put into one, and any other situation is better off with having a <code><nowiki>TileEntity</nowiki></code> or being a separate <code><nowiki>Block</nowiki></code>. Always consider if you actually need to use a state for your purposes. | + | Not all blocks and situations require the usage of <code><nowiki>BlockState</nowiki></code>; only the most basic properties of a block should be put into one, and any other situation is better off with having a <code><nowiki>BlockEntity</nowiki></code> or being a separate <code><nowiki>Block</nowiki></code>. Always consider if you actually need to use a state for your purposes. |
| | | |
| {{Colored box|title=Tip|content=A good rule of thumb is: '''if it has a different name, it should be a separate block'''.}} | | {{Colored box|title=Tip|content=A good rule of thumb is: '''if it has a different name, it should be a separate block'''.}} |
Line 38: |
Line 38: |
| The class <code><nowiki>BlockStateProperties</nowiki></code> contains shared vanilla properties which should be used or referenced whenever possible, in place of creating your own properties. | | The class <code><nowiki>BlockStateProperties</nowiki></code> contains shared vanilla properties which should be used or referenced whenever possible, in place of creating your own properties. |
| | | |
− | When you have your desired <code><nowiki>Property<></nowiki></code> objects, override <code><nowiki>Block#fillStateContainer(StateContainer$Builder)</nowiki></code> in your ''Block'' class. In that method, call <code><nowiki>StateContainer$Builder#add(...);</nowiki></code> with the parameters as every <code><nowiki>Property<?></nowiki></code> you wish the block to have. | + | When you have your desired <code><nowiki>Property<></nowiki></code> objects, override <code><nowiki>Block#createBlockStateDefinition(StateDefinition$Builder)</nowiki></code> in your ''Block'' class. In that method, call <code><nowiki>StateDefinition$Builder#add(...);</nowiki></code> with the parameters as every <code><nowiki>Property<?></nowiki></code> you wish the block to have. |
| | | |
− | Every block will also have a "default" state that is automatically chosen for you. You can change this "default" state by calling the <code><nowiki>Block#setDefaultState(BlockState)</nowiki></code> method from your constructor. When your block is placed it will become this "default" state. An example from <code><nowiki>DoorBlock</nowiki></code>: | + | Every block will also have a "default" state that is automatically chosen for you. You can change this "default" state by calling the <code><nowiki>Block#registerDefaultState(BlockState)</nowiki></code> method from your constructor. When your block is placed it will become this "default" state. An example from <code><nowiki>DoorBlock</nowiki></code>: |
| | | |
| <syntaxhighlight lang="java"> | | <syntaxhighlight lang="java"> |
− | this.setDefaultState( | + | this.registerDefaultState( |
− | this.stateContainer.getBaseState() | + | this.stateDefinition.any() |
− | .with(FACING, Direction.NORTH) | + | .setValue(FACING, Direction.NORTH) |
− | .with(OPEN, false) | + | .setValue(OPEN, false) |
− | .with(HINGE, DoorHingeSide.LEFT) | + | .setValue(HINGE, DoorHingeSide.LEFT) |
− | .with(POWERED, false) | + | .setValue(POWERED, false) |
− | .with(HALF, DoubleBlockHalf.LOWER) | + | .setValue(HALF, DoubleBlockHalf.LOWER) |
| ); | | ); |
− | </syntaxhighlight > | + | </syntaxhighlight> |
| | | |
− | If you wish to change what <code><nowiki>BlockState</nowiki></code> is used when placing your block, you can overwrite <code><nowiki>Block#getStateForPlacement(BlockItemUseContext)</nowiki></code>. This can be used to, for example, set the direction of your block depending on where the player is standing when they place it. | + | If you wish to change what <code><nowiki>BlockState</nowiki></code> is used when placing your block, you can overwrite <code><nowiki>Block#getStateForPlacement(BlockPlaceContext)</nowiki></code>. This can be used to, for example, set the direction of your block depending on where the player is standing when they place it. |
| | | |
− | Because <code><nowiki>BlockState</nowiki></code>s are immutable, and all combinations of their properties are generated on startup of the game, calling <code><nowiki>BlockState#with(IProperty<T>, T)</nowiki></code> will simply go to the <code><nowiki>Block</nowiki></code>'s <code><nowiki>StateContainer</nowiki></code> and request the <code><nowiki>BlockState</nowiki></code> with the set of values you want. | + | Because <code><nowiki>BlockState</nowiki></code>s are immutable, and all combinations of their properties are generated on startup of the game, calling <code><nowiki>BlockState#setValue(Property<T>, T)</nowiki></code> will simply go to the <code><nowiki>Block</nowiki></code>'s <code><nowiki>StateHolder</nowiki></code> and request the <code><nowiki>BlockState</nowiki></code> with the set of values you want. |
| | | |
| Because all possible <code><nowiki>BlockState</nowiki></code>s are generated at startup, you are free and encouraged to use the reference equality operator (<code><nowiki>==</nowiki></code>) to check if two <code><nowiki>BlockState</nowiki></code>s are equal. | | Because all possible <code><nowiki>BlockState</nowiki></code>s are generated at startup, you are free and encouraged to use the reference equality operator (<code><nowiki>==</nowiki></code>) to check if two <code><nowiki>BlockState</nowiki></code>s are equal. |
Line 61: |
Line 61: |
| == Using <tt>BlockState</tt>s == | | == Using <tt>BlockState</tt>s == |
| | | |
− | You can get the value of a property by calling <code><nowiki>BlockState#get(IProperty<?>)</nowiki></code>, passing it the property you want to get the value of. | + | You can get the value of a property by calling <code><nowiki>BlockState#getValue(Property<?>)</nowiki></code>, passing it the property you want to get the value of. |
− | If you want to get a <code><nowiki>BlockState</nowiki></code> with a different set of values, simply call <code><nowiki>BlockState#with(IProperty<T>, T)</nowiki></code> with the property and its value. | + | If you want to get a <code><nowiki>BlockState</nowiki></code> with a different set of values, simply call <code><nowiki>BlockState#setValue(Property<T>, T)</nowiki></code> with the property and its value. |
| | | |
− | You can get and place <code><nowiki>BlockState</nowiki></code>s in the world using <code><nowiki>World#setBlockState(BlockPos, BlockState)</nowiki></code> and <code><nowiki>World#getBlockState(BlockState)</nowiki></code>. If you are placing a <code><nowiki>Block</nowiki></code>, call <code><nowiki>Block#getDefaultState()</nowiki></code> to get the "default" state, and use subsequent calls to <code><nowiki>BlockState#with(IProperty<T>, T)</nowiki></code> as stated above to achieve the desired state. | + | You can get and place <code><nowiki>BlockState</nowiki></code>s in the level using <code><nowiki>Level#setBlockAndUpdate(BlockPos, BlockState)</nowiki></code> and <code><nowiki>Level#getBlockState(BlockState)</nowiki></code>. If you are placing a <code><nowiki>Block</nowiki></code>, call <code><nowiki>Block#defaultBlockState()</nowiki></code> to get the "default" state, and use subsequent calls to <code><nowiki>BlockState#setValue(Property<T>, T)</nowiki></code> as stated above to achieve the desired state. |