Implement BlocksAttack DamageReduction and ItemDamage (#12538)

This commit is contained in:
Pedro
2025-05-18 10:31:34 -04:00
committed by GitHub
parent 28d7df75ac
commit f1dbed072c
10 changed files with 448 additions and 28 deletions

View File

@@ -1,6 +1,8 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.datacomponent.item.blocksattacks.DamageReduction;
import io.papermc.paper.datacomponent.item.blocksattacks.ItemDamageFunction;
import io.papermc.paper.registry.tag.TagKey;
import net.kyori.adventure.key.Key;
import org.bukkit.damage.DamageType;
@@ -8,8 +10,13 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.List;
// TODO
/**
* Holds block attacks to the holding player like Shield.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
@@ -20,19 +27,59 @@ public interface BlocksAttacks {
return ItemComponentTypesBridge.bridge().blocksAttacks();
}
/**
* Gets the amount of time (in seconds) that use must be held before successfully blocking attacks.
*
* @return the delay in seconds
*/
float blockDelaySeconds();
/**
* Gets the multiplier applied to the cooldown time for the item when attacked by a disabling attack (the multiplier for {@link Weapon#disableBlockingForSeconds()}).
* <br>
* If set to 0, this item can never be disabled by attacks.
*
* @return the multiplier for the cooldown time
*/
float disableCooldownScale();
//List<DamageReduction> damageReductions();
/**
* Gets a list of {@link DamageReduction} of how much damage should be blocked in a given attack.
*
* @return a list of damage reductions
*/
List<DamageReduction> damageReductions();
//ItemDamageFunction itemDamage();
/**
* Gets how much damage should be applied to the item from a given attack.
*
* @return the damage function
*/
ItemDamageFunction itemDamage();
@Nullable TagKey<DamageType> bypassedBy();
/**
* Gets the DamageType that can bypass the blocking.
*
* @return a damage type tag key, or null if there is no such tag key
*/
@Nullable
TagKey<DamageType> bypassedBy();
@Nullable Key blockSound();
/**
* Gets the key sound to play when an attack is successfully blocked.
*
* @return a key of the sound
*/
@Nullable
Key blockSound();
@Nullable Key disableSound();
/**
* Gets the key sound to play when the item goes on its disabled cooldown due to an attack.
*
* @return a key of the sound
*/
@Nullable
Key disableSound();
/**
* Builder for {@link BlocksAttacks}.
@@ -47,14 +94,14 @@ public interface BlocksAttacks {
@Contract(value = "_ -> this", mutates = "this")
Builder disableCooldownScale(float scale);
//@Contract(value = "_ -> this", mutates = "this")
//Builder addDamageReduction(DamageReduction reduction);
@Contract(value = "_ -> this", mutates = "this")
Builder addDamageReduction(DamageReduction reduction);
//@Contract(value = "_ -> this", mutates = "this")
//Builder damageReductions(List<DamageReduction> reductions);
@Contract(value = "_ -> this", mutates = "this")
Builder damageReductions(List<DamageReduction> reductions);
//@Contract(value = "_ -> this", mutates = "this")
//Builder itemDamage(ItemDamageFunction function);
@Contract(value = "_ -> this", mutates = "this")
Builder itemDamage(ItemDamageFunction function);
@Contract(value = "_ -> this", mutates = "this")
Builder bypassedBy(@Nullable TagKey<DamageType> bypassedBy);

View File

@@ -0,0 +1,21 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import java.util.Optional;
import java.util.ServiceLoader;
@NullMarked
@ApiStatus.Internal
interface BlocksAttacksBridge {
Optional<BlocksAttacksBridge> BRIDGE = ServiceLoader.load(BlocksAttacksBridge.class).findFirst();
static BlocksAttacksBridge bridge() {
return BRIDGE.orElseThrow();
}
DamageReduction.Builder blocksAttacksDamageReduction();
ItemDamageFunction.Builder blocksAttacksItemDamageFunction();
}

View File

@@ -0,0 +1,78 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.registry.set.RegistryKeySet;
import org.bukkit.damage.DamageType;
import org.checkerframework.checker.index.qual.Positive;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Hold how much damage should be blocked in a given attack.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS
* @see io.papermc.paper.datacomponent.item.BlocksAttacks#damageReductions()
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface DamageReduction {
@Contract(value = "-> new", pure = true)
static DamageReduction.Builder damageReduction() {
return BlocksAttacksBridge.bridge().blocksAttacksDamageReduction();
}
/**
* The damage types to block.
*
* @return the set of damage type
*/
@Nullable
RegistryKeySet<DamageType> type();
/**
* Get the maximum angle between the users facing direction and the direction of the incoming attack to be blocked.
*
* @return the angle
*/
@Positive
float horizontalBlockingAngle();
/**
* Get the constant amount of damage to be blocked.
*
* @return the base
*/
float base();
/**
* Get the fraction of the dealt damage to be blocked.
*
* @return the factor
*/
float factor();
/**
* Builder for {@link DamageReduction}.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<DamageReduction> {
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder type(RegistryKeySet<DamageType> type);
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder horizontalBlockingAngle(@Positive float horizontalBlockingAngle);
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder base(float base);
@Contract(value = "_ -> this", mutates = "this")
DamageReduction.Builder factor(float factor);
}
}

View File

@@ -0,0 +1,71 @@
package io.papermc.paper.datacomponent.item.blocksattacks;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import org.checkerframework.checker.index.qual.NonNegative;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
/**
* Hold how much damage should be applied to the item from a given attack.
*
* @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS
* @see io.papermc.paper.datacomponent.item.BlocksAttacks#itemDamage()
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface ItemDamageFunction {
@Contract(value = "-> new", pure = true)
static ItemDamageFunction.Builder itemDamageFunction() {
return BlocksAttacksBridge.bridge().blocksAttacksItemDamageFunction();
}
/**
* Get the minimum amount of damage dealt by the attack before item damage is applied to the item.
*
* @return the threshold
*/
@NonNegative
float threshold();
/**
* Get the constant amount of damage applied to the item, if threshold is passed.
*
* @return the base
*/
float base();
/**
* Get the fraction of the dealt damage that should be applied to the item, if threshold is passed.
*
* @return the base
*/
float factor();
/**
* Get the damage to apply for the item.
*
* @apiNote this doesn't apply enchantments like {@link org.bukkit.enchantments.Enchantment#UNBREAKING}}
* @return the damage to apply
*/
int damageToApply(float damage);
/**
* Builder for {@link ItemDamageFunction}.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends DataComponentBuilder<ItemDamageFunction> {
@Contract(value = "_ -> this", mutates = "this")
ItemDamageFunction.Builder threshold(@NonNegative final float threshold);
@Contract(value = "_ -> this", mutates = "this")
ItemDamageFunction.Builder base(final float base);
@Contract(value = "_ -> this", mutates = "this")
ItemDamageFunction.Builder factor(final float factor);
}
}