diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 5384d3146..434f60d70 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -34,6 +34,7 @@ import net.momirealms.craftengine.core.plugin.context.CooldownData; import net.momirealms.craftengine.core.plugin.locale.TranslationManager; import net.momirealms.craftengine.core.plugin.network.ConnectionState; import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler; +import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.sound.SoundSource; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.*; @@ -1278,4 +1279,9 @@ public class BukkitServerPlayer extends Player { public void setExperienceLevels(int level) { platformPlayer().setLevel(level); } + + @Override + public void sendTotemAnimation(Item totem, @Nullable SoundData sound, boolean removeSound) { + PlayerUtils.sendTotemAnimation(this, totem, sound, removeSound); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/PlayerUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/PlayerUtils.java index 82b9b8113..c20d195b9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/PlayerUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/PlayerUtils.java @@ -57,7 +57,7 @@ public final class PlayerUtils { } } - public static void sendTotemAnimation(Player player, Item totem, @Nullable SoundData sound, boolean removeSound) { + public static void sendTotemAnimation(Player player, Item totem, @Nullable SoundData sound, boolean removeSound) { List packets = new ArrayList<>(); try { Object totemItem = totem.getLiteralObject(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index 507def94d..260b935f5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -194,6 +194,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract void setExperienceLevels(int level); + public abstract void sendTotemAnimation(Item totem, @Nullable SoundData sound, boolean removeSound); + @Override public void remove() { } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java index 1b94eb8c6..fbc8a4e69 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java @@ -57,6 +57,7 @@ public class EventFunctions { register(CommonFunctions.CYCLE_BLOCK_PROPERTY, new CycleBlockPropertyFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.SET_EXP, new SetExpFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.SET_LEVEL, new SetLevelFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.PLAY_TOTEM_ANIMATION, new PlayTotemAnimationFunction.FactoryImpl<>(EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java index a49c1f6e9..937534105 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java @@ -48,4 +48,5 @@ public final class CommonFunctions { public static final Key CYCLE_BLOCK_PROPERTY = Key.of("craftengine:cycle_block_property"); public static final Key SET_EXP = Key.of("craftengine:set_exp"); public static final Key SET_LEVEL = Key.of("craftengine:set_level"); + public static final Key PLAY_TOTEM_ANIMATION = Key.of("craftengine:play_totem_animation"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlayTotemAnimationFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlayTotemAnimationFunction.java new file mode 100644 index 000000000..4d167a9d5 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlayTotemAnimationFunction.java @@ -0,0 +1,103 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.DataComponentKeys; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors; +import net.momirealms.craftengine.core.sound.SoundData; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class PlayTotemAnimationFunction extends AbstractConditionalFunction { + private final PlayerSelector selector; + private final Key item; + @Nullable + private final Key sound; + private final float volume; + private final float pitch; + private final float minVolume; + private final float minPitch; + private final boolean noSound; + + public PlayTotemAnimationFunction( + List> predicates, + PlayerSelector selector, + Key item, + @Nullable Key sound, + float volume, + float pitch, + float minVolume, + float minPitch, + boolean noSound + ) { + super(predicates); + this.selector = selector; + this.item = item; + this.sound = sound; + this.volume = volume; + this.pitch = pitch; + this.minVolume = minVolume; + this.minPitch = minPitch; + this.noSound = noSound; + } + + @Override + protected void runInternal(CTX ctx) { + CustomItem customItem = CraftEngine.instance().itemManager().getCustomItem(this.item).orElse(null); + if (customItem == null) { + return; + } + SoundData soundData = null; + if (this.sound != null) { + soundData = SoundData.of( + this.sound, + SoundData.SoundValue.ranged(this.minVolume, this.volume), + SoundData.SoundValue.ranged(this.minPitch, this.pitch) + ); + } + for (Player player : this.selector.get(ctx)) { + Item buildItem = customItem.buildItem(player); + if (VersionHelper.isOrAbove1_21_2()) { + buildItem.setJavaComponent(DataComponentKeys.DEATH_PROTECTION, Map.of()); + } + player.sendTotemAnimation(buildItem, soundData, this.noSound); + } + } + + @Override + public Key type() { + return CommonFunctions.PLAY_TOTEM_ANIMATION; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + PlayerSelector selector = PlayerSelectors.fromObject(arguments.getOrDefault("target", "self"), conditionFactory()); + Key item = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.function.play_totem_animation.missing_item")); + @Nullable Key sound = Optional.ofNullable(arguments.get("sound")).map(String::valueOf).map(Key::of).orElse(null); + float volume = Math.max(ResourceConfigUtils.getAsFloat(arguments.getOrDefault("volume", 1f), "volume"), 0f); + float pitch = MiscUtils.clamp(ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 1f), "pitch"), 0f, 2f); + float minVolume = Math.max(ResourceConfigUtils.getAsFloat(arguments.getOrDefault("min-volume", 1f), "min-volume"), 0f); + float minPitch = MiscUtils.clamp(ResourceConfigUtils.getAsFloat(arguments.getOrDefault("min-pitch", 1f), "min-pitch"), 0f, 2f); + boolean noSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("no-sound", false), "no-sound"); + return new PlayTotemAnimationFunction<>(getPredicates(arguments), selector, item, sound, volume, pitch, minVolume, minPitch, noSound); + } + } +}