Giving a block state - CansteinBerlin/CustomBlocksApi GitHub Wiki
Every single block created with this plugin in represented by a singular CustomBlock instance. This makes it impossible to change a specific block's state by simply changing the CustomBlock instance's state, as every other block of that type will be affected! But, what if you do want to give a singular block state, so it can change based on some condition?
This is what CustomBlockStates are for. Say we wanted a block that can be charged.
First we define the boolean property of the block - whether or not it is turned. In fact, you can also use existing properties defined in vanilla, which can be found in Properties. If you intend to define other types of properties you may use IntProperty, BooleanProperty or EnumProperty
public class ExampleBlock extends CustomBlock {
public static BooleanProperty CHARGED = new BooleanProperty("charged");
}
Then we need to register the properties of the block overriding appendProperties, and then add the CHARGED property.
public class ExampleBlock extends CustomBlock {
[...]
@Override
public void appendProperties(PropertyListBuilder propertyListBuilder) {
propertyListBuilder.add(CHARGED);
}
}
Then we need to set the default state of our property in the block constructor (To set multiple properties, chain with() calls).
public class ExampleBlock extends CustomBlock {
[...]
public ExampleBlock(BlockSettings settings) {
super(settings, 1, new ItemBuilder(Material.IRON_NUGGET).setCustomModelData(1).setDisplayName("ยง6Example Block").build());
setDefaultState(getDefaultState().with(CHARGED, false));
}
}
Now we need to charge the block, through the onUse method, with invoking the state.with() and state.update() method inside of it
public class ExampleBlock extends CustomBlock {
[...]
@Override
public ActionResult onUse(CustomBlockState state, World world, Location location, Player player, EquipmentSlot hand) {
state.with(CHARGED, true); // Modify the state
state.update(); // Update Textures and save to entity
return ActionResult.SUCCESS;
}
}
And finally, to use the CHARGED property, we call onSteppedOn with state.get(CHARGED) inside of it. When registering the block we have to assure the SteppedOn Event if enabled!
public class ExampleBlock extends CustomBlock {
[...]
@Override
public void onSteppedOn(CustomBlockState state, World world, Location location, Entity entity) {
if(state.get(CHARGED)){
//Summon Lightning Bolt
world.strikeLightning(location);
state.with(CHARGED, false);
state.update();
}
}
}
Adding models for your blockstates
You can also change the texture and model of your block depending on the state. This is done with a CMDLookupTable (CustomModelDataLookupTable). This lookup table can be as complex as you want it to be. You do not have to use all registered states in the table. To create the lookuptable, override the createCMDLookupTable(CMDLookupTableBuilder) method in your block class.
public class ExampleBlock extends CustomBlock {
[...]
@Override
public CMDLookupTable createCMDLookupTable(CMDLookupTableBuilder tableBuilder) {
tableBuilder.with(CHARGED, false).hasCustomModelData(1).addElement();
tableBuilder.with(CHARGED, true).hasCustomModelData(2).addElement();
return tableBuilder.build();
}
}
You can also use this method to rotate the model of your block. This is especially useful if you use the same block model but want to rotate the block in a specific direction. This can be done with the hasRotation(Axis, Integer) method. Note that these methods can be concatenated to allow model rotations around multiple axes.
public class ExampleBlock extends CustomBlock {
[...]
@Override
public CMDLookupTable createCMDLookupTable(CMDLookupTableBuilder tableBuilder) {
tableBuilder.with(FACING, BlockFace.SOUTH).with(CHARGED, false).hasCustomModelData(1).addElement();
tableBuilder.with(FACING, BlockFace.WEST).with(CHARGED, false).hasCustomModelData(1).hasRotation(Axis.Y, 90).addElement();
tableBuilder.with(FACING, BlockFace.NORTH).with(CHARGED, false).hasCustomModelData(1).hasRotation(Axis.Y, 180).addElement();
tableBuilder.with(FACING, BlockFace.EAST).with(CHARGED, false).hasCustomModelData(1).hasRotation(Axis.Y, 270).addElement();
tableBuilder.with(FACING, BlockFace.SOUTH).with(CHARGED, true).hasCustomModelData(2).addElement();
tableBuilder.with(FACING, BlockFace.WEST).with(CHARGED, true).hasCustomModelData(2).hasRotation(Axis.Y, 90).addElement();
tableBuilder.with(FACING, BlockFace.NORTH).with(CHARGED, true).hasCustomModelData(2).hasRotation(Axis.Y, 180).addElement();
tableBuilder.with(FACING, BlockFace.EAST).with(CHARGED, true).hasCustomModelData(2).hasRotation(Axis.Y, 270).addElement();
return tableBuilder.build();
}
}
When updating the CustomBlockState with the update method, the lookuptable matches the block's properties with its contents. If your block has, say, two boolean properties and an int property with possible values from 0 to 5, and your lookuptable is set up to match only the int property, both boolean properties are ignored. If no valid match is found, the custom model data defined in the constructor is used.