From e5b3b72c83bb34a57ccdb305c486b483a0ee63dd Mon Sep 17 00:00:00 2001 From: Chaosdave34 Date: Mon, 23 Dec 2024 13:08:23 +0100 Subject: [PATCH] Add DamageType registry event --- .../data/DamageTypeRegistryEntry.java | 112 ++++++++++++++++ .../paper/registry/event/RegistryEvents.java | 3 + .../main/java/org/bukkit/UnsafeValues.java | 9 ++ .../java/org/bukkit/damage/DamageEffect.java | 19 +-- .../paper/registry/PaperRegistries.java | 3 +- .../data/PaperDamageTypeRegistryEntry.java | 120 ++++++++++++++++++ .../craftbukkit/damage/CraftDamageEffect.java | 6 +- .../craftbukkit/damage/CraftDamageType.java | 25 ++++ .../craftbukkit/util/CraftMagicNumbers.java | 7 + 9 files changed, 292 insertions(+), 12 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/DamageTypeRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperDamageTypeRegistryEntry.java diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/DamageTypeRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/DamageTypeRegistryEntry.java new file mode 100644 index 0000000000..51c27fa7fe --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/DamageTypeRegistryEntry.java @@ -0,0 +1,112 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import org.bukkit.damage.DamageEffect; +import org.bukkit.damage.DamageScaling; +import org.bukkit.damage.DamageType; +import org.bukkit.damage.DeathMessageType; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.Nullable; + +/** + * A data-centric version-specific registry entry for the {@link DamageType} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface DamageTypeRegistryEntry { + + /** + * Provides part of the death message translation key. (death.attack.<message_id>) + *

+ * Note The translation key is only used if + * {@link #deathMessageType()} is {@link DeathMessageType#DEFAULT} + * + * @return part of the translation key + */ + String messageId(); + + /** + * Provides the amount of hunger exhaustion caused by this damage type. + * + * @return the exhaustion + */ + Float exhaustion(); + + /** + * Provides the {@link DamageScaling} for this damage type. + * + * @return the damage scaling + */ + DamageScaling damageScaling(); + + /** + * Provides the {@link DamageEffect} for this damage type. + * + * @return the damage effect + */ + @Nullable + DamageEffect damageEffect(); + + /** + * Provides the {@link DeathMessageType} for this damage type. + * + * @return the death message type + */ + @Nullable + DeathMessageType deathMessageType(); + + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends DamageTypeRegistryEntry, RegistryBuilder { + /** + * Sets part of the death message translation key. + * + * @return this builder instance. + * @see DamageTypeRegistryEntry#messageId() + * @see DamageType#getTranslationKey() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder messageId(String messageId); + + /** + * Sets the amount of hunger exhaustion caused by this damage type. + * + * @return this builder instance. + * @see DamageTypeRegistryEntry#exhaustion() + * @see DamageType#getExhaustion() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder exhaustion(Float exhaustion); + + /** + * Sets the {@link DamageScaling} for this damage type. + * + * @return this builder instance. + * @see DamageTypeRegistryEntry#damageScaling() + * @see DamageType#getDamageScaling() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder damageScaling(DamageScaling scaling); + + /** + * Sets the {@link DamageEffect} for this damage type. + * + * @return this builder instance. + * @see DamageTypeRegistryEntry#damageEffect() + * @see DamageType#getDamageEffect() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder damageEffect(@Nullable DamageEffect effect); + + /** + * Sets the {@link DeathMessageType} for this damage type. + * + * @return this builder instance. + * @see DamageTypeRegistryEntry#deathMessageType() + * @see DamageType#getDeathMessageType() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder deathMessageType(@Nullable DeathMessageType deathMessageType); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java b/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java index 40deffbd09..797226b36e 100644 --- a/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java +++ b/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java @@ -1,11 +1,13 @@ package io.papermc.paper.registry.event; import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import org.bukkit.Art; import org.bukkit.GameEvent; +import org.bukkit.damage.DamageType; import org.bukkit.enchantments.Enchantment; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -23,6 +25,7 @@ public final class RegistryEvents { public static final RegistryEventProvider GAME_EVENT = create(RegistryKey.GAME_EVENT); public static final RegistryEventProvider ENCHANTMENT = create(RegistryKey.ENCHANTMENT); public static final RegistryEventProvider PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT); + public static final RegistryEventProvider DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE); private RegistryEvents() { } diff --git a/paper-api/src/main/java/org/bukkit/UnsafeValues.java b/paper-api/src/main/java/org/bukkit/UnsafeValues.java index d0de7ce3c3..0ea137cbaa 100644 --- a/paper-api/src/main/java/org/bukkit/UnsafeValues.java +++ b/paper-api/src/main/java/org/bukkit/UnsafeValues.java @@ -251,6 +251,15 @@ public interface UnsafeValues { * @throws IllegalArgumentException if the entity does not exist of have default attributes (use {@link #hasDefaultEntityAttributes(NamespacedKey)} first) */ @org.jetbrains.annotations.NotNull org.bukkit.attribute.Attributable getDefaultEntityAttributes(@org.jetbrains.annotations.NotNull NamespacedKey entityKey); + + /** + * Get the {@link Sound} played for this {@link DamageEffect} + * + * @param damageEffect the damageEffect + * @return the sound + */ + @ApiStatus.Internal + Sound getSoundForDamageEffect(@NotNull DamageEffect damageEffect); // Paper end // Paper start - namespaced key biome methods diff --git a/paper-api/src/main/java/org/bukkit/damage/DamageEffect.java b/paper-api/src/main/java/org/bukkit/damage/DamageEffect.java index 8cf8fde602..2c6dd04769 100644 --- a/paper-api/src/main/java/org/bukkit/damage/DamageEffect.java +++ b/paper-api/src/main/java/org/bukkit/damage/DamageEffect.java @@ -11,34 +11,35 @@ import org.jetbrains.annotations.NotNull; * effects only determine the sound that plays. */ @ApiStatus.Experimental -public interface DamageEffect { +public enum DamageEffect { /** * The default damage effect. */ - public static final DamageEffect HURT = getDamageEffect("hurt"); + HURT, /** * Thorns. */ - public static final DamageEffect THORNS = getDamageEffect("thorns"); + THORNS, /** * Drowning. */ - public static final DamageEffect DROWNING = getDamageEffect("drowning"); + DROWNING, /** * A single burn tick (fire, lava, etc.). */ - public static final DamageEffect BURNING = getDamageEffect("burning"); + BURNING, /** * Poked by a berry bush. */ - public static final DamageEffect POKING = getDamageEffect("poking"); + POKING, /** * Freeze tick (powder snow). */ - public static final DamageEffect FREEZING = getDamageEffect("freezing"); + FREEZING; @NotNull + @Deprecated private static DamageEffect getDamageEffect(@NotNull String key) { return Preconditions.checkNotNull(Bukkit.getUnsafe().getDamageEffect(key), "No DamageEffect found for %s. This is a bug.", key); } @@ -49,5 +50,7 @@ public interface DamageEffect { * @return the sound */ @NotNull - public Sound getSound(); + public Sound getSound() { + return Bukkit.getUnsafe().getSoundForDamageEffect(this); + } } diff --git a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java index a41356e136..8316b72296 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java @@ -4,6 +4,7 @@ import com.google.common.base.Preconditions; import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.PaperDataComponentType; +import io.papermc.paper.registry.data.PaperDamageTypeRegistryEntry; import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry; import io.papermc.paper.registry.data.PaperGameEventRegistryEntry; import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry; @@ -102,7 +103,7 @@ public final class PaperRegistries { start(Registries.STRUCTURE, RegistryKey.STRUCTURE).craft(Structure.class, CraftStructure::new).build().delayed(), start(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL).craft(TrimMaterial.class, CraftTrimMaterial::new).build().delayed(), start(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN).craft(TrimPattern.class, CraftTrimPattern::new).build().delayed(), - start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).build().delayed(), + start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).writable(PaperDamageTypeRegistryEntry.PaperBuilder::new).delayed(), start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().delayed(), start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).serializationUpdater(FieldRename.ENCHANTMENT_RENAME).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).delayed(), start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(), diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperDamageTypeRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperDamageTypeRegistryEntry.java new file mode 100644 index 0000000000..b2c3685cdb --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperDamageTypeRegistryEntry.java @@ -0,0 +1,120 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.damagesource.*; +import org.bukkit.craftbukkit.damage.CraftDamageType; +import org.bukkit.damage.DamageEffect; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperDamageTypeRegistryEntry implements DamageTypeRegistryEntry { + protected @Nullable String messageId; + protected @Nullable Float exhaustion; + protected @Nullable DamageScaling damageScaling; + protected @Nullable DamageEffects damageEffects; + protected @Nullable DeathMessageType deathMessageType; + + protected final Conversions conversions; + + public PaperDamageTypeRegistryEntry( + final Conversions conversions, + final @Nullable DamageType internal + ) { + this.conversions = conversions; + if (internal == null) return; + + this.messageId = internal.msgId(); + this.exhaustion = internal.exhaustion(); + this.damageScaling = internal.scaling(); + this.damageEffects = internal.effects(); + this.deathMessageType = internal.deathMessageType(); + } + + @Override + public String messageId() { + return asConfigured(messageId, "messsageId"); + } + + @Override + public Float exhaustion() { + return asConfigured(exhaustion, "exhaustion"); + } + + @Override + public org.bukkit.damage.DamageScaling damageScaling() { + return CraftDamageType.damageScalingToBukkit(asConfigured(this.damageScaling, "damageScaling")); + } + + @Override + public @Nullable DamageEffect damageEffect() { + return damageEffects == null ? null : CraftDamageType.damageEffectToBukkit(damageEffects); + } + + @Override + public org.bukkit.damage.@Nullable DeathMessageType deathMessageType() { + return deathMessageType == null ? null : CraftDamageType.deathMessageTypeToBukkit(deathMessageType); + } + + public static final class PaperBuilder extends PaperDamageTypeRegistryEntry implements DamageTypeRegistryEntry.Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable DamageType internal) { + super(conversions, internal); + } + + @Override + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + @Override + public Builder exhaustion(Float exhaustion) { + this.exhaustion = exhaustion; + return this; + } + + @Override + public Builder damageScaling(org.bukkit.damage.DamageScaling scaling) { + this.damageScaling = CraftDamageType.damageScalingToNMS(scaling); + return this; + } + + @Override + public Builder damageEffect(@Nullable DamageEffect effect) { + this.damageEffects = effect == null ? null : CraftDamageType.damageEffectToNMS(effect); + return this; + } + + @Override + public Builder deathMessageType(org.bukkit.damage.@Nullable DeathMessageType deathMessageType) { + this.deathMessageType = deathMessageType == null ? null : CraftDamageType.deathMessageTypeToNMS(deathMessageType); + return this; + } + + @Override + public DamageType build() { + if (this.damageEffects != null && this.deathMessageType != null) { + return new DamageType( + asConfigured(this.messageId, "messsageId"), + asConfigured(this.damageScaling, "scaling"), + asConfigured(this.exhaustion, "exhaustion"), + this.damageEffects, + this.deathMessageType); + } else if (this.damageEffects != null) { + return new DamageType( + asConfigured(this.messageId, "messsageId"), + asConfigured(this.damageScaling, "scaling"), + asConfigured(this.exhaustion, "exhaustion"), + this.damageEffects); + } else { + return new DamageType( + asConfigured(this.messageId, "messsageId"), + asConfigured(this.damageScaling, "scaling"), + asConfigured(this.exhaustion, "exhaustion") + ); + } + } + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageEffect.java b/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageEffect.java index e472a61c16..94e74608a2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageEffect.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageEffect.java @@ -5,7 +5,8 @@ import org.bukkit.Sound; import org.bukkit.craftbukkit.CraftSound; import org.bukkit.damage.DamageEffect; -public class CraftDamageEffect implements DamageEffect { +@Deprecated +public class CraftDamageEffect { private final DamageEffects damageEffects; @@ -17,7 +18,6 @@ public class CraftDamageEffect implements DamageEffect { return this.damageEffects; } - @Override public Sound getSound() { return CraftSound.minecraftToBukkit(this.getHandle().sound()); } @@ -32,6 +32,6 @@ public class CraftDamageEffect implements DamageEffect { } public static DamageEffect toBukkit(DamageEffects damageEffects) { - return new CraftDamageEffect(damageEffects); + return CraftDamageType.damageEffectToBukkit(damageEffects); } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageType.java b/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageType.java index d486412429..3a33200a3f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageType.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageType.java @@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.damage; import com.google.common.base.Preconditions; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; +import net.minecraft.world.damagesource.DamageEffects; import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.craftbukkit.CraftRegistry; @@ -98,6 +99,30 @@ public class CraftDamageType implements DamageType, Handleable DamageEffect.HURT; + case THORNS -> DamageEffect.THORNS; + case DROWNING -> DamageEffect.DROWNING; + case BURNING -> DamageEffect.BURNING; + case POKING -> DamageEffect.POKING; + case FREEZING -> DamageEffect.FREEZING; + default -> throw new IllegalArgumentException("NMS DamageEffect." + damageEffect + " cannot be converted to a Bukkit DamageEffect"); + }; + } + + public static DamageEffects damageEffectToNMS(DamageEffect damageEffect) { + return switch (damageEffect) { + case DamageEffect.HURT -> DamageEffects.HURT; + case DamageEffect.THORNS -> DamageEffects.THORNS; + case DamageEffect.DROWNING -> DamageEffects.DROWNING; + case DamageEffect.BURNING -> DamageEffects.BURNING; + case DamageEffect.POKING -> DamageEffects.POKING; + case DamageEffect.FREEZING -> DamageEffects.FREEZING; + default -> throw new IllegalArgumentException("Bukkit DamageEffect." + damageEffect + " cannot be converted to a NMS DamageEffect"); + }; + } + public static DamageType minecraftHolderToBukkit(Holder minecraftHolder) { return CraftDamageType.minecraftToBukkit(minecraftHolder.value()); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index b6665e1875..3da83cc1cd 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -467,6 +467,7 @@ public final class CraftMagicNumbers implements UnsafeValues { } @Override + @Deprecated public DamageEffect getDamageEffect(String key) { Preconditions.checkArgument(key != null, "key cannot be null"); return CraftDamageEffect.getById(key); @@ -674,6 +675,12 @@ public final class CraftMagicNumbers implements UnsafeValues { player == null ? null : ((org.bukkit.craftbukkit.entity.CraftPlayer) player).getHandle(), flag); return lines.stream().map(io.papermc.paper.adventure.PaperAdventure::asAdventure).toList(); } + + @Override + public org.bukkit.Sound getSoundForDamageEffect(DamageEffect damageEffect) { + Preconditions.checkArgument(damageEffect != null, "key cannot be null"); + return org.bukkit.craftbukkit.CraftSound.minecraftToBukkit(org.bukkit.craftbukkit.damage.CraftDamageType.damageEffectToNMS(damageEffect).sound()); + } // Paper end // Paper start - spawn egg color visibility