Changes

46 bytes added ,  22:10, 30 July 2021
Update to 1.17
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.