Fabric API

Fabric API

106M Downloads

Let's Talk: Reflection

LemmaEOF opened this issue ยท 10 comments

commented

Mixin is great, but it absolutely falls apart when trying to deal with getting private static fields. Reflection is what you want to use in this case, but Fabric doesn't really have anything to help with reflections, or even much of an indication/reminder that reflection exists. What tools could Fabric provide to make reflections seem like a more feasible option?

commented

Does Mixin actually have issues with static fields? In Better Together I do

@Mixin(CreativePlayerInventoryScreen.class)
public interface LetMeIn {
	@Accessor
	static BasicInventory getInventory() {
		return null;
	}
}

Which means I can get CreativePlayerInventoryScreen#inventory doing LetMeIn.getInventory(). Maybe this is exploiting a missing check but as far as I could tell this is what accessors are designed to let you do.

commented

This behavior needs better documentation, if it's intended. Nowhere in the @Accessor docs is it implied that this is possible.

commented

Can confirm this works, I've just done

@Mixin(PlayerContainer.class)
public interface PlayerContainerAccessor {
    @Accessor(value = "EQUIPMENT_SLOT_ORDER")
    static EquipmentSlot[] getEquipmentSlotOrder() {
        return null;
    }

    @Accessor(value = "EMPTY_ARMOR_SLOT_IDS")
    static String[] getEmptyArmorSlotIds() {
        return null;
    }
}

and I can call the mixin interface directly. Im not sure if this is intended, since it fails if you make the Mixin a class and not an interface.

commented

It is intended behavior, see the @Accessor javadoc.
They can also be used to create "Accessor Mixins" which are special mixins defined as interfaces which must only contain Accessor and Invoker methods. Unlike normal mixins however, Accessor Mixins are accessible via user code and thus no surrogate "Duck" interface is required to expose the generated methods, the mixin itself acts as its own Duck.

commented

Nothing there says anything about static methods.

commented

Hmm, you are right

commented

[...] but it absolutely falls apart when trying to deal with getting private static fields.

This behavior needs better documentation, if it's intended.

First off, in my opinion, this kind of behavior is literally implied from the documentation of @Accessor, but let's continue. Just based on the fact that the code snippet for using @Accessor on static members was posted earlier and deemed successful, it should've been blatantly obvious that this behavior was intentional.

Here, you can see that Mixin has explicit conditions for handling static members:

If static members were not intended to be exposed using @Accessor, then it wouldn't work at all.

Consider the following:

public class Main {

    private static int static_field;
    private int instance_field;

    public static void static_method() {}
    public void instance_method() {}
}

Static field access:

  • GETSTATIC Main.static_field:I
    

Static method invocation:

  • INVOKESTATIC Main.static_method()V
    

Instance field access:

  • ALOAD 0
    GETFIELD Main.instance_field:I
    

Instance method invocation:

  • ALOAD 0
    INVOKEVIRTUAL Main.instance_method()V
    

Accessibility to a better reflections system is pointless when Mixin is available and perfectly capable of what is achieved with reflections, while being drastically faster.

commented

mixin

๐Ÿคข ๐Ÿคข ๐Ÿคข ๐Ÿคข ๐Ÿคข ๐Ÿคข ๐Ÿคข ๐Ÿคข ๐Ÿคข

commented

We have access wideners now, which eliminate the need for reflection of Minecraft in the rare cases necessary

commented

Accessing private static fields is possible using @Accessor, and also access wideners, so I suppose the initial problem is now solved.