How to get block variant?

I noticed, that there is a way to get the block state with:


this code will return something like minecraft:stone[variant=diorite].

Would be great, if you guys can say me, how I can get “diorite” (variant). I was searching for a method like .getVariant(), but I could not find it…
Thansk :slight_smile:

Easiest way is through the Data API (definitely a core part of the API, learn here:

In this case, you can use BlockState.get(Keys.STONE_TYPE).get().getId() to the the String ID of the stone type.

As mentioned before, definitely read up on data. Entities, Tiles and Blocks all use the system for data related stuff, including health, variants, etc.

Sorry, but I don’t understand, how I can do it with your sample. Every time a user breaks a block, the given variant can be different.

Another problem is, that BlockState.get() is not a static method, how can I use it then?

Ok, I think I got it.
When I’m using this code:
String variant = event.getTransactions().get(0).getFinal().get(Keys.STONE_TYPE).get().getId();
Everything is fine :smile:
But I think “STONE_TYPE” is wrong?

People refer to methods like that.

BlockState#get() is usually more helpful, but what can you do? Programmers do what they do…

He really means:


Hey, please look at my edit :smiley:

Yeah i noticed, Discourse does that.

What do you mean it’s wrong?

is STONE_TYPE just for Blocks like stone, diorite etc? Because there is a SAND_TYPE too…

Well stone isn’t sand and sand isn’t stone.

If you’re wondering why there isn’t just a variant key, it’s a semantic difference really.

However it makes it so that you always get what you expect.

This way you can’t get sand type from stone and vice versa.

I’m using it like this now:

public void onLogBlockToolUse(ChangeBlockEvent event) {

        Optional<Player> LoptPlayer = event.getCause().first(Player.class);
        if (LoptPlayer.isPresent()) {
   + "");

When I place Blocks like Stone, Diorite and other types of stone, everything works, but when I try it with blocks liek dirt / sand, I get following error:

Could not pass ChangeBlockEvent$Place$Impl to Plugin{id=CaveCore, name=CaveCore, version=1.1}
java.util.NoSuchElementException: No value present
        at java.util.Optional.get( ~[?:1.8.0_66]
        at me.Hitzk0pf.CaveCore.listeners.BlockListeners.onLogBlockToolUse( ~[BlockListeners.class:?]
        at org.spongepowered.common.event.listener.ChangeBlockEventListener_BlockListeners_onLogBlockToolUse4.handle(Unknown Source) ~[?:?]
        at org.spongepowered.common.event.RegisteredListener.handle( ~[RegisteredListener.class:1.8-1577-2.1-DEV-880]
        at [SpongeModEventManager.class:1.8-1577-2.1-DEV-880]
        at org.spongepowered.mod.event.SpongeModEventManager.postBulk( [SpongeModEventManager.class:1.8-1577-2.1-DEV-880]
        at [SpongeModEventManager.class:1.8-1577-2.1-DEV-880]
        at [SpongeModEventManager.class:1.8-1577-2.1-DEV-880]
        at org.spongepowered.common.SpongeImpl.postEvent( [SpongeImpl.class:1.8-1577-2.1-DEV-880]
        at [aqu.class:?]
        at [qt.class:?]
        at [qt.class:?]
        at [qt.class:?]
        at net.minecraft.server.MinecraftServer.func_71190_q( [MinecraftServer.class:?]
        at net.minecraft.server.dedicated.DedicatedServer.func_71190_q( [po.class:?]
        at net.minecraft.server.MinecraftServer.func_71217_p( [MinecraftServer.class:?]
        at [MinecraftServer.class:?]
        at [?:1.8.0_66]
1 Like

Well right. It’s supposed to do that.

Only stone has stone type data…

You need to check if it’s stone or cobblestone first before you can try to get it’s type.

Also why do you need to add the + "" at the end? It’s already a string…

I know, that this is a string, just ignore it :smile:
How should I do that? This sounds like a huge walk around?
Is there really no way to simply get the variant of every block?
I mean this fires onBlockChange, so I have to check x times which block was changed?

Well let me ask you.

Do iron blocks have variants?

does grass have variants?

does bedrock have variants?

Not all blocks have variants, and they certainly don’t all have the same variants. They need to be separated to make any sense at all.

Would it be better, when I take (e.g.) minecraft:stone[variant=diorite], check with a regex if it contains the word “variant” and use another regex to get the value of the key variant?


Unless you want your code to break unexpectedly…

toString() is generally not a reliable source of data…

Hmm, so I have to use for example 20 “ifs”? Really? :frowning:

What do you even need the data for anyway?

This is looking like an XY problem.

I’m building a job plugin. A user gets different amounts for different blocks. I don’t want to let the users get the same amount of money for breaking / placing (e.g.) stone and diorite…

Yeah it looks like you get to have fun with a bunch of if statements.

The problem is that variant returns funny things for things like slabs and stairs.

You pretty much have to do this case by case…

1 Like

Thanks for helping me!