use of net.minecraft.world.entity.LivingEntity in project SpongeCommon by SpongePowered.
the class MobMixin method doHurtTarget.
/**
* @author gabizou - April 8th, 2016
* @author gabizou - April 11th, 2016 - Update for 1.9 additions
* @author Aaron1011 - November 12, 2016 - Update for 1.11
* @author Zidane - Minecraft 1.14.4
*
* @reason Rewrite this to throw an {@link AttackEntityEvent} and process correctly.
*
* float f | baseDamage
* int i | knockbackModifier
* boolean flag | attackSucceeded
*
* @param targetEntity The entity to attack
* @return True if the attack was successful
*/
@Overwrite
public boolean doHurtTarget(final net.minecraft.world.entity.Entity targetEntity) {
// Sponge Start - Prepare our event values
// float baseDamage = this.getEntityAttribute(Attributes.attackDamage).getAttributeValue();
final double originalBaseDamage = this.shadow$getAttribute(Attributes.ATTACK_DAMAGE).getValue();
final List<DamageFunction> originalFunctions = new ArrayList<>();
// Sponge End
float knockbackModifier = (float) this.shadow$getAttribute(Attributes.ATTACK_KNOCKBACK).getValue();
if (targetEntity instanceof LivingEntity) {
// Sponge Start - Gather modifiers
originalFunctions.addAll(DamageEventUtil.createAttackEnchantmentFunction(this.shadow$getMainHandItem(), ((LivingEntity) targetEntity).getMobType(), // 1.0F is for full attack strength since mobs don't have the concept
1.0F));
// baseDamage += EnchantmentHelper.getModifierForCreature(this.getHeldItem(), ((EntityLivingBase) targetEntity).getCreatureAttribute());
knockbackModifier += EnchantmentHelper.getKnockbackBonus((Mob) (Object) this);
}
// Sponge Start - Throw our event and handle appropriately
final DamageSource damageSource = DamageSource.mobAttack((Mob) (Object) this);
PhaseTracker.getCauseStackManager().pushCause(damageSource);
final AttackEntityEvent event = SpongeEventFactory.createAttackEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.entity.Entity) targetEntity, originalFunctions, knockbackModifier, originalBaseDamage);
SpongeCommon.post(event);
PhaseTracker.getCauseStackManager().popCause();
if (event.isCancelled()) {
return false;
}
knockbackModifier = event.knockbackModifier();
// boolean attackSucceeded = targetEntity.attackEntityFrom(DamageSource.causeMobDamage(this), baseDamage);
final boolean attackSucceeded = targetEntity.hurt(damageSource, (float) event.finalOutputDamage());
// Sponge End
if (attackSucceeded) {
if (knockbackModifier > 0 && targetEntity instanceof LivingEntity) {
((LivingEntity) targetEntity).knockback(knockbackModifier * 0.5F, Mth.sin(this.yRot * ((float) Math.PI / 180F)), -Mth.cos(this.yRot * ((float) Math.PI / 180F)));
this.shadow$setDeltaMovement(this.shadow$getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
}
final int j = EnchantmentHelper.getFireAspect((Mob) (Object) this);
if (j > 0) {
targetEntity.setSecondsOnFire(j * 4);
}
if (targetEntity instanceof Player) {
final Player playerentity = (Player) targetEntity;
final ItemStack mainHandItem = this.shadow$getMainHandItem();
final ItemStack useItem = playerentity.isUsingItem() ? playerentity.getUseItem() : ItemStack.EMPTY;
this.shadow$maybeDisableShield(playerentity, mainHandItem, useItem);
}
this.shadow$doEnchantDamageEffects((Mob) (Object) this, targetEntity);
this.shadow$setLastHurtMob(targetEntity);
}
return attackSucceeded;
}
use of net.minecraft.world.entity.LivingEntity in project SpongeCommon by SpongePowered.
the class MobMixin method onSetAttackTarget.
/**
* @author gabizou - January 4th, 2016
*
* This is to instill the check that if the entity is vanish, check whether they're untargetable
* as well.
*
* @param entitylivingbaseIn The entity living base coming in
*/
@Inject(method = "setTarget", at = @At("HEAD"), cancellable = true)
private void onSetAttackTarget(@Nullable final LivingEntity entitylivingbaseIn, final CallbackInfo ci) {
if (this.level.isClientSide || entitylivingbaseIn == null) {
return;
}
// noinspection ConstantConditions
if (EntityUtil.isUntargetable((net.minecraft.world.entity.Entity) (Object) this, entitylivingbaseIn)) {
this.target = null;
ci.cancel();
return;
}
if (ShouldFire.SET_A_I_TARGET_EVENT) {
final SetAITargetEvent event = SpongeCommonEventFactory.callSetAttackTargetEvent((Entity) entitylivingbaseIn, (Agent) this);
if (event.isCancelled()) {
ci.cancel();
} else {
this.target = ((LivingEntity) event.target().orElse(null));
}
}
}
use of net.minecraft.world.entity.LivingEntity in project SpongeCommon by SpongePowered.
the class PlayerMixin_Attack_Impl method attack.
// @formatter:on
/**
* @author gabizou - April 8th, 2016
* @author gabizou - April 11th, 2016 - Update for 1.9 - This enitre method was rewritten
* @author i509VCB - February 15th, 2020 - Update for 1.14.4
* @author gabizou - November 15th, 2020 - Update for 1.15.2
*
* @reason Rewrites the attack to throw an {@link AttackEntityEvent} prior
* to the ensuing {@link org.spongepowered.api.event.entity.DamageEntityEvent}. This should cover all cases where players are
* attacking entities and those entities override {@link LivingEntity#hurt(DamageSource, float)}
* and effectively bypass our damage event hooks.
*
* LVT Rename Table:
* float f | damage |
* float f1 | enchantmentDamage |
* float f2 | attackStrength |
* boolean flag | isStrongAttack |
* boolean flag1 | isSprintingAttack |
* boolean flag2 | isCriticalAttack | Whether critical particles will spawn and of course, multiply the output damage
* boolean flag3 | isSweapingAttack | Whether the player is sweaping an attack and will deal AoE damage
* int i | knockbackModifier | The knockback modifier, must be set from the event after it has been thrown
* float f4 | targetOriginalHealth | This is initially set as the entity original health
* boolean flag4 | litEntityOnFire | This is an internal flag to where if the attack failed, the entity is no longer set on fire
* int j | fireAspectModifier | Literally just to check that the weapon used has fire aspect enchantments
* double d0 | distanceWalkedDelta | This checks that the distance walked delta is more than the normal walking speed to evaluate if you're making a sweaping attack
* double d1 | targetMotionX | Current target entity motion x vector
* double d2 | targetMotionY | Current target entity motion y vector
* double d3 | targetMotionZ | Current target entity motion z vector
* boolean flag5 | attackSucceeded | Whether the attack event succeeded
*
* @param targetEntity The target entity
*/
@Overwrite
public void attack(final Entity targetEntity) {
// Sponge Start - Add SpongeImpl hook to override in forge as necessary
if (!PlatformHooks.INSTANCE.getEntityHooks().checkAttackEntity((net.minecraft.world.entity.player.Player) (Object) this, targetEntity)) {
return;
}
// Sponge End
if (targetEntity.isAttackable()) {
if (!targetEntity.skipAttackInteraction((net.minecraft.world.entity.player.Player) (Object) this)) {
// Sponge Start - Prepare our event values
// float damage = (float) this.getEntityAttribute(Attributes.ATTACK_DAMAGE).getAttributeValue();
final double originalBaseDamage = this.shadow$getAttribute(Attributes.ATTACK_DAMAGE).getValue();
float damage = (float) originalBaseDamage;
// Sponge End
float enchantmentDamage = 0.0F;
// Sponge Start - Redirect getting enchantments for our damage event handlers
// if (targetEntity instanceof LivingEntity) {
// enchantmentDamage = EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), ((LivingEntity) targetEntity).getCreatureAttribute());
// } else {
// enchantmentDamage = EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), CreatureAttribute.UNDEFINED);
// }
final float attackStrength = this.shadow$getAttackStrengthScale(0.5F);
final List<DamageFunction> originalFunctions = new ArrayList<>();
final MobType creatureAttribute = targetEntity instanceof LivingEntity ? ((LivingEntity) targetEntity).getMobType() : MobType.UNDEFINED;
final List<DamageFunction> enchantmentModifierFunctions = DamageEventUtil.createAttackEnchantmentFunction(this.shadow$getMainHandItem(), creatureAttribute, attackStrength);
// This is kept for the post-damage event handling
final List<DamageModifier> enchantmentModifiers = enchantmentModifierFunctions.stream().map(ModifierFunction::modifier).collect(Collectors.toList());
enchantmentDamage = (float) enchantmentModifierFunctions.stream().map(ModifierFunction::function).mapToDouble(function -> function.applyAsDouble(originalBaseDamage)).sum();
originalFunctions.addAll(enchantmentModifierFunctions);
// Sponge End
originalFunctions.add(DamageEventUtil.provideCooldownAttackStrengthFunction((net.minecraft.world.entity.player.Player) (Object) this, attackStrength));
damage = damage * (0.2F + attackStrength * attackStrength * 0.8F);
enchantmentDamage = enchantmentDamage * attackStrength;
this.shadow$resetAttackStrengthTicker();
if (damage > 0.0F || enchantmentDamage > 0.0F) {
final boolean isStrongAttack = attackStrength > 0.9F;
boolean isSprintingAttack = false;
boolean isCriticalAttack = false;
boolean isSweapingAttack = false;
int knockbackModifier = 0;
knockbackModifier = knockbackModifier + EnchantmentHelper.getKnockbackBonus((net.minecraft.world.entity.player.Player) (Object) this);
if (this.shadow$isSprinting() && isStrongAttack) {
// Sponge - Only play sound after the event has be thrown and not cancelled.
// this.world.playSound((EntityPlayer) null, this.posX, this.posY, this.posZ, SoundEvents.entity_player_attack_knockback, this.getSoundCategory(), 1.0F, 1.0F);
++knockbackModifier;
isSprintingAttack = true;
}
isCriticalAttack = isStrongAttack && this.fallDistance > 0.0F && !this.onGround && !this.shadow$onClimbable() && !this.shadow$isInWater() && !this.shadow$hasEffect(MobEffects.BLINDNESS) && !this.shadow$isPassenger() && targetEntity instanceof LivingEntity;
isCriticalAttack = isCriticalAttack && !this.shadow$isSprinting();
final EventHooks.CriticalHitResult criticalResult = PlatformHooks.INSTANCE.getEventHooks().callCriticalHitEvent((net.minecraft.world.entity.player.Player) (Object) this, targetEntity, isCriticalAttack, isCriticalAttack ? 1.5F : 1.0F);
isCriticalAttack = criticalResult.criticalHit;
if (isCriticalAttack) {
// Sponge Start - add critical attack tuple
// damage *= 1.5F; // Sponge - This is handled in the event
originalFunctions.add(DamageEventUtil.provideCriticalAttackTuple((net.minecraft.world.entity.player.Player) (Object) this, criticalResult.modifier));
// Sponge End
}
// damage = damage + enchantmentDamage; // Sponge - We don't need this since our event will re-assign the damage to deal
final double distanceWalkedDelta = (double) (this.walkDist - this.walkDistO);
final ItemStack heldItem = this.shadow$getMainHandItem();
if (isStrongAttack && !isCriticalAttack && !isSprintingAttack && this.onGround && distanceWalkedDelta < (double) this.shadow$getSpeed()) {
if (heldItem.getItem() instanceof SwordItem) {
isSweapingAttack = true;
}
}
// Sponge Start - Create the event and throw it
final DamageSource damageSource = DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this);
final boolean isMainthread = !this.level.isClientSide;
if (isMainthread) {
PhaseTracker.getInstance().pushCause(damageSource);
}
final Cause currentCause = isMainthread ? PhaseTracker.getInstance().currentCause() : Cause.of(EventContext.empty(), damageSource);
final AttackEntityEvent event = SpongeEventFactory.createAttackEntityEvent(currentCause, (org.spongepowered.api.entity.Entity) targetEntity, originalFunctions, knockbackModifier, originalBaseDamage);
SpongeCommon.post(event);
if (isMainthread) {
PhaseTracker.getInstance().popCause();
}
if (event.isCancelled()) {
return;
}
damage = (float) event.finalOutputDamage();
// Sponge End
// Sponge Start - need final for later events
final double attackDamage = damage;
knockbackModifier = (int) event.knockbackModifier();
enchantmentDamage = (float) enchantmentModifiers.stream().mapToDouble(event::outputDamage).sum();
// Sponge End
float targetOriginalHealth = 0.0F;
boolean litEntityOnFire = false;
final int fireAspectModifier = EnchantmentHelper.getFireAspect((net.minecraft.world.entity.player.Player) (Object) this);
if (targetEntity instanceof LivingEntity) {
targetOriginalHealth = ((LivingEntity) targetEntity).getHealth();
if (fireAspectModifier > 0 && !targetEntity.isOnFire()) {
litEntityOnFire = true;
targetEntity.setSecondsOnFire(1);
}
}
final net.minecraft.world.phys.Vec3 targetMotion = targetEntity.getDeltaMovement();
final boolean attackSucceeded = targetEntity.hurt(DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this), damage);
if (attackSucceeded) {
if (knockbackModifier > 0) {
if (targetEntity instanceof LivingEntity) {
((LivingEntity) targetEntity).knockback((float) knockbackModifier * 0.5F, (double) Mth.sin(this.yRot * 0.017453292F), (double) (-Mth.cos(this.yRot * 0.017453292F)));
} else {
targetEntity.push((double) (-Mth.sin(this.yRot * 0.017453292F) * (float) knockbackModifier * 0.5F), 0.1D, (double) (Mth.cos(this.yRot * 0.017453292F) * (float) knockbackModifier * 0.5F));
}
this.shadow$setDeltaMovement(this.shadow$getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
this.shadow$setSprinting(false);
}
if (isSweapingAttack) {
for (final LivingEntity livingEntity : this.level.getEntitiesOfClass(LivingEntity.class, targetEntity.getBoundingBox().inflate(1.0D, 0.25D, 1.0D))) {
if (livingEntity != (net.minecraft.world.entity.player.Player) (Object) this && livingEntity != targetEntity && !this.shadow$isAlliedTo(livingEntity) && (!(livingEntity instanceof ArmorStand) || !((ArmorStand) livingEntity).isMarker()) && this.shadow$distanceToSqr(livingEntity) < 9.0D) {
// Sponge Start - Do a small event for these entities
// livingEntity.knockBack(this, 0.4F, (double)MathHelper.sin(this.rotationYaw * 0.017453292F), (double)(-MathHelper.cos(this.rotationYaw * 0.017453292F)));
// livingEntity.attackEntityFrom(DamageSource.causePlayerDamage(this), 1.0F);
final EntityDamageSource sweepingAttackSource = EntityDamageSource.builder().entity((org.spongepowered.api.entity.living.player.Player) this).type(DamageTypes.SWEEPING_ATTACK).build();
try (final CauseStackManager.StackFrame frame = isMainthread ? PhaseTracker.getInstance().pushCauseFrame() : null) {
if (isMainthread) {
frame.pushCause(sweepingAttackSource);
}
final ItemStackSnapshot heldSnapshot = ItemStackUtil.snapshotOf(heldItem);
if (isMainthread) {
frame.addContext(EventContextKeys.WEAPON, heldSnapshot);
}
final DamageFunction sweapingFunction = DamageFunction.of(DamageModifier.builder().cause(Cause.of(EventContext.empty(), heldSnapshot)).item(heldSnapshot).type(DamageModifierTypes.SWEEPING).build(), incoming -> EnchantmentHelper.getSweepingDamageRatio((net.minecraft.world.entity.player.Player) (Object) this) * attackDamage);
final List<DamageFunction> sweapingFunctions = new ArrayList<>();
sweapingFunctions.add(sweapingFunction);
final AttackEntityEvent sweepingAttackEvent = SpongeEventFactory.createAttackEntityEvent(currentCause, (org.spongepowered.api.entity.Entity) livingEntity, sweapingFunctions, 1, 1.0D);
SpongeCommon.post(sweepingAttackEvent);
if (!sweepingAttackEvent.isCancelled()) {
livingEntity.knockback(sweepingAttackEvent.knockbackModifier() * 0.4F, (double) Mth.sin(this.yRot * ((float) Math.PI / 180F)), (double) -Mth.cos(this.yRot * ((float) Math.PI / 180F)));
livingEntity.hurt(DamageSource.playerAttack((net.minecraft.world.entity.player.Player) (Object) this), (float) sweepingAttackEvent.finalOutputDamage());
}
}
// Sponge End
}
}
if (this.bridge$vanishState().createsSounds()) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
this.shadow$sweepAttack();
}
if (targetEntity instanceof ServerPlayer && targetEntity.hurtMarked) {
((ServerPlayer) targetEntity).connection.send(new ClientboundSetEntityMotionPacket(targetEntity));
targetEntity.hurtMarked = false;
targetEntity.setDeltaMovement(targetMotion);
}
if (isCriticalAttack) {
if (this.bridge$vanishState().createsSounds()) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
this.shadow$crit(targetEntity);
}
if (!isCriticalAttack && !isSweapingAttack && this.bridge$vanishState().createsSounds()) {
if (isStrongAttack) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.shadow$getSoundSource(), 1.0F, 1.0F);
} else {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
}
if (enchantmentDamage > 0.0F) {
this.shadow$magicCrit(targetEntity);
}
this.shadow$setLastHurtMob(targetEntity);
if (targetEntity instanceof LivingEntity) {
EnchantmentHelper.doPostHurtEffects((LivingEntity) targetEntity, (net.minecraft.world.entity.player.Player) (Object) this);
}
EnchantmentHelper.doPostDamageEffects((net.minecraft.world.entity.player.Player) (Object) this, targetEntity);
final ItemStack itemstack1 = this.shadow$getMainHandItem();
Entity entity = targetEntity;
// Sponge - Forge compatibility for multi-part entities
entity = PlatformHooks.INSTANCE.getEntityHooks().getParentPart(entity);
if (!this.level.isClientSide && !itemstack1.isEmpty() && entity instanceof LivingEntity) {
itemstack1.hurtEnemy((LivingEntity) entity, (net.minecraft.world.entity.player.Player) (Object) this);
if (itemstack1.isEmpty()) {
// Sponge - platform hook for forge
PlatformHooks.INSTANCE.getEventHooks().callItemDestroyedEvent((net.minecraft.world.entity.player.Player) (Object) this, itemstack1, InteractionHand.MAIN_HAND);
this.shadow$setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY);
}
// Sponge Start
final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext();
final TransactionalCaptureSupplier transactor = context.getTransactor();
transactor.logPlayerInventoryChange((net.minecraft.world.entity.player.Player) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD);
// capture
this.inventoryMenu.broadcastChanges();
// Spong End
}
if (targetEntity instanceof LivingEntity) {
final float f5 = targetOriginalHealth - ((LivingEntity) targetEntity).getHealth();
this.shadow$awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F));
if (fireAspectModifier > 0) {
targetEntity.setSecondsOnFire(fireAspectModifier * 4);
}
if (this.level instanceof ServerWorld && f5 > 2.0F) {
final int k = (int) ((double) f5 * 0.5D);
((net.minecraft.server.level.ServerLevel) this.level).sendParticles(ParticleTypes.DAMAGE_INDICATOR, targetEntity.getX(), targetEntity.getY() + (double) (targetEntity.getBbHeight() * 0.5F), targetEntity.getZ(), k, 0.1D, 0.0D, 0.1D, 0.2D);
}
}
this.shadow$causeFoodExhaustion(0.1F);
} else {
if (this.bridge$vanishState().createsSounds()) {
this.level.playSound(null, this.shadow$getX(), this.shadow$getY(), this.shadow$getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.shadow$getSoundSource(), 1.0F, 1.0F);
}
if (litEntityOnFire) {
targetEntity.clearFire();
}
}
}
}
}
}
use of net.minecraft.world.entity.LivingEntity in project SpongeCommon by SpongePowered.
the class LivingEntityMixin_Attack_impl method hurt.
// @formatter:on
/**
* @author bloodmc - November 22, 2015
* @author gabizou - Updated April 11th, 2016 - Update for 1.9 changes
* @author Aaron1011 - Updated Nov 11th, 2016 - Update for 1.11 changes
* @author gabizou - Updated Nov 15th, 2020 - Update for 1.15 changes
* @author gabizou - Updated Jan 26th, 2022 - Update for 1.16.5 changes
* @reason Reroute damageEntity calls to our hook in order to prevent damage.
*/
@Overwrite
public boolean hurt(final DamageSource source, final float amount) {
// Sponge start - Add certain hooks for necessities
this.lastDamageSource = source;
if (source == null) {
new PrettyPrinter(60).centre().add("Null DamageSource").hr().addWrapped("Sponge has found a null damage source! This should NEVER happen " + "as the DamageSource is used for all sorts of calculations. Usually" + " this can be considered developer error. Please report the following" + " stacktrace to the most appropriate mod/plugin available.").add().add(new IllegalArgumentException("Null DamageSource")).log(SpongeCommon.logger(), Level.WARN);
return false;
}
// Sponge - This hook is for forge use mainly
if (!this.bridge$onLivingAttack((LivingEntity) (Object) this, source, amount)) {
return false;
}
// Sponge end
if (this.shadow$isInvulnerableTo(source)) {
return false;
} else if (this.level.isClientSide) {
return false;
// Sponge - Also ignore our customary damage source
} else if (this.shadow$isDeadOrDying() && source != SpongeDamageSources.IGNORED) {
return false;
} else if (source.isFire() && this.shadow$hasEffect(MobEffects.FIRE_RESISTANCE)) {
return false;
} else {
if (this.shadow$isSleeping() && !this.level.isClientSide) {
this.shadow$stopSleeping();
}
this.noActionTime = 0;
final float f = amount;
// Sponge - ignore as this is handled in our damageEntityHook
// if ((source == DamageSource.ANVIL || source == DamageSource.FALLING_BLOCK) && !this.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty())
// {
// this.getItemStackFromSlot(EquipmentSlotType.HEAD).damageItem((int)(amount * 4.0F + this.rand.nextFloat() * amount * 2.0F), this, (p_213341_0_) -> {
// p_213341_0_.sendBreakAnimation(EquipmentSlotType.HEAD);
// });
// amount *= 0.75F;
// }
// Sponge End
// Sponge - set the 'shield blocking ran' flag to the proper value, since
// we comment out the logic below
float f1 = 0.0F;
final boolean flag = amount > 0.0F && this.shadow$isDamageSourceBlocked(source);
// but we need to account for the amount later.
if (flag) {
f1 = amount;
}
// boolean flag = false;
//
// if (amount > 0.0F && this.shadow$canBlockDamageSource(source))
// {
// this.damageShield(amount);
// amount = 0.0F;
//
// if (!source.isProjectile())
// {
// Entity entity = source.getImmediateSource();
//
// if (entity instanceof EntityLivingBase)
// {
// this.blockUsingShield((EntityLivingBase)entity);
// }
// }
//
// flag = true;
// }
// Sponge end
this.animationSpeed = 1.5F;
boolean flag1 = true;
if ((float) this.invulnerableTime > 10.0F) {
if (amount <= this.lastHurt) {
// Technically, this is wrong since 'amount' won't be 0 if a shield is used. However, we need bridge$damageEntityHook so that we process the shield, so we leave it as-is
return false;
}
// damageEntity method, which would re-run our bridge$damageEntityHook.
if (((EntityTypeBridge) this.shadow$getType()).bridge$overridesDamageEntity()) {
this.shadow$actuallyHurt(source, amount - this.lastHurt);
} else {
if (!this.bridge$damageEntity(source, amount - this.lastHurt)) {
return false;
}
}
// this.damageEntity(source, amount - this.lastHurt); // handled above
// Sponge end
this.lastHurt = amount;
flag1 = false;
} else {
// Sponge start - reroute to our damage hook
if (((EntityTypeBridge) this.shadow$getType()).bridge$overridesDamageEntity()) {
this.shadow$actuallyHurt(source, amount);
} else {
if (!this.bridge$damageEntity(source, amount)) {
return false;
}
}
this.lastHurt = amount;
this.invulnerableTime = 20;
// this.damageEntity(source, amount); // handled above
// Sponge end
this.hurtDuration = 10;
this.hurtTime = this.hurtDuration;
}
this.hurtDir = 0.0F;
final Entity entity = source.getEntity();
if (entity != null) {
if (entity instanceof LivingEntity) {
this.shadow$setLastHurtByMob((LivingEntity) entity);
}
if (entity instanceof Player) {
this.lastHurtByPlayerTime = 100;
this.lastHurtByPlayer = (Player) entity;
// Forge Start - use TameableEntity instead of WolfEntity
// } else if (entity1 instanceof WolfEntity) {
// WolfEntity wolfentity = (WolfEntity)entity1;
} else if (entity instanceof TamableAnimal) {
final TamableAnimal wolfentity = (TamableAnimal) entity;
if (wolfentity.isTame()) {
this.lastHurtByPlayerTime = 100;
final LivingEntity livingentity = wolfentity.getOwner();
if (livingentity != null && livingentity.getType() == EntityType.PLAYER) {
this.lastHurtByPlayer = (Player) livingentity;
} else {
this.lastHurtByPlayer = null;
}
}
}
}
if (flag1) {
if (flag) {
this.level.broadcastEntityEvent((LivingEntity) (Object) this, (byte) 29);
} else if (source instanceof EntityDamageSource && ((EntityDamageSource) source).isThorns()) {
this.level.broadcastEntityEvent((LivingEntity) (Object) this, (byte) 33);
} else {
final byte b0;
if (source == DamageSource.DROWN) {
b0 = 36;
} else if (source.isFire()) {
b0 = 37;
} else if (source == DamageSource.SWEET_BERRY_BUSH) {
b0 = 44;
} else {
b0 = 2;
}
this.level.broadcastEntityEvent((LivingEntity) (Object) this, b0);
}
if (source != DamageSource.DROWN && !flag) {
// Sponge - remove 'amount > 0.0F' - it's redundant in Vanilla, and breaks our handling of shields
this.shadow$markHurt();
}
if (entity != null) {
double d1 = entity.getX() - this.shadow$getX();
double d0;
for (d0 = entity.getZ() - this.shadow$getZ(); d1 * d1 + d0 * d0 < 1.0E-4D; d0 = (Math.random() - Math.random()) * 0.01D) {
d1 = (Math.random() - Math.random()) * 0.01D;
}
this.hurtDir = (float) (Mth.atan2(d0, d1) * 57.2957763671875D - (double) this.yRot);
this.shadow$knockback(0.4F, d1, d0);
} else {
this.hurtDir = (float) (Math.random() * 2.0D * 180);
}
}
if (this.shadow$isDeadOrDying()) {
if (!this.shadow$checkTotemDeathProtection(source)) {
final SoundEvent soundevent = this.shadow$getDeathSound();
// Sponge - Check that we're not vanished
if (this.bridge$vanishState().createsSounds() && flag1 && soundevent != null) {
this.shadow$playSound(soundevent, this.shadow$getSoundVolume(), this.shadow$getVoicePitch());
}
// Sponge tracker will redirect this call
this.shadow$die(source);
}
} else if (flag1) {
// Sponge - Check if we're vanished
if (this.bridge$vanishState().createsSounds()) {
this.shadow$playHurtSound(source);
}
}
// Sponge - remove 'amount > 0.0F' since it's handled in the event
final boolean flag2 = !flag;
if (flag2) {
this.lastDamageSource = source;
this.lastDamageStamp = this.level.getGameTime();
}
if ((LivingEntity) (Object) this instanceof net.minecraft.server.level.ServerPlayer) {
CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((net.minecraft.server.level.ServerPlayer) (Object) this, source, f, amount, flag);
if (f1 > 0.0F && f1 < 3.4028235E37F) {
((net.minecraft.server.level.ServerPlayer) (Object) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f1 * 10.0F));
}
}
if (entity instanceof net.minecraft.server.level.ServerPlayer) {
CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((net.minecraft.server.level.ServerPlayer) entity, (Entity) (Object) this, source, f, amount, flag);
}
return flag2;
}
}
use of net.minecraft.world.entity.LivingEntity in project MinecraftForge by MinecraftForge.
the class GravityAttributeTest method worldTick.
@SubscribeEvent
public void worldTick(TickEvent.WorldTickEvent event) {
if (!event.world.isClientSide) {
if (ticks++ > 60) {
ticks = 0;
Level w = event.world;
List<LivingEntity> list;
if (w.isClientSide) {
ClientLevel cw = (ClientLevel) w;
list = new ArrayList<>(100);
for (Entity e : cw.entitiesForRendering()) {
if (e.isAlive() && e instanceof LivingEntity)
list.add((LivingEntity) e);
}
} else {
ServerLevel sw = (ServerLevel) w;
Stream<LivingEntity> s = StreamSupport.stream(sw.getEntities().getAll().spliterator(), false).filter(Entity::isAlive).filter(e -> e instanceof LivingEntity).map(e -> (LivingEntity) e);
list = s.collect(Collectors.toList());
}
for (LivingEntity liv : list) {
AttributeInstance grav = liv.getAttribute(ForgeMod.ENTITY_GRAVITY.get());
boolean inPlains = liv.level.getBiome(liv.blockPosition()).getBiomeCategory() == BiomeCategory.PLAINS;
if (inPlains && !grav.hasModifier(REDUCED_GRAVITY)) {
logger.info("Granted low gravity to Entity: {}", liv);
grav.addTransientModifier(REDUCED_GRAVITY);
} else if (!inPlains && grav.hasModifier(REDUCED_GRAVITY)) {
logger.info("Removed low gravity from Entity: {}", liv);
grav.removeModifier(REDUCED_GRAVITY);
}
}
}
}
}
Aggregations