use of org.spongepowered.asm.mixin.Mixin in project SpongeCommon by SpongePowered.
the class LivingEntityMixin method bridge$damageEntity.
@Override
public boolean bridge$damageEntity(final DamageSource damageSource, float damage) {
if (this.shadow$isInvulnerableTo(damageSource)) {
return false;
}
final boolean isHuman = (LivingEntity) (Object) this instanceof Player;
// Sponge Start - Call platform hook for adjusting damage
damage = this.bridge$applyModDamage((LivingEntity) (Object) this, damageSource, damage);
// Sponge End
final float originalDamage = damage;
if (damage <= 0) {
return false;
}
final List<DamageFunction> originalFunctions = new ArrayList<>();
final Optional<DamageFunction> hardHatFunction = DamageEventUtil.createHardHatModifier((LivingEntity) (Object) this, damageSource);
final Optional<DamageFunction> armorFunction = DamageEventUtil.createArmorModifiers((LivingEntity) (Object) this, damageSource);
final Optional<DamageFunction> resistanceFunction = DamageEventUtil.createResistanceModifier((LivingEntity) (Object) this, damageSource);
final Optional<List<DamageFunction>> armorEnchantments = DamageEventUtil.createEnchantmentModifiers((LivingEntity) (Object) this, damageSource);
final Optional<DamageFunction> absorptionFunction = DamageEventUtil.createAbsorptionModifier((LivingEntity) (Object) this);
final Optional<DamageFunction> shieldFunction = DamageEventUtil.createShieldFunction((LivingEntity) (Object) this, damageSource, damage);
hardHatFunction.ifPresent(originalFunctions::add);
shieldFunction.ifPresent(originalFunctions::add);
armorFunction.ifPresent(originalFunctions::add);
resistanceFunction.ifPresent(originalFunctions::add);
armorEnchantments.ifPresent(originalFunctions::addAll);
absorptionFunction.ifPresent(originalFunctions::add);
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
DamageEventUtil.generateCauseFor(damageSource, frame);
final DamageEntityEvent event = SpongeEventFactory.createDamageEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) this, originalFunctions, originalDamage);
if (damageSource != SpongeDamageSources.IGNORED) {
// Basically, don't throw an event if it's our own damage source
SpongeCommon.post(event);
}
if (event.isCancelled()) {
return false;
}
damage = (float) event.finalDamage();
// Sponge Start - Allow the platform to adjust damage before applying armor/etc
damage = this.bridge$applyModDamageBeforeFunctions((LivingEntity) (Object) this, damageSource, damage);
// Sponge End
// Helmet
final ItemStack helmet = this.shadow$getItemBySlot(EquipmentSlot.HEAD);
// without using our mixin redirects in EntityFallingBlockMixin.
if ((damageSource instanceof FallingBlockDamageSource) || damageSource == DamageSource.ANVIL || damageSource == DamageSource.FALLING_BLOCK && !helmet.isEmpty()) {
helmet.hurtAndBreak((int) (event.baseDamage() * 4.0F + this.random.nextFloat() * event.baseDamage() * 2.0F), (LivingEntity) (Object) this, (entity) -> entity.broadcastBreakEvent(EquipmentSlot.HEAD));
}
boolean hurtStack = false;
// Shield
if (shieldFunction.isPresent()) {
this.shadow$hurtCurrentlyUsedShield((float) event.baseDamage());
hurtStack = true;
if (!damageSource.isProjectile()) {
final Entity entity = damageSource.getDirectEntity();
if (entity instanceof LivingEntity) {
this.shadow$blockUsingShield((LivingEntity) entity);
}
}
}
// Armor
if (!damageSource.isBypassArmor() && armorFunction.isPresent()) {
this.shadow$hurtArmor(damageSource, (float) event.baseDamage());
hurtStack = true;
}
// Sponge start - log inventory change due to taking damage
if (hurtStack && isHuman) {
PhaseTracker.SERVER.getPhaseContext().getTransactor().logPlayerInventoryChange((Player) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD);
// capture
((Player) (Object) this).inventoryMenu.broadcastChanges();
}
// Resistance modifier post calculation
if (resistanceFunction.isPresent()) {
final float f2 = (float) event.damage(resistanceFunction.get().modifier()) - damage;
if (f2 > 0.0F && f2 < 3.4028235E37F) {
if (((LivingEntity) (Object) this) instanceof net.minecraft.server.level.ServerPlayer) {
((net.minecraft.server.level.ServerPlayer) ((LivingEntity) (Object) this)).awardStat(Stats.DAMAGE_RESISTED, Math.round(f2 * 10.0F));
} else if (damageSource.getEntity() instanceof net.minecraft.server.level.ServerPlayer) {
((net.minecraft.server.level.ServerPlayer) damageSource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f2 * 10.0F));
}
}
}
double absorptionModifier = absorptionFunction.map(function -> event.damage(function.modifier())).orElse(0d);
if (absorptionFunction.isPresent()) {
absorptionModifier = event.damage(absorptionFunction.get().modifier());
}
final float f = (float) event.finalDamage() - (float) absorptionModifier;
this.shadow$setAbsorptionAmount(Math.max(this.shadow$getAbsorptionAmount() + (float) absorptionModifier, 0.0F));
if (f > 0.0F && f < 3.4028235E37F && ((LivingEntity) (Object) this) instanceof net.minecraft.server.level.ServerPlayer) {
((Player) (Object) this).awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f * 10.0F));
}
if (damage != 0.0F) {
if (isHuman) {
((Player) (Object) this).causeFoodExhaustion(damageSource.getFoodExhaustion());
}
final float f2 = this.shadow$getHealth();
this.shadow$setHealth(f2 - damage);
this.shadow$getCombatTracker().recordDamage(damageSource, f2, damage);
if (isHuman) {
if (damage < 3.4028235E37F) {
((Player) (Object) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(damage * 10.0F));
}
return true;
}
this.shadow$setAbsorptionAmount(this.shadow$getAbsorptionAmount() - damage);
}
return true;
}
}
Aggregations