This doesn't seem to work properly for me, I keep getting a this error:
java.lang.IllegalAccessException: no private access for invokespecial: class net.minecraft.entity.monster.EntityMob, from net.minecraft.entity.monster.EntityMob/public
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:850) ~[?:1.8.0_131]
at java.lang.invoke.MethodHandles$Lookup.checkSpecialCaller(MethodHandles.java:1572) ~[?:1.8.0_131]
at java.lang.invoke.MethodHandles$Lookup.findSpecial(MethodHandles.java:1002) ~[?:1.8.0_131]
Here's the relevant code:
// static and final are important, they ensure this can be optimized by the JVM
protected static final MethodHandle mobLivingUpdate;
static {
try {
// with lookup().in(EntityMob.class) we obtain access to things that are "private" in EntityMob.
// findSpecial invokes the method in EntityMob.class without checking for overriding methods (such as the one in EntityEnderman)
mobLivingUpdate = MethodHandles.lookup().in(EntityMob.class).findSpecial(EntityMob.class, "onLivingUpdate", MethodType.methodType(void.class), EntityMob.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
@Override
public void onLivingUpdate()
{
if (this.world.isRemote)
{
for (int i = 0; i < 2; ++i)
{
if (oldAppearance) {
this.world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, 0.0D, 0.0D, 0.0D);
} else {
this.world.spawnParticle(EnumParticleTypes.PORTAL, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height - 0.25D, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D, new int[0]);
}
}
}
this.isJumping = false;
try {
// invokeExact is important, it ensures that this can be optimized by the JVM
mobLivingUpdate.invokeExact((EntityMob) this);
} catch (Throwable x) {
throw new RuntimeException(x);
}
}