Add DamageType registry event

This commit is contained in:
Chaosdave34 2024-12-23 13:08:23 +01:00
parent a0b3326609
commit e5b3b72c83
9 changed files with 292 additions and 12 deletions

View file

@ -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>)
* <p>
* <strong>Note</strong> 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<DamageType> {
/**
* 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);
}
}

View file

@ -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<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT);
public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT);
public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT);
public static final RegistryEventProvider<DamageType, DamageTypeRegistryEntry.Builder> DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE);
private RegistryEvents() {
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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(),

View file

@ -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<DamageType, org.bukkit.damage.DamageType> {
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")
);
}
}
}
}

View file

@ -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);
}
}

View file

@ -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<net.minecraft.wor
};
}
public static DamageEffect damageEffectToBukkit(DamageEffects damageEffect) {
return switch (damageEffect) {
case HURT -> 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<net.minecraft.world.damagesource.DamageType> minecraftHolder) {
return CraftDamageType.minecraftToBukkit(minecraftHolder.value());
}

View file

@ -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