Jump to content

[1.7.10] Stop view shaking when healing?


IceMetalPunk

Recommended Posts

I've made a custom enchantment for armor that heals you if you wear it in the rain. It works fine, but whenever it heals the player (using PlayerEntity#heal()), the view shakes. Since it heals them once per tick until they're fully healed, that gets annoying. The heal() method simply calls the setHealth() method, so doing that directly does nothing. And setHealth() updates a dataWatcher that I don't have access to.

 

So basically, how can I heal the player without the shaking animation? (Note: I'm healing in tiny amounts per tick, like 0.05 to 0.2 per tick. If that matters.)

 

*EDIT* More info: whenever I heal the player with these amounts, he also flashes red. So it's as though healing the player with such small amounts is animating as though it's damaging him, despite still correctly adding hearts. How can I get around this?

 

*EDIT 2* I've made it work by healing in integer amounts, but doing it less often. Unfortunately, that requires a constantly-running cooldown timer, which I was hoping to avoid. If there's a way to make it work with tiny amounts, let me know, please; meanwhile, the cooldown will have to stay.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Yep. It seems if you heal the player with a sufficiently small fractional amount, it will heal them, but also trigger the damage animation as well. Probably a precision error at fault, I'd guess. So just don't heal the player too little, is what I learned from this xD

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

What do "Instant Health" etc potions do? Does one of them use another "entrance" to improve health besides the call you're making?

 

Have you walked through the setHealth method and whatever it calls? Is there an event in there that you could catch, handle and cancel before the shaking starts?

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

Nope, the potions use the heal() method, but they always heal in integer amounts, so they avoid this problem. I did walk through the callstack...it's a mess of stack and packet handling and obfuscated members, but this is the general process:

 

EntityPlayerMP#heal calls EntityPlayerMP#setHealth, which updates a dataWatcher value.

EntityPlayerMP#onUpdateEntity checks if the player's health had changed, and if so, sends an S06PacketUpdateHealth to the client.

That packet gets sent over to an INetHandler for processing on the client.

That net handler calls the game controller's player's EntityClientPlayerMP#setPlayerSPHealth method to set the health.

This calls EntityPlayer#setHealth as well as EntityPlayerSP#setPlayerSPHealth.

That then sets the EntityPlayerSP's health (client player's health) and checks previous health minus updated health as a float, and if it's < 0, it sets the EntityPlayerSP#hurtResistantTime to half the max. (This is why I believe the issue to be a float precision error.)

 

And that value is what determines whether the damage animation should be rendered or not.

 

So there's not really anywhere to intercept it, since the client's health is updated in the same method that sets hurtResistantTime.

 

I mean, technically, I could set hurtResistantTime back to 0 after, since it's public, but if you actually *are* getting hurt by something, doing that every step would remove your hit immunity, which is definitely not desired.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Nope, the potions use the heal() method, but they always heal in integer amounts, so they avoid this problem. I did walk through the callstack...it's a mess of stack and packet handling and obfuscated members, but this is the general process:

 

EntityPlayerMP#heal calls EntityPlayerMP#setHealth, which updates a dataWatcher value.

EntityPlayerMP#onUpdateEntity checks if the player's health had changed, and if so, sends an S06PacketUpdateHealth to the client.

That packet gets sent over to an INetHandler for processing on the client.

That net handler calls the game controller's player's EntityClientPlayerMP#setPlayerSPHealth method to set the health.

This calls EntityPlayer#setHealth as well as EntityPlayerSP#setPlayerSPHealth.

That then sets the EntityPlayerSP's health (client player's health) and checks previous health minus updated health as a float, and if it's < 0, it sets the EntityPlayerSP#hurtResistantTime to half the max. (This is why I believe the issue to be a float precision error.)

 

And that value is what determines whether the damage animation should be rendered or not.

 

So there's not really anywhere to intercept it, since the client's health is updated in the same method that sets hurtResistantTime.

 

I mean, technically, I could set hurtResistantTime back to 0 after, since it's public, but if you actually *are* getting hurt by something, doing that every step would remove your hit immunity, which is definitely not desired.

 

That looks wrong (what I highlighted in red). If you've been injured, then your previous health is greater than updated, which would yield a positive diff, not <0. Is that really how it is? Or is the expression new-health minus previous-health? Float should have enough precision to discriminate at .05. I'd set a break point on that line and run the debugger (or temporarily print output just before it)  to see what numbers are really there.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

Sorry, typo, it is in fact >, not <. I can't get access to the code right now, but I've already released the mod anyway (using integer amounts and a cooldown timer), so it's not terribly important anymore. If you'd like to see it in action, just add a tick handler that calls EntityPlayerMP#heal(0.05) each tick and see for yourself :)

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.