Let's Talk: Reflection
LemmaEOF opened this issue ยท 10 comments
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?
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.
This behavior needs better documentation, if it's intended. Nowhere in the @Accessor
docs is it implied that this is possible.
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.
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.
[...] 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.
We have access wideners now, which eliminate the need for reflection of Minecraft in the rare cases necessary
Accessing private static fields is possible using @Accessor, and also access wideners, so I suppose the initial problem is now solved.