Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

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.

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. :P

I might be terribly wrong.. Like really, really wrong. But I'm just trying to help.

  • 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 xD

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

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.

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

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.

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

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

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.