Compatibility between mods
HeberonYT opened this issue ยท 19 comments
Hello
I am using the Emoticons and PlayerRevive mod, but when I die the player stands up, and should be lying on the floor.
I hope you can add support for those effects
Minecraft 1.12.2
Emoticons https://www.curseforge.com/minecraft/mc-mods/emoticons
What about checking if the player is bleeding in the update loop?
else if (target.isPlayerSleeping() || PlayerReviveServer.isPlayerBleeding((EntityPlayer) target))
{
this.setActiveAction(this.sleeping);
}
Doesn't matter PlayerReviveServer also works on client side (the capability is synchronized).
You can also do it with reflections. This code should work just fine.
private static Method isPlayerBleedingMethod = loadPlayerReviveMethod();
private static Method loadPlayerReviveMethod() {
try {
return ReflectionHelper.findMethod(Class.forName("com.creativemd.playerrevive.server.PlayerReviveServer"), "isPlayerBleeding", "isPlayerBleeding", EntityPlayer.class);
} catch (ClassNotFoundException | UnableToFindMethodException e) {
return null;
}
}
public static boolean isPlayerBleeding(EntityPlayer player) {
if (isPlayerBleedingMethod != null)
return isPlayerBleedingMethod.invoke(player);
return false;
}
Alright, I'll give it a try once I'll have some time, thank you very much (I hope it's not too performance heavy ๐ )! ๐
Performance of reflections are not that bad. No idea why everybody is concerned about it. The only thing which affects performance a little bit is to find the class and the method itself, but this will be only done once. The invoke call will affect performance in no way.
Disable Emoticons non-emote animations, then it's going to work. It's not PlayerRevive's issue. All the animation related stuff is on my side, and I can't fix it (easily).
I don't use custom animations, all I do is to set sleeping
to true before the player will be rendered (and back to false once it's done) source.
Oh, I see, meanwhile I detect sleeping animation like this:
else if (target.isPlayerSleeping())
{
this.setActiveAction(this.sleeping);
}
Which in turn returns result from that EntityPlayer#sleeping
field. That's so peculiar... ๐ค
No, this is being run every loop update, for some reason this part of else if
... the whole method looks like this:
/**
* This method is designed specifically to isolate any controlling
* code (i.e. the ones that is responsible for switching between
* actions).
*/
protected void controlActions(EntityLivingBase target)
{
double dx = target.posX - this.prevX;
double dz = target.posZ - this.prevZ;
boolean creativeFlying = target instanceof EntityPlayer && ((EntityPlayer) target).capabilities.isFlying;
boolean wet = target.isInWater();
final float threshold = creativeFlying ? 0.1F : (wet ? 0.025F : 0.01F);
boolean moves = Math.abs(dx) > threshold || Math.abs(dz) > threshold;
if (this.emote != null)
{
this.setActiveAction(this.emote);
}
else if (target.getHealth() <= 0)
{
this.setActiveAction(this.dying);
}
else if (target.isPlayerSleeping())
{
this.setActiveAction(this.sleeping);
}
else if (wet)
{
this.setActiveAction(!moves ? this.swimmingIdle : this.swimming);
}
else if (target.isRiding())
{
Entity riding = target.getRidingEntity();
moves = Math.abs(riding.posX - this.prevX) > threshold || Math.abs(riding.posZ - this.prevZ) > threshold;
this.prevX = riding.posX;
this.prevZ = riding.posZ;
this.setActiveAction(!moves ? this.ridingIdle : this.riding);
}
else if (creativeFlying || target.isElytraFlying())
{
this.setActiveAction(!moves ? this.flyingIdle : this.flying);
}
else
{
float speed = (float) (Math.round(Math.sqrt(dx * dx + dz * dz) * 1000) / 1000.0);
if (target.isSneaking())
{
speed /= 0.065F;
this.setActiveAction(!moves ? this.crouchingIdle : this.crouching);
if (this.crouching != null) this.crouching.setSpeed(target.moveForward > 0 ? speed : -speed);
}
else if (!target.onGround && target.motionY < 0 && target.fallDistance > 1.25)
{
this.setActiveAction(this.falling);
}
else if (target.isSprinting() && this.sprinting != null)
{
this.setActiveAction(this.sprinting);
this.sprinting.setSpeed(speed / 0.281F);
}
else
{
this.setActiveAction(!moves ? this.idle : this.running);
speed /= 0.216F;
if (this.running != null) this.running.setSpeed(target.moveForward >= 0 ? speed : -speed);
if (this.walking != null) this.walking.setSpeed(target.moveForward > 0 ? speed : -speed);
}
if (target.onGround && !this.wasOnGround && !target.isSprinting() && this.prevMY < -0.5)
{
this.addAction(this.land);
}
}
if (!target.onGround && this.wasOnGround && Math.abs(target.motionY) > 0.2F)
{
this.addAction(this.jump);
this.wasOnGround = false;
}
/* Bow and consumables */
boolean shooting = this.wasShooting;
boolean consuming = this.wasConsuming;
ItemStack stack = target.getHeldItemMainhand();
if (!stack.isEmpty())
{
if (target.getItemInUseCount() > 0)
{
EnumAction action = stack.getItemUseAction();
if (action == EnumAction.BOW)
{
if (!this.actions.contains(this.shoot))
{
this.addAction(this.shoot);
}
this.wasShooting = true;
}
else if (action == EnumAction.DRINK || action == EnumAction.EAT)
{
if (!this.actions.contains(this.consume))
{
this.addAction(this.consume);
}
this.wasConsuming = true;
}
}
else
{
this.wasShooting = false;
this.wasConsuming = false;
}
}
else
{
this.wasShooting = false;
this.wasConsuming = false;
}
if (shooting && !this.wasShooting && this.shoot != null)
{
this.shoot.fade();
}
if (consuming && !this.wasConsuming && this.consume != null)
{
this.consume.fade();
}
if (target.hurtTime == target.maxHurtTime - 1)
{
this.addAction(this.hurt);
}
if (target.isSwingInProgress && target.swingProgress == 0 && !target.isPlayerSleeping())
{
this.addAction(this.swipe);
}
this.prevX = target.posX;
this.prevZ = target.posZ;
this.prevMY = target.motionY;
this.wasOnGround = target.onGround;
}
And somewhere down the line it gets called from the PlayerTickEvent
event.
Yeah, that won't work. As I said I only set it true before the rendering (and set it to false once the rendering is over):
RenderPlayerEvent.Pre -> sleeping = true
RenderPlayerEvent.Post -> sleeping = false
Which means it will always be false during the tick. Not sure if you can work with that.
Yeah, I don't think I can work with that... ๐ฉ
My action management code is heavily depends on the update loop, moving it to render loop will cause lots of issues on my side. Feel free to close that ticket.
Thanks for looking into it!
@CreativeMD no, sorry, I didn't had any time to do it, I still have a remainder on to try it out. I'll try later today, if I'll have some time.
I was able to fix it thanks to your code snippet (with minor adjustments). I tested it, and it seems to work fine. Here is the update @HeberonYT.
Thanks for helping, @CreativeMD, this issue can be closed! ๐
@mchorse have you had any time to try it out?