How to get block variant?

As an alternative to using the Data API, you can use BlockTraits. These operate by using strings, so for example just use “variant” to get the variant trait of a block.
Note than in minecraft not all variants are called “variant” for example wool color is called “color”.
You may find it useful to search through the EnumTraits class in the API.

Here is an example of getting the variant of a block, the blockVariant variable is the same that is shown when you do BlockState#toString. (Note: code untested)

Optional<BlockTrait<?>> variantTrait = block.getTrait("variant");
if (variantTrait.isPresent()) {
    Optional<?> variant = block.getTraitValue(variantTrait.get());
    if (variant.isPresent()) {
        String blockVariant = variant.get().toString();
    }
}
2 Likes

Alternatively, it would be possible to go over all DataManipulators and check for if one extends VariantData. (Code untested)

for(DataManipulator data : block.getContainers()) {
    if (data instanceof VariantData) {
        Object value = ((VariantData) data).type().get();
        String blockVariant = (value instanceof CatalogType) ? ((CatalogType) value).getId() : value.toString();
    }
}

The way the code is written you may experience some weird stuff when there’s more than one VariantData. That can happen for Quartz (as they can have a QuartzData and an AxisData), stairs etc, basically everything that can have both a variant and a direction.

But the Data API way, won’t necessarily work for modded blocks either.

The “variant=diorite” is an inbuilt Mojang concept into the block, which in Sponge is called a trait.

What you really want, is a way for a block to match a user inputtable string right? like in a config?

So you could either test against BlockTypes or BlockStates. However, BlockStates are difficult to work with, as some of their traits that distinguish block states are useless for some uses, take redstone power for a jobs plugin for example. So what we need, is a serializable Predicate Something that can test blocks to see if they match (similar to your regex idea) and be easy to input by users.

Blood suggested that we use the old meta values that blocks had, but all that does is restrict you to dealing with specific blockstates, and you would still need to create a set of blockstates that are aliased under another name, e.g. Leaves would cover blocktypes leaves and leaves2…

The other idea blood had, was that the blockstates be dumped to a file as strings, so it was at least easy to copy them and refer to them in config files, in order to create these sets, This is a somewhat better idea and would be the simplest solution that seems feasible.

However I propose another solution, slightly more complex, but certainly more flexible and easy to use for more advanced tests, resulting in less work for server admins that can understand the concept.

3 Likes

Hello, I apologize for bringing this back to the surface, but I’d like to know how this could be applied to a player holding an item player.getItemInHand(). How can I get the variant from this? Thanks.

Answered here: [Solved] Item In Hand Properties - #4 by gabizou
Docs have a page on manipulating item stacks and how to use Data API.

after 3 years, is there any good way to do this, easy for server admin to edit the config file ?