Minecraft 1.12 modding with forge – 17 – Blockstates

Hello everyone! In this part I’ll explain what blockstates are, why you can use them and how you can use them.

Prerequisites

    • You don’t need to have anything, but you should probably understand how java works and how to add blocks.

Why use blockstates?

As you may know, some blocks in minecraft can have different properties. For example logs can be rotated, crops for their age, leaves to know if they should decay, redstone for the connections and power level, etc. You may also know (especially if you played minecraft a couple of updates ago) that those blocks have so called metadata. A number which translates to the properties of the block. It used to be that you had to work with those numbers every where, but these are almost completely replaced with blockstates now (They are still saved using those numbers but everywhere else you use the blockstates).

How to use blockstates in code:

The properties are defined using IProperty. There are multiple types already built into minecraft you can use:

  • PropertyBool, for when you want to save a boolean. (Ex. if sponge is wet)
  • PropertyEnum<T>, for when you need to save an enum. (Ex. color)
    • PropertyDirection, this is actually a PropertyEnum but because this is used so much they made it its own type. (Ex. torches)
  • PropertyInteger, for an integer. (Ex. age)

You can also make some yourself, but that’ll not be covered in this part.

To use them in your block you need to define them somewhere. Vanilla redefines them in every block, but this is not necessary. I’ll do it the vanilla way.
The name you use in your property is very important. This name will be referenced in your model files so you can change the model for every change in your property!

Example:

public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 5);

This will create a property for the age of ex. a plant. (This was taken from BlockChorusFlower)

[collapse]

But this just makes a variable, we have to tell minecraft we want to use it. You do this by overriding createBlockState. Here you need to return a BlockStateContainer. This will take your block, and an IProperty array with all of your properties, it will then generate every unique combination of properties and save it. This is all done on startup, and is only done once.

Example:

protected BlockStateContainer createBlockState() {
    return new BlockStateContainer(this, new IProperty[] {AGE});
}

This will create a BlockStateContainer with the AGE property. (This was taken from BlockChorusFlower)

[collapse]

An IBlockstate is a combination of the block, the properties of the block and the values of those properties. You can get the values by getting the blockstate, for example using world.getBlockState(pos), and calling getValue with the property you want to know.

Example:

state.getValue(BlockLog.LOG_AXIS);

This will return the axis of the log (You need to make sure it has the property first, or else it will crash!)

[collapse]

Saving the blockstates (or not):

But we still need a way to convert from IBlockState to metadata, and the other way around, to save the block. We do this by overriding getStateFromMeta and getMetaFromState.
In the getMetaFromState method you get the IBlockState that should be saved and return an int. You may think: “an integer can store a lot of values, so I can add a lot of states!”. But minecraft only uses the lower 4 bits (and crashes if you return a value > 15).

In the getStateFromMeta method you get an integer and you need to convert that to an IBlockState, ofcourse you need to make sure that your getStateFromMeta returns the same blockstate as your getMetaFromState had when creating the integer.
You may want to read up on bitmasks and how to use them, they are used a lot in these methods!

But what if you need to have more states? Well if you can calculate them from the world you are in luck! Fences for example don’t save their connections, they calculate them when needed. If you want to use this you still need to add the property to your block normally, but you don’t save it (or load it) in the getMetaFromState (and getStateFromMeta) methods, and you need to override getActualState here you get the saved state, the world and the position and you should return the actual calculated state.

How to add blockstate dependent models:

Now we have to tell minecraft how to render the different blockstates. For this you need to define every variant in assets/MODID/blockstates/BLOCKNAME.json. For every variant you can define which model file to use and which rotation it should have. For example if you have one enum property with the values: x, y, z and none your blockstate file could look like this (This is a blockstate file for a log for example):

This was again a tutorial with a lot of theory, but you should now be able to implement custom logs, or leaves, or any other block with custom properties! In the next part I’ll show how to implement custom logs. But you can already try it for yourself! (Hint: extend BlockLog, you only need to override 3 methods!).
I hope this helped! And as always for any questions, feel free to comment or join the discord!

~suppergerrie2

Posted in Forge tutorial, Forge Tutorial 1.12.

6 Comments

    • Did you try setting the blocks using /setblock?
      Placing it and having it rotate needs more code, check the log blocks or other rotatable blocks for that.

  1. Nice ! Finally found someone that explains this in a clear way !
    Been doing my mod using your tutorial for a while now and I’d like to know if you planned on coverring the ForgeEnergy

    Anyway, keep up the good work :3

  2. Omg THANK YOU! I have been searching for SO LONG to find a clear, concise explanation of what each method is for. Thank you thank you thank you!!

Comments are closed.