mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 23:19:15 +00:00
改进totem指令
This commit is contained in:
@@ -30,10 +30,12 @@ import org.incendo.cloud.bukkit.parser.selector.MultiplePlayerSelectorParser;
|
|||||||
import org.incendo.cloud.context.CommandContext;
|
import org.incendo.cloud.context.CommandContext;
|
||||||
import org.incendo.cloud.context.CommandInput;
|
import org.incendo.cloud.context.CommandInput;
|
||||||
import org.incendo.cloud.parser.flag.CommandFlag;
|
import org.incendo.cloud.parser.flag.CommandFlag;
|
||||||
|
import org.incendo.cloud.parser.standard.FloatParser;
|
||||||
import org.incendo.cloud.suggestion.Suggestion;
|
import org.incendo.cloud.suggestion.Suggestion;
|
||||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
|
public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
|
||||||
@@ -46,6 +48,7 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
|
|||||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||||
return builder
|
return builder
|
||||||
.flag(FlagKeys.SILENT_FLAG)
|
.flag(FlagKeys.SILENT_FLAG)
|
||||||
|
.flag(CommandFlag.builder("no-sound"))
|
||||||
.required("players", MultiplePlayerSelectorParser.multiplePlayerSelectorParser())
|
.required("players", MultiplePlayerSelectorParser.multiplePlayerSelectorParser())
|
||||||
.required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
|
.required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -53,7 +56,16 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
|
|||||||
return CompletableFuture.completedFuture(plugin().itemManager().cachedTotemSuggestions());
|
return CompletableFuture.completedFuture(plugin().itemManager().cachedTotemSuggestions());
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.flag(CommandFlag.builder("sound").withComponent(NamespacedKeyParser.namespacedKeyParser()).build())
|
.optional("sound", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
|
||||||
|
@Override
|
||||||
|
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
|
||||||
|
return CompletableFuture.completedFuture(plugin().soundManager().cachedSoundSuggestions());
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.optional("volume", FloatParser.floatParser(0f))
|
||||||
|
.optional("pitch", FloatParser.floatParser(0f, 2f))
|
||||||
|
.optional("min-volume", FloatParser.floatParser(0f))
|
||||||
|
.optional("min-pitch", FloatParser.floatParser(0f, 2f))
|
||||||
.handler(context -> {
|
.handler(context -> {
|
||||||
NamespacedKey namespacedKey = context.get("id");
|
NamespacedKey namespacedKey = context.get("id");
|
||||||
Key key = Key.of(namespacedKey.namespace(), namespacedKey.value());
|
Key key = Key.of(namespacedKey.namespace(), namespacedKey.value());
|
||||||
@@ -62,6 +74,16 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
|
|||||||
handleFeedback(context, MessageConstants.COMMAND_TOTEM_NOT_TOTEM, Component.text(key.toString()));
|
handleFeedback(context, MessageConstants.COMMAND_TOTEM_NOT_TOTEM, Component.text(key.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Optional<NamespacedKey> soundKey = context.optional("sound");
|
||||||
|
SoundData soundData = null;
|
||||||
|
if (soundKey.isPresent()) {
|
||||||
|
float volume = context.getOrDefault("volume", 1.0f);
|
||||||
|
float pitch = context.getOrDefault("pitch", 1.0f);
|
||||||
|
float minVolume = context.getOrDefault("min-volume", 1.0f);
|
||||||
|
float minPitch = context.getOrDefault("min-pitch", 1.0f);
|
||||||
|
soundData = SoundData.of(KeyUtils.namespacedKey2Key(soundKey.get()), SoundData.SoundValue.ranged(minVolume, volume), SoundData.SoundValue.ranged(minPitch, pitch));
|
||||||
|
}
|
||||||
|
boolean removeSound = context.flags().hasFlag("no-sound");
|
||||||
MultiplePlayerSelector selector = context.get("players");
|
MultiplePlayerSelector selector = context.get("players");
|
||||||
for (Player player : selector.values()) {
|
for (Player player : selector.values()) {
|
||||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
|
||||||
@@ -69,13 +91,11 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
|
|||||||
if (VersionHelper.isOrAbove1_21_2()) {
|
if (VersionHelper.isOrAbove1_21_2()) {
|
||||||
item.setJavaComponent(ComponentTypes.DEATH_PROTECTION, Map.of());
|
item.setJavaComponent(ComponentTypes.DEATH_PROTECTION, Map.of());
|
||||||
}
|
}
|
||||||
NamespacedKey soundKey = context.flags().get("sound");
|
// TODO 存在第一次进服 未正确移除图腾声音的问题
|
||||||
SoundData soundData = null;
|
PlayerUtils.sendTotemAnimation(serverPlayer, item, soundData, removeSound);
|
||||||
if (soundKey != null) {
|
|
||||||
soundData = SoundData.of(KeyUtils.namespacedKey2Key(soundKey), SoundData.SoundValue.FIXED_1, SoundData.SoundValue.FIXED_1);
|
|
||||||
}
|
|
||||||
PlayerUtils.sendTotemAnimation(serverPlayer, item, soundData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 消息提示
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.util;
|
|||||||
|
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||||
|
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
@@ -56,15 +57,19 @@ public final class PlayerUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendTotemAnimation(Player player, Item<ItemStack> totem, @Nullable SoundData sound) {
|
public static void sendTotemAnimation(Player player, Item<ItemStack> totem, @Nullable SoundData sound, boolean removeSound) {
|
||||||
List<Object> packets = new ArrayList<>();
|
List<Object> packets = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Object totemItem = totem.getLiteralObject();
|
Object totemItem = totem.getLiteralObject();
|
||||||
Item<?> previousMainHandItem = player.getItemInHand(InteractionHand.MAIN_HAND);
|
Item<?> previousMainHandItem = player.getItemInHand(InteractionHand.MAIN_HAND);
|
||||||
boolean flag = previousMainHandItem.id().equals(ItemKeys.TOTEM_OF_UNDYING);
|
boolean isMainHandTotem;
|
||||||
|
if (VersionHelper.isOrAbove1_21_2()) {
|
||||||
|
isMainHandTotem = previousMainHandItem.hasComponent(ComponentTypes.DEATH_PROTECTION);
|
||||||
|
} else {
|
||||||
|
isMainHandTotem = previousMainHandItem.id().equals(ItemKeys.TOTEM_OF_UNDYING);
|
||||||
|
}
|
||||||
Object previousOffHandItem = player.getItemInHand(InteractionHand.OFF_HAND).getLiteralObject();
|
Object previousOffHandItem = player.getItemInHand(InteractionHand.OFF_HAND).getLiteralObject();
|
||||||
|
if (isMainHandTotem) {
|
||||||
if (flag) {
|
|
||||||
packets.add(NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(
|
packets.add(NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(
|
||||||
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$MAINHAND, BukkitItemManager.instance().uniqueEmptyItem().item().getLiteralObject()))
|
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$MAINHAND, BukkitItemManager.instance().uniqueEmptyItem().item().getLiteralObject()))
|
||||||
));
|
));
|
||||||
@@ -73,7 +78,7 @@ public final class PlayerUtils {
|
|||||||
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$OFFHAND, totemItem))
|
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$OFFHAND, totemItem))
|
||||||
));
|
));
|
||||||
packets.add(NetworkReflections.constructor$ClientboundEntityEventPacket.newInstance(player.serverPlayer(), (byte) 35));
|
packets.add(NetworkReflections.constructor$ClientboundEntityEventPacket.newInstance(player.serverPlayer(), (byte) 35));
|
||||||
if (flag) {
|
if (isMainHandTotem) {
|
||||||
packets.add(NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(
|
packets.add(NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(
|
||||||
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$MAINHAND, previousMainHandItem.getLiteralObject()))
|
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$MAINHAND, previousMainHandItem.getLiteralObject()))
|
||||||
));
|
));
|
||||||
@@ -81,12 +86,13 @@ public final class PlayerUtils {
|
|||||||
packets.add(NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(
|
packets.add(NetworkReflections.constructor$ClientboundSetEquipmentPacket.newInstance(
|
||||||
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$OFFHAND, previousOffHandItem))
|
player.entityID(), List.of(Pair.of(CoreReflections.instance$EquipmentSlot$OFFHAND, previousOffHandItem))
|
||||||
));
|
));
|
||||||
|
if (sound != null || removeSound) {
|
||||||
if (sound != null) {
|
|
||||||
packets.add(NetworkReflections.constructor$ClientboundStopSoundPacket.newInstance(
|
packets.add(NetworkReflections.constructor$ClientboundStopSoundPacket.newInstance(
|
||||||
FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "item.totem.use"),
|
FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "item.totem.use"),
|
||||||
CoreReflections.instance$SoundSource$PLAYERS
|
CoreReflections.instance$SoundSource$PLAYERS
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
if (sound != null) {
|
||||||
packets.add(FastNMS.INSTANCE.constructor$ClientboundSoundPacket(
|
packets.add(FastNMS.INSTANCE.constructor$ClientboundSoundPacket(
|
||||||
FastNMS.INSTANCE.method$Holder$direct(FastNMS.INSTANCE.constructor$SoundEvent(KeyUtils.toResourceLocation(sound.id()), Optional.empty())),
|
FastNMS.INSTANCE.method$Holder$direct(FastNMS.INSTANCE.constructor$SoundEvent(KeyUtils.toResourceLocation(sound.id()), Optional.empty())),
|
||||||
CoreReflections.instance$SoundSource$PLAYERS,
|
CoreReflections.instance$SoundSource$PLAYERS,
|
||||||
@@ -94,7 +100,6 @@ public final class PlayerUtils {
|
|||||||
RandomUtils.generateRandomLong()
|
RandomUtils.generateRandomLong()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendPackets(packets, false);
|
player.sendPackets(packets, false);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
BukkitCraftEngine.instance().logger().warn("Failed to send totem animation");
|
BukkitCraftEngine.instance().logger().warn("Failed to send totem animation");
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ public abstract class CraftEngine implements Plugin {
|
|||||||
// collect illegal characters from minecraft:default font
|
// collect illegal characters from minecraft:default font
|
||||||
this.fontManager.delayedLoad();
|
this.fontManager.delayedLoad();
|
||||||
this.advancementManager.delayedLoad();
|
this.advancementManager.delayedLoad();
|
||||||
|
this.soundManager.delayedLoad();
|
||||||
if (reloadRecipe) {
|
if (reloadRecipe) {
|
||||||
// convert data pack recipes
|
// convert data pack recipes
|
||||||
this.recipeManager.delayedLoad();
|
this.recipeManager.delayedLoad();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
|||||||
import net.momirealms.craftengine.core.plugin.config.IdSectionConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.IdSectionConfigParser;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.*;
|
import net.momirealms.craftengine.core.util.*;
|
||||||
|
import org.incendo.cloud.suggestion.Suggestion;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -21,6 +22,7 @@ public abstract class AbstractSoundManager implements SoundManager {
|
|||||||
protected final SoundParser soundParser;
|
protected final SoundParser soundParser;
|
||||||
protected final SongParser songParser;
|
protected final SongParser songParser;
|
||||||
protected final Map<Integer, Key> customSoundsInRegistry = new HashMap<>();
|
protected final Map<Integer, Key> customSoundsInRegistry = new HashMap<>();
|
||||||
|
protected final List<Suggestion> soundSuggestions = new ArrayList<>();
|
||||||
|
|
||||||
public AbstractSoundManager(CraftEngine plugin) {
|
public AbstractSoundManager(CraftEngine plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -43,6 +45,22 @@ public abstract class AbstractSoundManager implements SoundManager {
|
|||||||
this.byId.clear();
|
this.byId.clear();
|
||||||
this.byNamespace.clear();
|
this.byNamespace.clear();
|
||||||
this.songs.clear();
|
this.songs.clear();
|
||||||
|
this.soundSuggestions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayedLoad() {
|
||||||
|
for (Key key : VANILLA_SOUND_EVENTS) {
|
||||||
|
this.soundSuggestions.add(Suggestion.suggestion(key.asString()));
|
||||||
|
}
|
||||||
|
for (Key key : this.byId.keySet()) {
|
||||||
|
this.soundSuggestions.add(Suggestion.suggestion(key.asString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Suggestion> cachedSoundSuggestions() {
|
||||||
|
return this.soundSuggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ public record SoundData(Key id, SoundValue volume, SoundValue pitch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SoundValue ranged(float min, float max) {
|
static SoundValue ranged(float min, float max) {
|
||||||
|
if (min > max) {
|
||||||
|
return new Ranged(max, min);
|
||||||
|
} else if (min == max) {
|
||||||
|
return SoundValue.fixed(max);
|
||||||
|
}
|
||||||
return new Ranged(min, max);
|
return new Ranged(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package net.momirealms.craftengine.core.sound;
|
|||||||
import net.momirealms.craftengine.core.plugin.Manageable;
|
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import org.incendo.cloud.suggestion.Suggestion;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface SoundManager extends Manageable {
|
public interface SoundManager extends Manageable {
|
||||||
@@ -12,5 +14,7 @@ public interface SoundManager extends Manageable {
|
|||||||
|
|
||||||
ConfigParser[] parsers();
|
ConfigParser[] parsers();
|
||||||
|
|
||||||
|
List<Suggestion> cachedSoundSuggestions();
|
||||||
|
|
||||||
Map<Key, SoundEvent> sounds();
|
Map<Key, SoundEvent> sounds();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user