In doing an overall cleanup of SpongeCommon's mixins, I've started moving away from using AT's for certain fields and using Accessor Mixins. While they work well in consumer code, I've found a corner case where the application of a SpongeForge mixin fails.
The setup:
Accessor Mixin that exists in SpongeCommon:
package org.spongepowered.common.mixin.core.entity;
@Mixin(net.minecraft.entity.Entity.class)
public interface AccessorEntity {
@Accessor("rand") Random accessor$getEntityRandom();
}
package org.spongepowered.mod.mixin.core.item;
@Mixin(value = ItemShears.class)
public abstract class MixinItemShears_Forge extends Item {
/**
* @author gabizou - June 21st, 2016
* @reason Rewrites the forge handling of this to properly handle
* when sheared drops are captured by whatever current phase the
* {@link PhaseTracker} is in.
*
* Returns true if the item can be used on the given entity, e.g. shears on sheep.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
@Overwrite(remap = false)
@Override // Overrides the forge added method from net.minecraft.item.Item
public boolean itemInteractionForEntity(ItemStack itemstack, EntityPlayer player, EntityLivingBase entity, EnumHand hand) {
if (entity.world.isRemote) {
return false;
}
if (entity instanceof IShearable) {
IShearable target = (IShearable) entity;
BlockPos pos = new BlockPos(entity.posX, entity.posY, entity.posZ);
if (target.isShearable(itemstack, entity.world, pos)) {
List<ItemStack> drops = target.onSheared(itemstack, entity.world, pos, EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, itemstack));
// Sponge Start - Handle drops according to the current phase
final Random random = ((AccessorEntity) entity).accessor$getRandom(); // This is where the application fails
}
return true;
}
return false;
}
}
The error that comes up isn't about AccessorEntity not being found in the hierarchy of net.minecraft.entity.Entity, but about AccessorEntity not being found in the hierarchy of net.minecraft.item.ItemShears:
if (!typeInfo.isMixin() || typeInfo.isAccessor()) { // Would need to add this method to ClassInfo
return desc;
}
I've been able to work around the issue by using the native method EntityLivingBase#getRNG(), but I feel that using accessor mixins in other mixin code should still be a valid practice.
In doing an overall cleanup of SpongeCommon's mixins, I've started moving away from using AT's for certain fields and using Accessor Mixins. While they work well in consumer code, I've found a corner case where the application of a SpongeForge mixin fails.
The setup: Accessor Mixin that exists in SpongeCommon:
The Consumer code in non-Mixin class
And consumer code in a SpongeForge Mixin class:
The error that comes up isn't about
AccessorEntity
not being found in the hierarchy ofnet.minecraft.entity.Entity
, but aboutAccessorEntity
not being found in the hierarchy ofnet.minecraft.item.ItemShears
:Now, given that I understand accessor mixins are quasi mixins and should be allowed, I feel the bug in this case lies here, in finding the
MixinTargetContext#transformSingleDescriptor()
. I've not been able to test whether changing that if statement to be as follows:I've been able to work around the issue by using the native method
EntityLivingBase#getRNG()
, but I feel that using accessor mixins in other mixin code should still be a valid practice.