Add combat tracker API (#11853)
This commit is contained in:
@ -1,10 +1,15 @@
|
||||
package io.papermc.paper;
|
||||
|
||||
import io.papermc.paper.world.damagesource.CombatEntry;
|
||||
import io.papermc.paper.world.damagesource.FallLocationType;
|
||||
import net.kyori.adventure.util.Services;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.damage.DamageEffect;
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Static bridge to the server internals.
|
||||
@ -45,5 +50,28 @@ public interface InternalAPIBridge {
|
||||
@Deprecated(forRemoval = true, since = "1.21.5")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "1.22")
|
||||
Biome constructLegacyCustomBiome();
|
||||
|
||||
/**
|
||||
* Creates a new combat entry.
|
||||
* <p>
|
||||
* The fall location and fall distance will be calculated from the entity's current state.
|
||||
*
|
||||
* @param entity entity
|
||||
* @param damageSource damage source
|
||||
* @param damage damage amount
|
||||
* @return new combat entry
|
||||
*/
|
||||
CombatEntry createCombatEntry(LivingEntity entity, DamageSource damageSource, float damage);
|
||||
|
||||
/**
|
||||
* Creates a new combat entry
|
||||
*
|
||||
* @param damageSource damage source
|
||||
* @param damage damage amount
|
||||
* @param fallLocationType fall location type
|
||||
* @param fallDistance fall distance
|
||||
* @return combat entry
|
||||
*/
|
||||
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
package io.papermc.paper.world.damagesource;
|
||||
|
||||
import io.papermc.paper.InternalAPIBridge;
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a combat entry
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.Experimental
|
||||
@ApiStatus.NonExtendable
|
||||
public interface CombatEntry {
|
||||
|
||||
/**
|
||||
* Gets the damage source.
|
||||
*
|
||||
* @return the damage source
|
||||
*/
|
||||
DamageSource getDamageSource();
|
||||
|
||||
/**
|
||||
* Gets the amount of damage caused.
|
||||
*
|
||||
* @return the amount of damage caused
|
||||
*/
|
||||
float getDamage();
|
||||
|
||||
/**
|
||||
* Gets the fall location type at the time of this damage.
|
||||
*
|
||||
* @return the fall location type
|
||||
*/
|
||||
@Nullable FallLocationType getFallLocationType();
|
||||
|
||||
/**
|
||||
* Gets the fall distance at the time of this damage.
|
||||
*
|
||||
* @return the fall distance
|
||||
*/
|
||||
float getFallDistance();
|
||||
|
||||
/**
|
||||
* Creates a new combat entry.
|
||||
* <p>
|
||||
* The fall location and fall distance will be calculated from the entity's current state.
|
||||
*
|
||||
* @param entity entity
|
||||
* @param damageSource damage source
|
||||
* @param damage damage amount
|
||||
* @return combat entry
|
||||
* @see #combatEntry(DamageSource, float, FallLocationType, float)
|
||||
*/
|
||||
static CombatEntry combatEntry(final LivingEntity entity, final DamageSource damageSource, final float damage) {
|
||||
return InternalAPIBridge.get().createCombatEntry(entity, damageSource, damage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new combat entry
|
||||
*
|
||||
* @param damageSource damage source
|
||||
* @param damage damage amount
|
||||
* @param fallLocationType fall location type
|
||||
* @param fallDistance fall distance
|
||||
* @return a new combat entry
|
||||
* @see CombatTracker#calculateFallLocationType()
|
||||
* @see Entity#getFallDistance()
|
||||
*/
|
||||
static CombatEntry combatEntry(
|
||||
final DamageSource damageSource,
|
||||
final float damage,
|
||||
@Nullable final FallLocationType fallLocationType,
|
||||
final float fallDistance
|
||||
) {
|
||||
return InternalAPIBridge.get().createCombatEntry(damageSource, damage, fallLocationType, fallDistance);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
package io.papermc.paper.world.damagesource;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents entity's combat tracker
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.Experimental
|
||||
@ApiStatus.NonExtendable
|
||||
public interface CombatTracker {
|
||||
|
||||
/**
|
||||
* Gets the entity behind this combat tracker.
|
||||
*
|
||||
* @return the entity behind this combat tracker
|
||||
*/
|
||||
LivingEntity getEntity();
|
||||
|
||||
/**
|
||||
* Gets the list of recorded combat entries.
|
||||
* <p>
|
||||
* The returned list is a copy, so any modifications
|
||||
* to its contents won't affect this entity's
|
||||
* combat history.
|
||||
*
|
||||
* @return the list of combat entries
|
||||
* @see #setCombatEntries(List)
|
||||
*/
|
||||
List<CombatEntry> getCombatEntries();
|
||||
|
||||
/**
|
||||
* Sets the entity's combat history.
|
||||
* <p>
|
||||
* Note that overriding the entity's combat history won't
|
||||
* affect the entity's current or new combat state.
|
||||
* Reset the current combat state and register new combat entries instead
|
||||
* if you want the new history to affect the combat state.
|
||||
*
|
||||
* @param combatEntries combat entries
|
||||
* @see #resetCombatState()
|
||||
* @see #addCombatEntry(CombatEntry)
|
||||
*/
|
||||
void setCombatEntries(List<CombatEntry> combatEntries);
|
||||
|
||||
/**
|
||||
* Calculates the most significant fall damage entry.
|
||||
*
|
||||
* @return the most significant fall damage entry
|
||||
*/
|
||||
@Nullable CombatEntry computeMostSignificantFall();
|
||||
|
||||
/**
|
||||
* Checks whether the entity is in combat,
|
||||
* i.e. has taken damage from an entity
|
||||
* since the combat tracking has begun.
|
||||
*
|
||||
* @return whether the entity is in combat
|
||||
*/
|
||||
boolean isInCombat();
|
||||
|
||||
/**
|
||||
* Checks whether the entity has started recording damage,
|
||||
* i.e. its combat tracking is active.
|
||||
*
|
||||
* @return whether the entity has started recording damage
|
||||
*/
|
||||
boolean isTakingDamage();
|
||||
|
||||
/**
|
||||
* Gets the last or current combat duration.
|
||||
*
|
||||
* @return the combat duration
|
||||
* @see #isInCombat()
|
||||
*/
|
||||
int getCombatDuration();
|
||||
|
||||
/**
|
||||
* Adds a new entry the pool of combat entries,
|
||||
* updating the entity's combat state.
|
||||
*
|
||||
* @param combatEntry combat entry
|
||||
*/
|
||||
void addCombatEntry(CombatEntry combatEntry);
|
||||
|
||||
/**
|
||||
* Constructs a death message based on the current combat history.
|
||||
*
|
||||
* @return a death message
|
||||
*/
|
||||
Component getDeathMessage();
|
||||
|
||||
/**
|
||||
* Resets entity's combat state, clearing combat history.
|
||||
*/
|
||||
void resetCombatState();
|
||||
|
||||
/**
|
||||
* Calculates the fall location type from the current entity's location.
|
||||
*
|
||||
* @return the fall location type
|
||||
*/
|
||||
@Nullable FallLocationType calculateFallLocationType();
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package io.papermc.paper.world.damagesource;
|
||||
|
||||
import net.kyori.adventure.translation.Translatable;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Represents a type of location from which the entity fell.
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.Experimental
|
||||
public sealed interface FallLocationType extends Translatable permits FallLocationTypeImpl {
|
||||
|
||||
/**
|
||||
* Gets the fall location id.
|
||||
*
|
||||
* @return the fall location id
|
||||
*/
|
||||
String id();
|
||||
|
||||
/**
|
||||
* Gets the translation key used for a fall death message
|
||||
* caused by falling from this location
|
||||
*
|
||||
* @return the translation key
|
||||
*/
|
||||
@Override
|
||||
String translationKey();
|
||||
|
||||
/**
|
||||
* The entity was not within a special fall location.
|
||||
*/
|
||||
FallLocationType GENERIC = new FallLocationTypeImpl("generic");
|
||||
/**
|
||||
* The entity was within the ladder.
|
||||
*/
|
||||
FallLocationType LADDER = new FallLocationTypeImpl("ladder");
|
||||
/**
|
||||
* The entity was in vines.
|
||||
*/
|
||||
FallLocationType VINES = new FallLocationTypeImpl("vines");
|
||||
/**
|
||||
* The entity was in weeping wines.
|
||||
*/
|
||||
FallLocationType WEEPING_VINES = new FallLocationTypeImpl("weeping_vines");
|
||||
/**
|
||||
* The entity was in twisting vines.
|
||||
*/
|
||||
FallLocationType TWISTING_VINES = new FallLocationTypeImpl("twisting_vines");
|
||||
/**
|
||||
* The entity was in scaffolding.
|
||||
*/
|
||||
FallLocationType SCAFFOLDING = new FallLocationTypeImpl("scaffolding");
|
||||
/**
|
||||
* The entity was within some other climbable block.
|
||||
*/
|
||||
FallLocationType OTHER_CLIMBABLE = new FallLocationTypeImpl("other_climbable");
|
||||
/**
|
||||
* The entity was in water.
|
||||
*/
|
||||
FallLocationType WATER = new FallLocationTypeImpl("water");
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package io.papermc.paper.world.damagesource;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
record FallLocationTypeImpl(String id) implements FallLocationType {
|
||||
|
||||
@Override
|
||||
public String translationKey() {
|
||||
// Same as net.minecraft.world.damagesource.FallLocation#languageKey
|
||||
return "death.fell.accident." + this.id;
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,6 +4,8 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import io.papermc.paper.world.damagesource.CombatTracker;
|
||||
import io.papermc.paper.world.damagesource.FallLocationType;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -21,6 +23,7 @@ import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -1452,4 +1455,12 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
|
||||
*/
|
||||
boolean canUseEquipmentSlot(org.bukkit.inventory.@NotNull EquipmentSlot slot);
|
||||
// Paper end - Expose canUseSlot
|
||||
|
||||
/**
|
||||
* Gets the entity's combat tracker
|
||||
*
|
||||
* @return the entity's combat tracker
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
@NotNull CombatTracker getCombatTracker();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user