Search in sources :

Example 1 with Mixin

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;
    }
}
Also used : LivingEntity(net.minecraft.world.entity.LivingEntity) Inject(org.spongepowered.asm.mixin.injection.Inject) SpongeDamageSources(org.spongepowered.common.event.cause.entity.damage.SpongeDamageSources) ParticleOptions(net.minecraft.core.particles.ParticleOptions) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) HandType(org.spongepowered.api.data.type.HandType) PlayerBridge(org.spongepowered.common.bridge.world.entity.player.PlayerBridge) SpongeCommonEventFactory(org.spongepowered.common.event.SpongeCommonEventFactory) CallbackInfoReturnable(org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable) CallbackInfo(org.spongepowered.asm.mixin.injection.callback.CallbackInfo) Mixin(org.spongepowered.asm.mixin.Mixin) DamageEntityEvent(org.spongepowered.api.event.entity.DamageEntityEvent) PlayerInventoryTransaction(org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction) Living(org.spongepowered.api.entity.living.Living) AttributeMap(net.minecraft.world.entity.ai.attributes.AttributeMap) Transaction(org.spongepowered.api.data.Transaction) At(org.spongepowered.asm.mixin.injection.At) CombatTracker(net.minecraft.world.damagesource.CombatTracker) Collection(java.util.Collection) Sponge(org.spongepowered.api.Sponge) Player(net.minecraft.world.entity.player.Player) DamageEventUtil(org.spongepowered.common.util.DamageEventUtil) List(java.util.List) BlockPos(net.minecraft.core.BlockPos) SoundEvent(net.minecraft.sounds.SoundEvent) Shadow(org.spongepowered.asm.mixin.Shadow) Optional(java.util.Optional) LivingEntityBridge(org.spongepowered.common.bridge.world.entity.LivingEntityBridge) ItemStack(net.minecraft.world.item.ItemStack) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) MoveEntityEvent(org.spongepowered.api.event.entity.MoveEntityEvent) ServerLocation(org.spongepowered.api.world.server.ServerLocation) HumanEntity(org.spongepowered.common.entity.living.human.HumanEntity) SoundSource(net.minecraft.sounds.SoundSource) EventContextKeys(org.spongepowered.api.event.EventContextKeys) ServerWorld(org.spongepowered.api.world.server.ServerWorld) Constants(org.spongepowered.common.util.Constants) Overwrite(org.spongepowered.asm.mixin.Overwrite) ServerLevel(net.minecraft.server.level.ServerLevel) SleepingEvent(org.spongepowered.api.event.action.SleepingEvent) ArrayList(java.util.ArrayList) AttributeInstance(net.minecraft.world.entity.ai.attributes.AttributeInstance) ItemStackUtil(org.spongepowered.common.item.util.ItemStackUtil) DamageSource(net.minecraft.world.damagesource.DamageSource) Stats(net.minecraft.stats.Stats) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LocalCapture(org.spongepowered.asm.mixin.injection.callback.LocalCapture) Nullable(javax.annotation.Nullable) UseItemStackEvent(org.spongepowered.api.event.item.inventory.UseItemStackEvent) Ticks(org.spongepowered.api.util.Ticks) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) FallingBlockDamageSource(org.spongepowered.api.event.cause.entity.damage.source.FallingBlockDamageSource) Redirect(org.spongepowered.asm.mixin.injection.Redirect) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) MobEffectInstance(net.minecraft.world.effect.MobEffectInstance) ShouldFire(org.spongepowered.common.event.ShouldFire) SpongeCommon(org.spongepowered.common.SpongeCommon) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Attribute(net.minecraft.world.entity.ai.attributes.Attribute) Cause(org.spongepowered.api.event.Cause) MovementTypes(org.spongepowered.api.event.cause.entity.MovementTypes) Entity(net.minecraft.world.entity.Entity) DamageFunction(org.spongepowered.api.event.cause.entity.damage.DamageFunction) Vector3d(org.spongepowered.math.vector.Vector3d) PlatformLivingEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformLivingEntityBridge) EquipmentSlot(net.minecraft.world.entity.EquipmentSlot) VecHelper(org.spongepowered.common.util.VecHelper) InteractionHand(net.minecraft.world.InteractionHand) MobEffect(net.minecraft.world.effect.MobEffect) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) LivingEntity(net.minecraft.world.entity.LivingEntity) HumanEntity(org.spongepowered.common.entity.living.human.HumanEntity) Entity(net.minecraft.world.entity.Entity) ArrayList(java.util.ArrayList) LivingEntity(net.minecraft.world.entity.LivingEntity) FallingBlockDamageSource(org.spongepowered.api.event.cause.entity.damage.source.FallingBlockDamageSource) CauseStackManager(org.spongepowered.api.event.CauseStackManager) DamageFunction(org.spongepowered.api.event.cause.entity.damage.DamageFunction) List(java.util.List) ArrayList(java.util.ArrayList) DamageEntityEvent(org.spongepowered.api.event.entity.DamageEntityEvent) Player(net.minecraft.world.entity.player.Player) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) ItemStack(net.minecraft.world.item.ItemStack)

Aggregations

ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 List (java.util.List)1 Optional (java.util.Optional)1 Nullable (javax.annotation.Nullable)1 BlockPos (net.minecraft.core.BlockPos)1 ParticleOptions (net.minecraft.core.particles.ParticleOptions)1 ServerLevel (net.minecraft.server.level.ServerLevel)1 SoundEvent (net.minecraft.sounds.SoundEvent)1 SoundSource (net.minecraft.sounds.SoundSource)1 Stats (net.minecraft.stats.Stats)1 InteractionHand (net.minecraft.world.InteractionHand)1 CombatTracker (net.minecraft.world.damagesource.CombatTracker)1 DamageSource (net.minecraft.world.damagesource.DamageSource)1 MobEffect (net.minecraft.world.effect.MobEffect)1 MobEffectInstance (net.minecraft.world.effect.MobEffectInstance)1 Entity (net.minecraft.world.entity.Entity)1 EquipmentSlot (net.minecraft.world.entity.EquipmentSlot)1 LivingEntity (net.minecraft.world.entity.LivingEntity)1 Attribute (net.minecraft.world.entity.ai.attributes.Attribute)1