Skip to content

Commit

Permalink
fix health scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
vectrixdevelops committed Oct 15, 2022
1 parent 2195961 commit c801b95
Showing 1 changed file with 19 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import org.spongepowered.common.bridge.data.SpongeDataHolderBridge;
import org.spongepowered.common.bridge.server.level.ServerPlayerEntityHealthScaleBridge;
import org.spongepowered.common.mixin.core.world.entity.player.PlayerMixin;
import org.spongepowered.common.util.Constants;

import java.util.Collection;
import java.util.Iterator;
Expand All @@ -58,8 +57,7 @@ public abstract class ServerPlayerMixin_HealthScale extends PlayerMixin implemen
@Shadow public ServerGamePacketListenerImpl connection;
// @formatter:on

private double impl$healthScale = Constants.Entity.Player.DEFAULT_HEALTH_SCALE;
private float impl$cachedModifiedHealth = -1;
private Double impl$healthScale = null;

@Inject(method = "doTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getArmorValue()I", ordinal = 1))
private void updateHealthPriorToArmor(final CallbackInfo ci) {
Expand All @@ -78,7 +76,6 @@ private void updateHealthPriorToArmor(final CallbackInfo ci) {
}

this.impl$healthScale = scale;
this.impl$cachedModifiedHealth = -1;
this.lastSentHealth = -1.0F;

((SpongeDataHolderBridge) this).bridge$offer(Keys.HEALTH_SCALE, scale);
Expand All @@ -89,8 +86,7 @@ private void updateHealthPriorToArmor(final CallbackInfo ci) {

@Override
public void bridge$resetHealthScale() {
this.impl$healthScale = Constants.Entity.Player.DEFAULT_HEALTH_SCALE;
this.impl$cachedModifiedHealth = -1;
this.impl$healthScale = null;
this.lastSentHealth = -1.0F;

((SpongeDataHolderBridge) this).bridge$remove(Keys.HEALTH_SCALE);
Expand All @@ -110,6 +106,7 @@ private void updateHealthPriorToArmor(final CallbackInfo ci) {
final FoodData foodData = this.shadow$getFoodData();
this.connection.send(new ClientboundSetHealthPacket(this.bridge$getInternalScaledHealth(), foodData.getFoodLevel(), foodData.getSaturationLevel()));
this.connection.send(new ClientboundUpdateAttributesPacket(this.shadow$getId(), dirtyInstances));

// Reset the dirty instances since they've now been manually updated on the client.
dirtyInstances.clear();

Expand All @@ -130,6 +127,7 @@ private void updateHealthPriorToArmor(final CallbackInfo ci) {
break;
}
}

if (!foundMax) {
// Means we didn't find the max health attribute and need to fetch the modifiers from
// the cached map because it wasn't marked dirty for some reason
Expand All @@ -144,6 +142,7 @@ private void updateHealthPriorToArmor(final CallbackInfo ci) {
if (!modifiers.isEmpty()) {
modifiers.forEach(attribute::addTransientModifier);
}

set.add(attribute);
}

Expand All @@ -154,36 +153,28 @@ private void updateHealthPriorToArmor(final CallbackInfo ci) {

@Override
public float bridge$getInternalScaledHealth() {
if (!this.bridge$isHealthScaled()) {
return this.shadow$getHealth();
}
if (this.impl$cachedModifiedHealth == -1) {
// Because attribute modifiers from mods can add onto health and multiply health, we
// need to replicate what the mod may be trying to represent, regardless whether the health scale
// says to show only x hearts.
final AttributeInstance maxAttribute = this.shadow$getAttribute(Attributes.MAX_HEALTH);
double modifiedScale = this.impl$healthScale;
// Apply additive modifiers
for (final AttributeModifier modifier : maxAttribute.getModifiers(AttributeModifier.Operation.ADDITION)) {
modifiedScale += modifier.getAmount();
}
float maximumHealth = this.shadow$getMaxHealth();
float healthScale = maximumHealth;

for (final AttributeModifier modifier : maxAttribute.getModifiers(AttributeModifier.Operation.MULTIPLY_BASE)) {
modifiedScale += modifiedScale * modifier.getAmount();
}
if (this.bridge$isHealthScaled()) {
// Attribute modifiers from mods can add onto health and multiply health, we need to replicate
// what the mod may be trying to represent, regardless whether the health scale says to show
// only x hearts.
final Collection<AttributeModifier> modifiers = this.shadow$getAttribute(Attributes.MAX_HEALTH).getModifiers();
final AttributeInstance attribute = new AttributeInstance(Attributes.MAX_HEALTH, i -> {});

for (final AttributeModifier modifier : maxAttribute.getModifiers(AttributeModifier.Operation.MULTIPLY_TOTAL)) {
modifiedScale *= 1.0D + modifier.getAmount();
}
attribute.setBaseValue(this.impl$healthScale);
modifiers.forEach(attribute::addTransientModifier);

this.impl$cachedModifiedHealth = (float) modifiedScale;
healthScale = (float) attribute.getValue();
}
return (this.shadow$getHealth() / this.shadow$getMaxHealth()) * this.impl$cachedModifiedHealth;

return (this.shadow$getHealth() / maximumHealth) * healthScale;
}

@Override
public boolean bridge$isHealthScaled() {
return this.impl$healthScale != Constants.Entity.Player.DEFAULT_HEALTH_SCALE;
return this.impl$healthScale != null;
}

}
Expand Down

0 comments on commit c801b95

Please sign in to comment.