Mixin - how to shadow a field with a private type


#1

Hi all,

I have the following mixin -
@Mixin(ContainerBeacon.class)
public abstract class MixinContainerBeacon extends Container {

	@Shadow
	@Final
	private Slot beaconSlot;

	@Inject(method = "onContainerClosed", at = @At("HEAD"))
	public void onOnContainerClosed(EntityPlayer player, CallbackInfo ci) {
		if (player instanceof EntityPlayerMP) {
			if (beaconSlot.getStack().getCount() > 1) {
				EnchantmentCracker.dropItemCheck();
			}
		}
	}

}

However, the beaconSlot field is actually declared in ContainerBeacon as follows:
private final ContainerBeacon.BeaconSlot beaconSlot;
The class ContainerBeacon.BeaconSlot is private.
When I try to compile the code I get the following warning:
enchantment_cracking\build\sources\main\java\net\earthcomputer\enchcrack\mixin\MixinContainerBeacon.java:20: warning: Cannot find target for @Shadow field in net.minecraft.inventory.ContainerBeacon
@Shadow
^

I think this error is due to the shadow field’s type not matching the target field, but I’m unsure how to declare the shadow field to have the same type.

Any help appreciated


Mixin - How to shadow a field with private Inner class?
#2

You have two choices, a simple way and the slightly more complex way that avoids using access transformers.

  1. Use an access transformer to make the class public

or

  1. Apply an interface mixin to BeaconSlot (eg. IBeaconSlot) and then find the slot in the public Container::inventorySlots list using a simple instanceof check. The interface mixin can also provide @Accessor or @Invoker members to allow the members in the private class to be called.

Personally I prefer the latter because I hate access transformers. But the former is much simpler (though it does require re-decompiling the game, which is one of the main annoyances of access transformers).