PlayerRevive

PlayerRevive

5M Downloads

Compatibility between mods

HeberonYT opened this issue ยท 19 comments

commented

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

commented

What about checking if the player is bleeding in the update loop?

else if (target.isPlayerSleeping() || PlayerReviveServer.isPlayerBleeding((EntityPlayer) target))
{
    this.setActiveAction(this.sleeping);
}
commented

This code run is only on the client side.

commented

Doesn't matter PlayerReviveServer also works on client side (the capability is synchronized).

commented

Huh, is there a way to do that beside adding the mod jar to dependencies list?

commented

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;
	}
commented

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 ๐Ÿ˜…)! ๐Ÿ‘

commented

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.

commented

Alright, awesome! I'll give it a try on the weekend ๐Ÿ™‚

commented

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).

commented

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.

commented

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... ๐Ÿค”

commented

Maybe PlayerRevive sets it too late, so this line will never be executed?

commented

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.

commented

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.

commented

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!

commented

@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.

commented

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! ๐Ÿ˜Š

commented

@mchorse have you had any time to try it out?

commented

Nice! Thank you very much! Good to see it being solved.