After Damage Event (#4051)

* after damage event

* add after damage event to testmod

* remove amount > 0 check to capture shield blocking

* add javadoc

* dont fire event if killed

* clarify javadoc a bit more

* fix checkstyle issue

* fix other checkstyle issues lol

* rename damageDealt to baseDamageTaken

(cherry picked from commit 2122d828f0)
This commit is contained in:
TheDeathlyCow 2024-08-26 23:02:20 +12:00 committed by modmuss50
parent ca1fb63b82
commit 6cca2bef65
3 changed files with 43 additions and 0 deletions

View file

@ -42,6 +42,22 @@ public final class ServerLivingEntityEvents {
return true;
});
/**
* An event that is called after an entity is damaged. This is fired from {@link LivingEntity#damage} after damage
* is applied, or after that damage was blocked by a shield.
*
* <p>The base damage taken is the damage initially applied to the entity. Damage taken is the amount of damage the
* entity actually took, after effects such as shields and extra freezing damage are applied. Damage taken does NOT
* include damage reduction from armor and enchantments.
*
* <p>This event is not fired if the entity was killed by the damage.
*/
public static final Event<AfterDamage> AFTER_DAMAGE = EventFactory.createArrayBacked(AfterDamage.class, callbacks -> (entity, source, baseDamageTaken, damageTaken, blocked) -> {
for (AfterDamage callback : callbacks) {
callback.afterDamage(entity, source, baseDamageTaken, damageTaken, blocked);
}
});
/**
* An event that is called when an entity takes fatal damage.
*
@ -104,6 +120,21 @@ public final class ServerLivingEntityEvents {
boolean allowDamage(LivingEntity entity, DamageSource source, float amount);
}
@FunctionalInterface
public interface AfterDamage {
/**
* Called after a living entity took damage, unless they were killed. The base damage taken is given as damage
* taken before armor or enchantments are applied, but after other effects like shields are applied.
*
* @param entity the entity that was damaged
* @param source the source of the damage
* @param baseDamageTaken the amount of damage initially dealt
* @param damageTaken the amount of damage actually taken by the entity, before armor and enchantment effects
* @param blocked whether the damage was blocked by a shield
*/
void afterDamage(LivingEntity entity, DamageSource source, float baseDamageTaken, float damageTaken, boolean blocked);
}
@FunctionalInterface
public interface AllowDeath {
/**

View file

@ -30,6 +30,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.block.BedBlock;
import net.minecraft.block.BlockState;
@ -83,6 +84,13 @@ abstract class LivingEntityMixin {
}
}
@Inject(method = "damage", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
private void afterDamage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir, float dealt, boolean blocked) {
if (!isDead()) {
ServerLivingEntityEvents.AFTER_DAMAGE.invoker().afterDamage((LivingEntity) (Object) this, source, dealt, amount, blocked);
}
}
@Inject(method = "sleep", at = @At("RETURN"))
private void onSleep(BlockPos pos, CallbackInfo info) {
EntitySleepEvents.START_SLEEPING.invoker().onStartSleeping((LivingEntity) (Object) this, pos);

View file

@ -90,6 +90,10 @@ public final class EntityEventTests implements ModInitializer {
return true;
});
ServerLivingEntityEvents.AFTER_DAMAGE.register((entity, source, baseDamageTaken, damageTaken, blocked) -> {
LOGGER.info("Entity {} received {} damage from {} (initially dealt {}, blocked {})", entity.getName().getString(), damageTaken, source.getName(), baseDamageTaken, blocked);
});
ServerLivingEntityEvents.ALLOW_DEATH.register((entity, source, amount) -> {
LOGGER.info("{} is going to die to {} damage from {} damage source", entity.getName().getString(), amount, source.getName());