SPIGOT-7942: Add Consumable Component

This commit is contained in:
Doc 2025-02-16 09:02:19 +11:00 committed by md_5
parent 29e1e9f1ab
commit ade46cc79f
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
10 changed files with 541 additions and 34 deletions

View File

@ -17,8 +17,8 @@ import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.FireworkEffect.Type;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific.To;
import org.bukkit.craftbukkit.inventory.ItemMetaKey.Specific;
import org.bukkit.craftbukkit.inventory.ItemMetaKey.Specific.To;
import org.bukkit.inventory.meta.FireworkMeta;
@DelegateDeserialization(SerializableMeta.class)

View File

@ -14,10 +14,6 @@ import com.mojang.serialization.DynamicOps;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
@ -57,6 +53,7 @@ import net.minecraft.nbt.SnbtPrinterTagVisitor;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Unit;
import net.minecraft.world.entity.EnumItemSlot;
@ -65,9 +62,11 @@ import net.minecraft.world.entity.ai.attributes.AttributeBase;
import net.minecraft.world.food.FoodInfo;
import net.minecraft.world.item.EitherHolder;
import net.minecraft.world.item.EnumItemRarity;
import net.minecraft.world.item.ItemUseAnimation;
import net.minecraft.world.item.JukeboxPlayable;
import net.minecraft.world.item.JukeboxSongs;
import net.minecraft.world.item.component.BlockItemStateProperties;
import net.minecraft.world.item.component.Consumable;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.component.CustomModelData;
import net.minecraft.world.item.component.DamageResistant;
@ -97,13 +96,14 @@ import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific;
import org.bukkit.craftbukkit.inventory.ItemMetaKey.Specific;
import org.bukkit.craftbukkit.inventory.components.CraftCustomModelDataComponent;
import org.bukkit.craftbukkit.inventory.components.CraftEquippableComponent;
import org.bukkit.craftbukkit.inventory.components.CraftFoodComponent;
import org.bukkit.craftbukkit.inventory.components.CraftJukeboxComponent;
import org.bukkit.craftbukkit.inventory.components.CraftToolComponent;
import org.bukkit.craftbukkit.inventory.components.CraftUseCooldownComponent;
import org.bukkit.craftbukkit.inventory.components.consumable.CraftConsumableComponent;
import org.bukkit.craftbukkit.inventory.tags.DeprecatedCustomTagContainer;
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
@ -128,6 +128,7 @@ import org.bukkit.inventory.meta.components.FoodComponent;
import org.bukkit.inventory.meta.components.JukeboxPlayableComponent;
import org.bukkit.inventory.meta.components.ToolComponent;
import org.bukkit.inventory.meta.components.UseCooldownComponent;
import org.bukkit.inventory.meta.components.consumable.ConsumableComponent;
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.tag.DamageTypeTags;
@ -158,32 +159,6 @@ import org.bukkit.tag.DamageTypeTags;
// Important: ItemMeta needs to be the first interface see #applicableTo(Material)
class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
static class ItemMetaKey {
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
@interface Specific {
enum To {
BUKKIT,
NBT,
;
}
To value();
}
final String BUKKIT;
final String NBT;
ItemMetaKey(final String both) {
this(both, both);
}
ItemMetaKey(final String nbt, final String bukkit) {
this.NBT = nbt;
this.BUKKIT = bukkit;
}
}
static final class ItemMetaKeyType<T> extends ItemMetaKey {
final DataComponentType<T> TYPE;
@ -262,6 +237,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<FoodInfo> FOOD = new ItemMetaKeyType<>(DataComponents.FOOD, "food");
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<Consumable> CONSUMABLE = new ItemMetaKeyType<>(DataComponents.CONSUMABLE, "consumable");
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<Tool> TOOL = new ItemMetaKeyType<>(DataComponents.TOOL, "tool");
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<Equippable> EQUIPPABLE = new ItemMetaKeyType<>(DataComponents.EQUIPPABLE, "equippable");
@ -302,6 +279,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
private ItemStack useRemainder;
private CraftUseCooldownComponent useCooldown;
private CraftFoodComponent food;
private CraftConsumableComponent consumable;
private CraftToolComponent tool;
private CraftEquippableComponent equippable;
private CraftJukeboxComponent jukebox;
@ -364,6 +342,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
if (meta.hasFood()) {
this.food = new CraftFoodComponent(meta.food);
}
if (meta.hasConsumable()) {
this.consumable = new CraftConsumableComponent(meta.consumable);
}
if (meta.hasTool()) {
this.tool = new CraftToolComponent(meta.tool);
}
@ -470,6 +451,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
getOrEmpty(tag, FOOD).ifPresent((foodInfo) -> {
food = new CraftFoodComponent(foodInfo);
});
getOrEmpty(tag, CONSUMABLE).ifPresent((consumableInfo) -> {
consumable = new CraftConsumableComponent(consumableInfo);
});
getOrEmpty(tag, TOOL).ifPresent((toolInfo) -> {
tool = new CraftToolComponent(toolInfo);
});
@ -700,6 +684,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
setFood(food);
}
CraftConsumableComponent consumable = SerializableMeta.getObject(CraftConsumableComponent.class, map, CONSUMABLE.BUKKIT, true);
if (consumable != null) {
setConsumable(consumable);
}
CraftToolComponent tool = SerializableMeta.getObject(CraftToolComponent.class, map, TOOL.BUKKIT, true);
if (tool != null) {
setTool(tool);
@ -993,6 +982,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
itemTag.put(FOOD, food.getHandle());
}
if (hasConsumable()) {
itemTag.put(CONSUMABLE, consumable.getHandle());
}
if (hasTool()) {
itemTag.put(TOOL, tool.getHandle());
}
@ -1103,7 +1096,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
@Overridden
boolean isEmpty() {
return !(hasDisplayName() || hasItemName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasEnchantable() || hasBlockData() || hasRepairCost() || !unhandledTags.build().isEmpty() || !removedTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isHideTooltip() || hasTooltipStyle() || hasItemModel() || isUnbreakable() || hasEnchantmentGlintOverride() || isGlider() || hasDamageResistant() || hasMaxStackSize() || hasRarity() || hasUseRemainder() || hasUseCooldown() || hasFood() || hasTool() || hasJukeboxPlayable() || hasEquippable() || hasDamage() || hasMaxDamage() || hasAttributeModifiers() || customTag != null);
return !(hasDisplayName() || hasItemName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasEnchantable() || hasBlockData() || hasRepairCost() || !unhandledTags.build().isEmpty() || !removedTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isHideTooltip() || hasTooltipStyle() || hasItemModel() || isUnbreakable() || hasEnchantmentGlintOverride() || isGlider() || hasDamageResistant() || hasMaxStackSize() || hasRarity() || hasUseRemainder() || hasUseCooldown() || hasFood() || hasConsumable() || hasTool() || hasJukeboxPlayable() || hasEquippable() || hasDamage() || hasMaxDamage() || hasAttributeModifiers() || customTag != null);
}
@Override
@ -1530,6 +1523,21 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
this.food = (food == null) ? null : new CraftFoodComponent((CraftFoodComponent) food);
}
@Override
public boolean hasConsumable() {
return this.consumable != null;
}
@Override
public ConsumableComponent getConsumable() {
return (this.hasConsumable()) ? new CraftConsumableComponent(this.consumable) : new CraftConsumableComponent(new Consumable(Consumable.DEFAULT_CONSUME_SECONDS, ItemUseAnimation.EAT, SoundEffects.GENERIC_EAT, true, List.of()));
}
@Override
public void setConsumable(ConsumableComponent consumable) {
this.consumable = (consumable == null) ? null : new CraftConsumableComponent((CraftConsumableComponent) consumable);
}
@Override
public boolean hasTool() {
return this.tool != null;
@ -1833,6 +1841,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
&& (this.hasUseRemainder() ? that.hasUseRemainder() && this.useRemainder.equals(that.useRemainder) : !that.hasUseRemainder())
&& (this.hasUseCooldown() ? that.hasUseCooldown() && this.useCooldown.equals(that.useCooldown) : !that.hasUseCooldown())
&& (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood())
&& (this.hasConsumable() ? that.hasConsumable() && this.consumable.equals(that.consumable) : !that.hasConsumable())
&& (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool())
&& (this.hasEquippable() ? that.hasEquippable() && this.equippable.equals(that.equippable) : !that.hasEquippable())
&& (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable())
@ -1884,6 +1893,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
hash = 61 * hash + (hasUseRemainder() ? this.useRemainder.hashCode() : 0);
hash = 61 * hash + (hasUseCooldown() ? this.useCooldown.hashCode() : 0);
hash = 61 * hash + (hasFood() ? this.food.hashCode() : 0);
hash = 61 * hash + (hasConsumable() ? this.consumable.hashCode() : 0);
hash = 61 * hash + (hasTool() ? this.tool.hashCode() : 0);
hash = 61 * hash + (hasJukeboxPlayable() ? this.jukebox.hashCode() : 0);
hash = 61 * hash + (hasEquippable() ? this.equippable.hashCode() : 0);
@ -1937,6 +1947,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
if (this.hasFood()) {
clone.food = new CraftFoodComponent(food);
}
if (this.hasConsumable()) {
clone.consumable = new CraftConsumableComponent(consumable);
}
if (this.hasTool()) {
clone.tool = new CraftToolComponent(tool);
}
@ -2057,6 +2070,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
builder.put(FOOD.BUKKIT, food);
}
if (hasConsumable()) {
builder.put(CONSUMABLE.BUKKIT, consumable);
}
if (hasTool()) {
builder.put(TOOL.BUKKIT, tool);
}
@ -2251,6 +2268,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
USE_REMAINDER.TYPE,
USE_COOLDOWN.TYPE,
FOOD.TYPE,
CONSUMABLE.TYPE,
TOOL.TYPE,
EQUIPPABLE.TYPE,
JUKEBOX_PLAYABLE.TYPE,

View File

@ -0,0 +1,31 @@
package org.bukkit.craftbukkit.inventory;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class ItemMetaKey {
@Retention(value = RetentionPolicy.SOURCE)
@Target(value = ElementType.FIELD)
@interface Specific {
public static enum To {
BUKKIT, NBT
}
To value();
}
public final String BUKKIT;
public final String NBT;
public ItemMetaKey(final String both) {
this(both, both);
}
public ItemMetaKey(final String nbt, final String bukkit) {
this.NBT = nbt;
this.BUKKIT = bukkit;
}
}

View File

@ -0,0 +1,137 @@
package org.bukkit.craftbukkit.inventory.components.consumable;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.core.Holder;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.sounds.SoundEffects;
import net.minecraft.world.item.ItemUseAnimation;
import net.minecraft.world.item.component.Consumable;
import net.minecraft.world.item.consume_effects.ConsumeEffect;
import org.bukkit.Sound;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.craftbukkit.CraftSound;
import org.bukkit.craftbukkit.inventory.SerializableMeta;
import org.bukkit.craftbukkit.inventory.components.consumable.effects.CraftConsumableEffect;
import org.bukkit.inventory.meta.components.consumable.ConsumableComponent;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumableEffect;
@SerializableAs("Consumable")
public class CraftConsumableComponent implements ConsumableComponent {
private Consumable handle;
public CraftConsumableComponent(Consumable consumable) {
this.handle = consumable;
}
public CraftConsumableComponent(CraftConsumableComponent consumable) {
this.handle = consumable.handle;
}
public CraftConsumableComponent(Map<String, Object> map) {
Float consumeSeconds = SerializableMeta.getObject(Float.class, map, "consume-seconds", false);
Animation animation = SerializableMeta.getObject(Animation.class, map, "animation", false);
Boolean hasConsumeParticles = SerializableMeta.getBoolean(map, "has-consume-particles");
Sound sound = SerializableMeta.getObject(Sound.class, map, "sound", false);
List<ConsumableEffect> consumableEffects = SerializableMeta.getList(ConsumableEffect.class, map, "effects");
List<ConsumeEffect> consumeEffects = (List<ConsumeEffect>) consumableEffects.stream().map(consumableEffect -> CraftConsumableEffect.bukkitToMinecraftSpecific(((CraftConsumableEffect<?>) consumableEffect))).toList();
this.handle = new Consumable(consumeSeconds, CraftAnimation.bukkitToMinecraft(animation), CraftSound.bukkitToMinecraftHolder(sound), hasConsumeParticles, consumeEffects);
}
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<>();
result.put("consume-seconds", this.getConsumeSeconds());
result.put("animation", this.getAnimation());
result.put("sound", this.getSound());
result.put("has-consume-particles", this.hasConsumeParticles());
result.put("effects", this.getEffects());
return result;
}
public Consumable getHandle() {
return handle;
}
@Override
public float getConsumeSeconds() {
return this.handle.consumeSeconds();
}
@Override
public void setConsumeSeconds(float consumeSeconds) {
handle = new Consumable(consumeSeconds, this.handle.animation(), this.handle.sound(), this.handle.hasConsumeParticles(), this.handle.onConsumeEffects());
}
@Override
public Animation getAnimation() {
return CraftAnimation.minecraftToBukkit(this.handle.animation());
}
@Override
public void setAnimation(Animation animation) {
Preconditions.checkArgument(animation != null, "Animation cannot be null");
handle = new Consumable(this.handle.consumeSeconds(), CraftAnimation.bukkitToMinecraft(animation), this.handle.sound(), this.handle.hasConsumeParticles(), this.handle.onConsumeEffects());
}
@Override
public Sound getSound() {
return CraftSound.minecraftHolderToBukkit(this.handle.sound());
}
@Override
public void setSound(Sound sound) {
Holder<SoundEffect> soundEffectHolder = (sound != null) ? CraftSound.bukkitToMinecraftHolder(sound) : SoundEffects.GENERIC_EAT;
handle = new Consumable(this.handle.consumeSeconds(), this.handle.animation(), soundEffectHolder, this.handle.hasConsumeParticles(), this.handle.onConsumeEffects());
}
@Override
public boolean hasConsumeParticles() {
return this.handle.hasConsumeParticles();
}
@Override
public void setConsumeParticles(boolean consumeParticles) {
handle = new Consumable(this.handle.consumeSeconds(), this.handle.animation(), this.handle.sound(), consumeParticles, this.handle.onConsumeEffects());
}
@Override
public List<ConsumableEffect> getEffects() {
return this.getHandle().onConsumeEffects().stream().map(CraftConsumableEffect::minecraftToBukkitSpecific).map(o -> ((ConsumableEffect) o)).toList();
}
@Override
public void setEffects(List<ConsumableEffect> effects) {
handle = new Consumable(this.handle.consumeSeconds(), this.handle.animation(), this.handle.sound(), this.handle.hasConsumeParticles(), effects.stream().map(consumableEffect -> CraftConsumableEffect.bukkitToMinecraftSpecific(((CraftConsumableEffect<ConsumeEffect>) consumableEffect))).toList());
}
@Override
public ConsumableEffect addEffect(ConsumableEffect consumableEffect) {
List<ConsumeEffect> effects = new ArrayList<>(this.handle.onConsumeEffects());
ConsumeEffect newEffect = CraftConsumableEffect.bukkitToMinecraftSpecific(((CraftConsumableEffect<?>) consumableEffect));
effects.add(newEffect);
handle = new Consumable(this.handle.consumeSeconds(), this.handle.animation(), this.handle.sound(), this.handle.hasConsumeParticles(), effects);
return consumableEffect;
}
public static class CraftAnimation {
public static Animation minecraftToBukkit(ItemUseAnimation minecraft) {
return Animation.valueOf(minecraft.name());
}
public static ItemUseAnimation bukkitToMinecraft(Animation bukkit) {
return ItemUseAnimation.valueOf(bukkit.name());
}
}
}

View File

@ -0,0 +1,85 @@
package org.bukkit.craftbukkit.inventory.components.consumable.effects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect;
import org.bukkit.craftbukkit.inventory.ItemMetaKey;
import org.bukkit.craftbukkit.inventory.SerializableMeta;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumableApplyEffects;
import org.bukkit.potion.PotionEffect;
public class CraftConsumableApplyEffects extends CraftConsumableEffect<ApplyStatusEffectsConsumeEffect> implements ConsumableApplyEffects {
static final ItemMetaKey POTIONS = new ItemMetaKey("effects");
public CraftConsumableApplyEffects(ApplyStatusEffectsConsumeEffect consumeEffect) {
super(consumeEffect);
}
public CraftConsumableApplyEffects(CraftConsumableApplyEffects consumeEffect) {
super(consumeEffect);
}
public CraftConsumableApplyEffects(Map<String, Object> map) {
super(map);
List<PotionEffect> effectList = new ArrayList<>();
Iterable<?> rawEffectTypeList = SerializableMeta.getObject(Iterable.class, map, POTIONS, true);
if (rawEffectTypeList == null) {
return;
}
for (Object obj : rawEffectTypeList) {
Preconditions.checkArgument(obj instanceof PotionEffect, "Object (%s) in effect list is not valid", obj.getClass());
effectList.add((PotionEffect) obj);
}
Float probability = SerializableMeta.getObject(Float.class, map, "probability", false);
this.handle = new ApplyStatusEffectsConsumeEffect(effectList.stream().map(CraftPotionUtil::fromBukkit).toList(), probability);
}
@Override
public List<PotionEffect> getEffects() {
List<MobEffect> mobEffectList = this.getHandle().effects();
return mobEffectList.stream().map(CraftPotionUtil::toBukkit).toList();
}
@Override
public void setEffects(List<PotionEffect> list) {
this.handle = new ApplyStatusEffectsConsumeEffect(list.stream().map(CraftPotionUtil::fromBukkit).toList());
}
@Override
public PotionEffect addEffect(PotionEffect potionEffect) {
List<MobEffect> mobEffectList = this.getHandle().effects();
mobEffectList.add(CraftPotionUtil.fromBukkit(potionEffect));
this.handle = new ApplyStatusEffectsConsumeEffect(mobEffectList, this.handle.probability());
return potionEffect;
}
@Override
public float getProbability() {
return this.getHandle().probability();
}
@Override
public void setProbability(float probability) {
Preconditions.checkArgument(probability >= 0.0f && probability <= 1.0f, "Probability must be between 0.0f and 1.0f but is %s", probability);
this.handle = new ApplyStatusEffectsConsumeEffect(this.getHandle().effects(), probability);
}
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<>();
result.put(POTIONS.BUKKIT, ImmutableList.copyOf(this.getEffects()));
return result;
}
}

View File

@ -0,0 +1,21 @@
package org.bukkit.craftbukkit.inventory.components.consumable.effects;
import java.util.Map;
import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumableClearEffects;
public class CraftConsumableClearEffects extends CraftConsumableEffect<ClearAllStatusEffectsConsumeEffect> implements ConsumableClearEffects {
public CraftConsumableClearEffects(ClearAllStatusEffectsConsumeEffect consumeEffect) {
super(consumeEffect);
}
public CraftConsumableClearEffects(CraftConsumableClearEffects consumeEffect) {
super(consumeEffect);
}
@Override
public Map<String, Object> serialize() {
return Map.of();
}
}

View File

@ -0,0 +1,49 @@
package org.bukkit.craftbukkit.inventory.components.consumable.effects;
import java.util.Map;
import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect;
import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect;
import net.minecraft.world.item.consume_effects.ConsumeEffect;
import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect;
import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect;
import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumableEffect;
public abstract class CraftConsumableEffect<T extends ConsumeEffect> implements ConsumableEffect {
public static <T extends CraftConsumableEffect<?>> T minecraftToBukkitSpecific(ConsumeEffect effect) {
if (effect instanceof ApplyStatusEffectsConsumeEffect nmsEffect) {
return ((T) new CraftConsumableApplyEffects(nmsEffect));
} else if (effect instanceof RemoveStatusEffectsConsumeEffect nmsEffect) {
return ((T) new CraftConsumableRemoveEffect(nmsEffect));
} else if (effect instanceof ClearAllStatusEffectsConsumeEffect nmsEffect) {
return ((T) new CraftConsumableClearEffects(nmsEffect));
} else if (effect instanceof TeleportRandomlyConsumeEffect nmsEffect) {
return ((T) new CraftConsumableTeleportRandomly(nmsEffect));
} else if (effect instanceof PlaySoundConsumeEffect nmsEffect) {
return ((T) new CraftConsumablePlaySound(nmsEffect));
}
throw new IllegalStateException("Unexpected value: " + effect.getType());
}
public static <T extends ConsumeEffect> T bukkitToMinecraftSpecific(CraftConsumableEffect<T> effect) {
return effect.getHandle();
}
T handle;
public CraftConsumableEffect(T consumeEffect) {
this.handle = consumeEffect;
}
public CraftConsumableEffect(CraftConsumableEffect<T> consumeEffect) {
this.handle = consumeEffect.handle;
}
public CraftConsumableEffect(Map<String, Object> map) {
}
public T getHandle() {
return handle;
}
}

View File

@ -0,0 +1,41 @@
package org.bukkit.craftbukkit.inventory.components.consumable.effects;
import java.util.LinkedHashMap;
import java.util.Map;
import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.CraftSound;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumablePlaySound;
public class CraftConsumablePlaySound extends CraftConsumableEffect<PlaySoundConsumeEffect> implements ConsumablePlaySound {
public CraftConsumablePlaySound(PlaySoundConsumeEffect consumeEffect) {
super(consumeEffect);
}
public CraftConsumablePlaySound(CraftConsumableEffect<PlaySoundConsumeEffect> consumeEffect) {
super(consumeEffect);
}
public CraftConsumablePlaySound(Map<String, Object> map) {
super(map);
}
@Override
public Sound getSound() {
return CraftSound.minecraftHolderToBukkit(this.getHandle().sound());
}
@Override
public void setSound(Sound sound) {
this.handle = new PlaySoundConsumeEffect(CraftSound.bukkitToMinecraftHolder(sound));
}
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<>();
result.put("sound", getSound());
return result;
}
}

View File

@ -0,0 +1,76 @@
package org.bukkit.craftbukkit.inventory.components.consumable.effects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import net.minecraft.core.HolderSet;
import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect;
import org.bukkit.craftbukkit.inventory.ItemMetaKey;
import org.bukkit.craftbukkit.inventory.SerializableMeta;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumableRemoveEffect;
import org.bukkit.potion.PotionEffectType;
public class CraftConsumableRemoveEffect extends CraftConsumableEffect<RemoveStatusEffectsConsumeEffect> implements ConsumableRemoveEffect {
static final ItemMetaKey POTION_TYPES = new ItemMetaKey("effects");
public CraftConsumableRemoveEffect(RemoveStatusEffectsConsumeEffect consumeEffect) {
super(consumeEffect);
}
public CraftConsumableRemoveEffect(CraftConsumableRemoveEffect consumeEffect) {
super(consumeEffect);
}
public CraftConsumableRemoveEffect(Map<String, Object> map) {
super(map);
List<PotionEffectType> effectTypeList = new ArrayList<>();
Iterable<?> rawEffectTypeList = SerializableMeta.getObject(Iterable.class, map, POTION_TYPES.BUKKIT, true);
if (rawEffectTypeList == null) {
return;
}
for (Object obj : rawEffectTypeList) {
Preconditions.checkArgument(obj instanceof PotionEffectType, "Object (%s) in effect type list is not valid", obj.getClass());
effectTypeList.add((PotionEffectType) obj);
}
super.handle = new RemoveStatusEffectsConsumeEffect(HolderSet.direct(effectTypeList.stream().map(CraftPotionEffectType::bukkitToMinecraftHolder).collect(Collectors.toList())));
}
public RemoveStatusEffectsConsumeEffect getHandle() {
return (RemoveStatusEffectsConsumeEffect) super.getHandle();
}
@Override
public List<PotionEffectType> getEffectTypes() {
return this.getHandle().effects().stream().map(CraftPotionEffectType::minecraftHolderToBukkit).collect(Collectors.toList());
}
@Override
public void setEffectTypes(List<PotionEffectType> effectTypeList) {
this.handle = new RemoveStatusEffectsConsumeEffect(HolderSet.direct(effectTypeList.stream().map(CraftPotionEffectType::bukkitToMinecraftHolder).collect(Collectors.toList())));
}
@Override
public PotionEffectType addEffectType(PotionEffectType potionEffect) {
List<PotionEffectType> list = this.getEffectTypes();
list.add(potionEffect);
this.setEffectTypes(list);
return potionEffect;
}
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<>();
result.put(POTION_TYPES.BUKKIT, ImmutableList.copyOf(this.getEffectTypes()));
return result;
}
}

View File

@ -0,0 +1,49 @@
package org.bukkit.craftbukkit.inventory.components.consumable.effects;
import java.util.LinkedHashMap;
import java.util.Map;
import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect;
import org.bukkit.craftbukkit.inventory.SerializableMeta;
import org.bukkit.inventory.meta.components.consumable.effects.ConsumableTeleportRandomly;
import org.jetbrains.annotations.NotNull;
public class CraftConsumableTeleportRandomly extends CraftConsumableEffect<TeleportRandomlyConsumeEffect> implements ConsumableTeleportRandomly {
private TeleportRandomlyConsumeEffect handle;
public CraftConsumableTeleportRandomly(TeleportRandomlyConsumeEffect consumableEffect) {
super(consumableEffect);
}
public CraftConsumableTeleportRandomly(CraftConsumableTeleportRandomly consumableEffect) {
super(consumableEffect);
this.handle = consumableEffect.handle;
}
public CraftConsumableTeleportRandomly(Map<String, Object> map) {
super(map);
Float diameter = SerializableMeta.getObject(Float.class, map, "diameter", false);
this.handle = new TeleportRandomlyConsumeEffect(diameter);
}
@Override
public float getDiameter() {
return this.handle.diameter();
}
@Override
public void setDiameter(float diameter) {
handle = new TeleportRandomlyConsumeEffect(diameter);
}
@NotNull
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<>();
result.put("diameter", getDiameter());
return result;
}
}