Trouble getting properties of blocks from BlockStates

Hello,

I am currently having some trouble getting certain properties of blocks from BlockStates. Specifically, I am trying to extract the block hardness level, the harvest level, and their names.

I noticed that BlockStates contain a block object, which contains the values that I want for this. The block object and its members are all private, though, so I have decided to use Reflection to get those values.

I wrote the following method for extracting the information from the blocks.

private Object getFieldFromString(Object object, String name) {
        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            if (field.getName().equals(name)) {
                try {
                    return field.get(object);
                } catch (IllegalAccessException ex) {
                    System.out.println("IAE");
                }
            }
        }
        return null;
}

Using reflection is definitely not optimal, since it breaks both abstraction and encapsulation, and neither is using generic Objects, but it seems necessary since the values that I want to access are private and since my project doesn’t have the NMS block sources.

For extracting the values that I want, I used getFieldFromString to first try and get blocks from the block states and then use the method again to get the fields that I want from the block. Unfortunately, this seems to only work with a small subset of the block in the game.

What might I be doing wrong here? Is there a better way for me to get these values?

did you try blockState.getProperty(HardnessProperty.class) yet?

Your problem might be that getDeclaredFields only returns fields of that exact class. Fields inherited from any superclass are not included. To get those you need to traverse all superclasses as well, using getSuperclass until that method returns null …
Of course @DosMike’s solution would be better if that property is enough ^^

1 Like

I have attempted using the getProperty method for getting the HardnessProperty, but when I try to print it out, all I see is “Optional.empty”.

I also modified my method to traverse up the class inheritance hierarchy. Here’s the modified version:

private ArrayList<Object> getFieldsFromString(Object object, String[] names) {
        ArrayList<String> namesArrayList = new ArrayList<>(Arrays.asList(names));
        ArrayList<Object> returns = new ArrayList<>();
        boolean firstRun = true;
        Class currentClass = object.getClass();
        while (!namesArrayList.isEmpty() || firstRun) { // this was originally set to to returns ArrayList instead of the namesArrayList
            if (currentClass == null || namesArrayList.isEmpty()) {
                break;
            }
            firstRun = false;
            for (Field field : currentClass.getDeclaredFields()) {
                field.setAccessible(true);
                for (int i = 0; i < namesArrayList.size(); i++) {
                    String name = names[i];
                    if (field.getName().equals(name)) {
                        try {
                            namesArrayList.remove(name);
                            returns.add(field.get(object));
                        } catch (IllegalAccessException ex) {
                            System.out.println("IAE");
                        }
                    }
                }
            }
            currentClass = currentClass.getSuperclass();
        }
        return returns;
    }

For some reason, this consistently fails to find anything. What might be the issue now?

Edit: I figured out the issue. I put a comment in the code block describing what it was. Thank you for your input.

1 Like