diff --git a/SpongeAPI b/SpongeAPI index d15129ee57e..34dda9c933d 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit d15129ee57e97491fc3a4e1e1ba6051683d142b2 +Subproject commit 34dda9c933d867c35e04fd77d951d6440ff2a384 diff --git a/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java b/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java index 63366a3e4c3..205a2cc1934 100644 --- a/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java +++ b/generator/src/main/java/org/spongepowered/vanilla/generator/item/ItemRegistries.java @@ -111,6 +111,13 @@ public static List itemRegistries(final Context context) { $ -> true, RegistryScope.SERVER ), + new RegistryEntriesGenerator<>( + "data.type", + "ItemActionTypes", + "ITEM_ACTION_TYPE", + context.relativeClass("data.type", "ItemActionType"), + Registries.CONSUME_EFFECT_TYPE + ), new EnumEntriesValidator<>( "entity.display", "ItemDisplayTypes", diff --git a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java index d0996aa7c40..eb411c5c0b7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java +++ b/src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java @@ -25,12 +25,11 @@ package org.spongepowered.common.data.provider.item.stack; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.StringUtil; import net.minecraft.util.Unit; @@ -43,22 +42,19 @@ import net.minecraft.world.item.component.Consumable; import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.DamageResistant; +import net.minecraft.world.item.component.DeathProtection; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.item.component.Unbreakable; import net.minecraft.world.item.component.UseCooldown; import net.minecraft.world.item.component.UseRemainder; -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.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.Platform; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.data.DataTransactionResult; import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ItemAction; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.item.ItemRarity; import org.spongepowered.api.item.ItemType; @@ -78,7 +74,7 @@ public final class ItemStackData { public static final FoodProperties DEFAULT_FOOD_PROPERTIES = new FoodProperties(0, 0, false); - public static final Consumable DEFAULT_CONSUMABLE_PROPERTIES = new Consumable(1.6F, ItemUseAnimation.EAT, null, true, List.of()); + public static final Consumable DEFAULT_CONSUMABLE_PROPERTIES = new Consumable(1.6F, ItemUseAnimation.EAT, SoundEvents.GENERIC_EAT, true, List.of()); private ItemStackData() { } @@ -100,14 +96,6 @@ public static void register(final DataProviderRegistrator registrator) { // TODO DataComponents.RECIPES - for Items.KNOWLEDGE_BOOK // TODO DataComponents.OMINOUS_BOTTLE_AMPLIFIER 1.21 - // TODO rework applicable potion effects to consume effects - final var applicablePotionEffects = Keys.APPLICABLE_POTION_EFFECTS; - ConsumeEffect newPotionEffects = new ApplyStatusEffectsConsumeEffect(List.of()); - ConsumeEffect teleportRand = new TeleportRandomlyConsumeEffect(5); - ConsumeEffect removeStatusEffects = new RemoveStatusEffectsConsumeEffect(HolderSet.empty()); - ConsumeEffect clearStatusEffects = new ClearAllStatusEffectsConsumeEffect(); - ConsumeEffect playSoundEffect = new PlaySoundConsumeEffect(Holder.direct(null)); - registrator .asMutable(ItemStack.class) .create(Keys.BURN_TIME) @@ -252,6 +240,20 @@ public static void register(final DataProviderRegistrator registrator) { }) .set((h, v) -> h.update(DataComponents.CONSUMABLE, DEFAULT_CONSUMABLE_PROPERTIES, c -> new Consumable(v.ticks() / 20f, c.animation(), c.sound(), c.hasConsumeParticles(), c.onConsumeEffects()))) + .create(Keys.CONSUME_ACTIONS) + .get(h -> { + final var consumable = h.get(DataComponents.CONSUMABLE); + return consumable == null ? null : (List) (Object) consumable.onConsumeEffects(); + }) + .set((h, v) -> h.update(DataComponents.CONSUMABLE, DEFAULT_CONSUMABLE_PROPERTIES, + c -> new Consumable(c.consumeSeconds(), c.animation(), c.sound(), c.hasConsumeParticles(), (List) (Object) v))) + .create(Keys.DEATH_PROTECTION_ACTIONS) + .get(h -> { + final var deathProtection = h.get(DataComponents.DEATH_PROTECTION); + return deathProtection == null ? null : (List) (Object) deathProtection.deathEffects(); + }) + .set((h, v) -> h.set(DataComponents.DEATH_PROTECTION, new DeathProtection((List) (Object) v))) + .delete(h -> h.remove(DataComponents.DEATH_PROTECTION)) .create(Keys.FOOD_CONVERTS_TO) .get(h -> { final var remainder = h.get(DataComponents.USE_REMAINDER); diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java b/src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java new file mode 100644 index 00000000000..ce8a0bcc56f --- /dev/null +++ b/src/main/java/org/spongepowered/common/item/SpongeItemActionFactory.java @@ -0,0 +1,93 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.item; + +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; +import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; +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.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffect; +import org.spongepowered.api.effect.potion.PotionEffectType; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.api.tag.Tag; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class SpongeItemActionFactory implements ItemAction.Factory { + + @Override + public ItemAction.ApplyEffects applyEffects(final double chance, final List effects) { + Objects.requireNonNull(effects, "effects"); + if (chance < 0 || chance > 1) { + throw new IllegalArgumentException("chance must be in range [0; 1]: " + chance); + } + return (ItemAction.ApplyEffects) (Object) new ApplyStatusEffectsConsumeEffect((List) List.copyOf(effects), (float) chance); + } + + @Override + public ItemAction.RemoveEffects removeEffects(final Set effectTypes) { + Objects.requireNonNull(effectTypes, "effectTypes"); + final var holderSet = HolderSet.direct( + effectType -> BuiltInRegistries.MOB_EFFECT.wrapAsHolder((MobEffect) effectType), + effectTypes); + return (ItemAction.RemoveEffects) (Object) new RemoveStatusEffectsConsumeEffect(holderSet); + } + + @Override + public ItemAction.RemoveEffects removeEffects(final Tag effectTypeTag) { + Objects.requireNonNull(effectTypeTag, "effectTypeTag"); + final var tag = (TagKey) (Object) effectTypeTag; + final var holderSet = BuiltInRegistries.MOB_EFFECT.get(tag).map(hs -> (HolderSet) hs).orElse(HolderSet.empty()); + return (ItemAction.RemoveEffects) (Object) new RemoveStatusEffectsConsumeEffect(holderSet); + } + + @Override + public ItemAction.ClearEffects clearEffects() { + return (ItemAction.ClearEffects) (Object) ClearAllStatusEffectsConsumeEffect.INSTANCE; + } + + @Override + public ItemAction.PlaySound playSound(final SoundType soundType) { + Objects.requireNonNull(soundType, "soundType"); + return (ItemAction.PlaySound) (Object) new PlaySoundConsumeEffect(BuiltInRegistries.SOUND_EVENT.wrapAsHolder((SoundEvent) (Object) soundType)); + } + + @Override + public ItemAction.TeleportRandomly teleportRandomly(final double distance) { + if (distance <= 0) { + throw new IllegalArgumentException("distance must be positive: " + distance); + } + return (ItemAction.TeleportRandomly) (Object) new TeleportRandomlyConsumeEffect((float) distance * 2); + } +} diff --git a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java index b9b30d606d2..e9d91aa1786 100644 --- a/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java +++ b/src/main/java/org/spongepowered/common/item/util/ItemStackUtil.java @@ -167,6 +167,10 @@ public static net.minecraft.world.item.ItemStack fromLikeToNative(@Nullable Item return itemStack == null ? ItemStackUtil.emptyNative() : itemStack.isEmpty() ? ItemStackUtil.emptyNative() : ItemStackUtil.toNative(itemStack.asMutable()); } + public static net.minecraft.world.item.ItemStack fromLikeToNativeCopy(@Nullable ItemStackLike itemStack) { + return itemStack == null ? ItemStackUtil.emptyNative() : itemStack.isEmpty() ? ItemStackUtil.emptyNative() : ItemStackUtil.toNative(itemStack.asMutableCopy()); + } + public static ItemStack empty() { return ItemStackUtil.fromNative(net.minecraft.world.item.ItemStack.EMPTY); } diff --git a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java index 201ebe38af7..b39affb0bce 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java @@ -41,6 +41,7 @@ import org.spongepowered.api.command.registrar.tree.CommandTreeNode; import org.spongepowered.api.command.selector.Selector; import org.spongepowered.api.data.DataManipulator; +import org.spongepowered.api.data.type.ItemAction; import org.spongepowered.api.data.type.ToolRule; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.effect.ForwardingViewer; @@ -126,6 +127,7 @@ import org.spongepowered.common.event.SpongeEventListenerRegistration; import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStepType; import org.spongepowered.common.event.tracking.BlockChangeFlagManager; +import org.spongepowered.common.item.SpongeItemActionFactory; import org.spongepowered.common.item.SpongeItemStack; import org.spongepowered.common.item.SpongeItemStackSnapshot; import org.spongepowered.common.item.SpongeToolRuleFactory; @@ -285,6 +287,7 @@ public void registerDefaultFactories() { .registerFactory(NaturalSpawner.Factory.class, new SpongeNaturalSpawnerFactory()) .registerFactory(ScoreFormat.Factory.class, new SpongeScoreFormatFactory()) .registerFactory(ToolRule.Factory.class, new SpongeToolRuleFactory()) + .registerFactory(ItemAction.Factory.class, new SpongeItemActionFactory()) .registerFactory(PortalLogic.Factory.class, new SpongePortalLogicFactory()) .registerFactory(RecipeInput.Factory.class, new SpongeRecipeInputFactory()) .registerFactory(ArmorTrim.Factory.class, new SpongeArmorTrimFactory()) diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java new file mode 100644 index 00000000000..1a2c5a5b2c4 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffectMixin_API.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffect; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(ApplyStatusEffectsConsumeEffect.class) +@Implements(@Interface(iface = ItemAction.ApplyEffects.class, prefix = "consumeEffect$")) +public abstract class ApplyStatusEffectsConsumeEffectMixin_API implements ItemAction.ApplyEffects { + + @Shadow @Final private float probability; + @Shadow @Final private List effects; + + @Override + public double chance() { + return this.probability; + } + + @Intrinsic + public List consumeEffect$effects() { + return (List) this.effects; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java new file mode 100644 index 00000000000..ffb15a2514d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffectMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ClearAllStatusEffectsConsumeEffect.class) +public abstract class ClearAllStatusEffectsConsumeEffectMixin_API implements ItemAction.ClearEffects { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java new file mode 100644 index 00000000000..b6157338515 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffectMixin_API.java @@ -0,0 +1,60 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.consume_effects.ConsumeEffect; +import net.minecraft.world.level.Level; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.data.type.ItemActionType; +import org.spongepowered.api.entity.living.Living; +import org.spongepowered.api.item.inventory.ItemStackLike; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.common.item.util.ItemStackUtil; + +import java.util.Objects; + +@Mixin(ConsumeEffect.class) +public interface ConsumeEffectMixin_API extends ItemAction { + + @Shadow ConsumeEffect.Type shadow$getType(); + @Shadow boolean shadow$apply(Level level, ItemStack itemStack, LivingEntity livingEntity); + + @Override + default ItemActionType type() { + return (ItemActionType) (Object) this.shadow$getType(); + } + + @Override + default boolean apply(final Living entity, final ItemStackLike stack) { + Objects.requireNonNull(entity, "entity"); + return this.shadow$apply( + (Level) entity.world(), + ItemStackUtil.fromLikeToNativeCopy(stack), + (LivingEntity) entity); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java new file mode 100644 index 00000000000..31e206c0c91 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/ConsumeEffect_TypeMixin_API.java @@ -0,0 +1,33 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.item.consume_effects.ConsumeEffect; +import org.spongepowered.api.data.type.ItemActionType; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ConsumeEffect.Type.class) +public abstract class ConsumeEffect_TypeMixin_API implements ItemActionType { +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java new file mode 100644 index 00000000000..4e3f681d634 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/PlaySoundConsumeEffectMixin_API.java @@ -0,0 +1,45 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.core.Holder; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.item.consume_effects.PlaySoundConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.sound.SoundType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(PlaySoundConsumeEffect.class) +public abstract class PlaySoundConsumeEffectMixin_API implements ItemAction.PlaySound { + + @Shadow @Final private Holder sound; + + @Override + public SoundType soundType() { + return (SoundType) (Object) this.sound.value(); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java new file mode 100644 index 00000000000..1aad96d28f3 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/RemoveStatusEffectsConsumeEffectMixin_API.java @@ -0,0 +1,49 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffectType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Set; +import java.util.stream.Collectors; + +@Mixin(RemoveStatusEffectsConsumeEffect.class) +public abstract class RemoveStatusEffectsConsumeEffectMixin_API implements ItemAction.RemoveEffects { + + @Shadow @Final private HolderSet effects; + + @Override + public Set effectTypes() { + return this.effects.stream().map(Holder::value).map(PotionEffectType.class::cast).collect(Collectors.toSet()); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java new file mode 100644 index 00000000000..b1a9f2bd27d --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffectMixin_API.java @@ -0,0 +1,42 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.minecraft.world.item.consume_effects; + +import net.minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffect; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(TeleportRandomlyConsumeEffect.class) +public abstract class TeleportRandomlyConsumeEffectMixin_API implements ItemAction.TeleportRandomly { + + @Shadow @Final private float diameter; + + @Override + public double distance() { + return this.diameter / 2; + } +} diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index bcfb7af29ce..835e8e57719 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -333,6 +333,13 @@ "minecraft.world.item.alchemy.PotionMixin_API", "minecraft.world.item.component.FireworkExplosionMixin_API", "minecraft.world.item.component.Tool_RuleMixin_API", + "minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.ConsumeEffect_TypeMixin_API", + "minecraft.world.item.consume_effects.ConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.PlaySoundConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffectMixin_API", + "minecraft.world.item.consume_effects.TeleportRandomlyConsumeEffectMixin_API", "minecraft.world.item.crafting.AbstractCookingRecipeMixin_API", "minecraft.world.item.crafting.CraftingRecipeMixin_API", "minecraft.world.item.crafting.CustomRecipeMixin_API", diff --git a/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java new file mode 100644 index 00000000000..2f228a8f3a5 --- /dev/null +++ b/testplugins/src/main/java/org/spongepowered/test/data/ConsumableDataTest.java @@ -0,0 +1,125 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.test.data; + +import com.google.inject.Inject; +import net.kyori.adventure.text.Component; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.parameter.CommandContext; +import org.spongepowered.api.data.Keys; +import org.spongepowered.api.data.type.ItemAction; +import org.spongepowered.api.effect.potion.PotionEffect; +import org.spongepowered.api.effect.potion.PotionEffectTypes; +import org.spongepowered.api.effect.sound.SoundTypes; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.util.Ticks; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; +import org.spongepowered.test.LoadableModule; + +@Plugin("consumabledata") +public class ConsumableDataTest implements LoadableModule { + + private final PluginContainer plugin; + + @Inject + public ConsumableDataTest(final PluginContainer plugin) { + this.plugin = plugin; + } + + @Override + public void enable(final CommandContext ctx) { + } + + @Listener + public void onRegisterCommand(final RegisterCommandEvent event) { + final Command.Builder builder = Command.builder(); + builder.addChild(Command.builder().executor(this::items).build(), "items"); + builder.addChild(Command.builder().executor(this::applyTeleport).build(), "applyteleport"); + builder.addChild(Command.builder().executor(this::applySound).build(), "applysound"); + event.register(this.plugin, builder.build(), "consumabledata"); + } + + private CommandResult items(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + final ItemStack stack1 = ItemStack.of(ItemTypes.BRICKS); + stack1.offer(Keys.CUSTOM_NAME, Component.text("Remove slowness, get speed & regeneration")); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.playSound(SoundTypes.BLOCK_ANVIL_BREAK)); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.teleportRandomly(5)); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.removeEffects(PotionEffectTypes.SLOWNESS)); + stack1.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.applyEffects( + PotionEffect.of(PotionEffectTypes.SPEED, 1, Ticks.of(20 * 30)), + PotionEffect.of(PotionEffectTypes.REGENERATION, 0, Ticks.of(20 * 30)) + )); + + final ItemStack stack2 = ItemStack.of(ItemTypes.CHORUS_FRUIT); + stack2.offer(Keys.CUSTOM_NAME, Component.text("Remove all effects, get slowness & haste with 50% chance")); + stack2.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.clearEffects()); + stack2.offerSingle(Keys.CONSUME_ACTIONS, ItemAction.applyEffects(0.5, + PotionEffect.of(PotionEffectTypes.SLOWNESS, 1, Ticks.of(20 * 10)), + PotionEffect.of(PotionEffectTypes.HASTE, 0, Ticks.of(20 * 10)) + )); + + final ItemStack stack3 = ItemStack.of(ItemTypes.TOTEM_OF_UNDYING); + stack3.offer(Keys.CUSTOM_NAME, Component.text("No death protection")); + stack3.remove(Keys.DEATH_PROTECTION_ACTIONS); + + final ItemStack stack4 = ItemStack.of(ItemTypes.ANVIL); + stack4.offer(Keys.CUSTOM_NAME, Component.text("Teleport on death")); + stack4.offerSingle(Keys.DEATH_PROTECTION_ACTIONS, ItemAction.teleportRandomly(20)); + + player.inventory().offer(stack1, stack2, stack3, stack4); + return CommandResult.success(); + } + + private CommandResult applyTeleport(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + ItemAction.teleportRandomly(20).apply(player); + return CommandResult.success(); + } + + private CommandResult applySound(final CommandContext commandContext) { + final ServerPlayer player = commandContext.cause().first(ServerPlayer.class).orElse(null); + if (player == null) { + return CommandResult.error(Component.text("Must be run ingame by a player")); + } + + ItemAction.playSound(SoundTypes.BLOCK_BELL_USE).apply(player); + return CommandResult.success(); + } +} diff --git a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java index 8a2fa01995b..be7a3bb5f18 100644 --- a/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/data/DataTest.java @@ -239,7 +239,6 @@ public void testData(final ServerPlayer player) { PotionEffect.builder().potionType(PotionEffectTypes.RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), PotionEffect.builder().potionType(PotionEffectTypes.FIRE_RESISTANCE).amplifier(0).ambient(false).duration(Ticks.of(6000)).build(), PotionEffect.builder().potionType(PotionEffectTypes.ABSORPTION).amplifier(3).ambient(false).duration(Ticks.of(2400)).build()); - this.checkGetWeightedData(goldenApple, Keys.APPLICABLE_POTION_EFFECTS, notchAppleEffects); this.checkOfferListData(goldenApple, Keys.APPLIED_ENCHANTMENTS, Arrays.asList(Enchantment.of(EnchantmentTypes.SHARPNESS, 5))); this.checkOfferListData(goldenApple, Keys.APPLIED_ENCHANTMENTS, Arrays.asList(Enchantment.of(EnchantmentTypes.PROTECTION, 4))); diff --git a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json index 8af3eb43009..9390048f78c 100644 --- a/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json +++ b/testplugins/src/main/resource-templates/META-INF/sponge_plugins.json @@ -377,6 +377,12 @@ "name": "Decorated Pot Data", "entrypoint": "org.spongepowered.test.data.PotDataTest", "description": "Decorated Pot Data" + }, + { + "id": "consumabledata", + "name": "Consumable ItemStack Data", + "entrypoint": "org.spongepowered.test.data.ConsumableDataTest", + "description": "Consumable ItemStack Data" } ] }