Posted December 16, 20159 yr 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.
December 17, 20159 yr what do you mean view shakes? Is it like you get hurt whenever you heal? I've never experienced my view shaking when I heal in minecraft. I might be terribly wrong.. Like really, really wrong. But I'm just trying to help.
December 17, 20159 yr Author 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 Whatever Minecraft needs, it is most likely not yet another tool tier.
December 18, 20159 yr 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.
December 18, 20159 yr Author 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.
December 18, 20159 yr 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.
December 18, 20159 yr Author 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.
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.