From 7a98acedbd584acdb2147937653c2cd1ddf112c4 Mon Sep 17 00:00:00 2001 From: MATRIX-feather Date: Tue, 31 Oct 2023 17:28:37 +0800 Subject: [PATCH] =?UTF-8?q?misc:=20=E7=A7=BB=E5=8A=A8=E4=BC=AA=E8=A3=85?= =?UTF-8?q?=E9=97=B2=E7=BD=AE=E9=9F=B3=E5=A4=84=E7=90=86=E5=88=B0DisguiseS?= =?UTF-8?q?tate=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/xiamomc/morph/MorphManager.java | 2 + .../morph/backends/DisguiseWrapper.java | 23 ++-- .../morph/backends/fallback/NilWrapper.java | 7 +- .../libsdisg/LibsDisguiseWrapper.java | 80 +---------- .../morph/events/CommonEventProcessor.java | 2 +- .../xiamomc/morph/misc/DisguiseState.java | 125 +++++++++++++++++- .../morph/skills/MorphSkillHandler.java | 2 +- 7 files changed, 138 insertions(+), 103 deletions(-) diff --git a/src/main/java/xiamomc/morph/MorphManager.java b/src/main/java/xiamomc/morph/MorphManager.java index 902d2657..d17ea099 100644 --- a/src/main/java/xiamomc/morph/MorphManager.java +++ b/src/main/java/xiamomc/morph/MorphManager.java @@ -183,6 +183,8 @@ private void update() unMorph(nilCommandSource, p, true, true); } + + i.getSoundHandler().update(); }); } diff --git a/src/main/java/xiamomc/morph/backends/DisguiseWrapper.java b/src/main/java/xiamomc/morph/backends/DisguiseWrapper.java index 95747f51..d2b27526 100644 --- a/src/main/java/xiamomc/morph/backends/DisguiseWrapper.java +++ b/src/main/java/xiamomc/morph/backends/DisguiseWrapper.java @@ -11,7 +11,6 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; -import org.bukkit.util.BoundingBox; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import xiamomc.morph.misc.CollisionBoxRecord; @@ -20,13 +19,13 @@ /** * A wrapper that holds the underlying disguise instance - * @param Type of the disguise instance + * @param Type of the disguise instance */ -public abstract class DisguiseWrapper +public abstract class DisguiseWrapper { - protected T instance; + protected TInstance instance; - public DisguiseWrapper(@NotNull T instance, DisguiseBackend> backend) + public DisguiseWrapper(@NotNull TInstance instance, DisguiseBackend> backend) { this.instance = instance; this.backend = backend; @@ -36,14 +35,14 @@ public DisguiseWrapper(@NotNull T instance, DisguiseBackend> backend; + private final DisguiseBackend> backend; - public DisguiseBackend> getBackend() + public DisguiseBackend> getBackend() { return backend; } @@ -76,13 +75,13 @@ public T getInstance() * Clone the underlying disguise instance * @return A new instance cloned from the underlying disguise */ - public abstract T copyInstance(); + public abstract TInstance copyInstance(); /** * Clone this wrapper * @return A new wrapper cloned from this instance, everything in the new instance should not have any reference with this wrapper */ - public abstract DisguiseWrapper clone(); + public abstract DisguiseWrapper clone(); /** * 返回此伪装的名称 @@ -196,7 +195,7 @@ public EntityDimensions getDimensions() : dimensions; } - protected abstract boolean isBaby(); + public abstract boolean isBaby(); protected float getSlimeDimensionScale() { @@ -292,8 +291,6 @@ public void dispose() //region Temp - public abstract void resetAmbientSoundInterval(); - public void showArms(boolean showarms) { } diff --git a/src/main/java/xiamomc/morph/backends/fallback/NilWrapper.java b/src/main/java/xiamomc/morph/backends/fallback/NilWrapper.java index d0d053c9..d837ad11 100644 --- a/src/main/java/xiamomc/morph/backends/fallback/NilWrapper.java +++ b/src/main/java/xiamomc/morph/backends/fallback/NilWrapper.java @@ -59,11 +59,6 @@ public int getNetworkEntityId() return -1; } - @Override - public void resetAmbientSoundInterval() - { - } - @Nullable @Override public R getTag(@NotNull String path, TagType type) @@ -143,7 +138,7 @@ public void setDisguiseName(String name) } @Override - protected boolean isBaby() + public boolean isBaby() { return instance.isBaby; } diff --git a/src/main/java/xiamomc/morph/backends/libsdisg/LibsDisguiseWrapper.java b/src/main/java/xiamomc/morph/backends/libsdisg/LibsDisguiseWrapper.java index 9096f78e..c3bb5c0b 100644 --- a/src/main/java/xiamomc/morph/backends/libsdisg/LibsDisguiseWrapper.java +++ b/src/main/java/xiamomc/morph/backends/libsdisg/LibsDisguiseWrapper.java @@ -49,7 +49,6 @@ public LibsDisguiseWrapper(@NotNull Disguise instance, LibsBackend backend) var config = depMgr.get(MorphConfigManager.class, true); if (config == null) return; - soundFrequency = MathUtils.clamp(0, 2, config.getBindable(Double.class, ConfigOption.AMBIENT_FREQUENCY).get()); } private final FlagWatcher watcher; @@ -94,10 +93,6 @@ public DisguiseWrapper clone() var newWrapper = new LibsDisguiseWrapper(instance.clone(), (LibsBackend) getBackend()); newWrapper.compoundTag.merge(this.compoundTag); - newWrapper.ambientInterval = this.ambientInterval; - newWrapper.ambientSoundPrimary = this.ambientSoundPrimary; - newWrapper.ambientSoundSecondary = this.ambientSoundSecondary; - return newWrapper; } @@ -126,7 +121,7 @@ public void setDisguiseName(String name) private boolean isBaby; @Override - protected boolean isBaby() + public boolean isBaby() { return isBaby; } @@ -230,52 +225,16 @@ public void onPostConstructDisguise(DisguiseState state, @Nullable Entity target } instance.setKeepDisguiseOnPlayerDeath(true); - - initializeSounds(); - } - - private void initializeSounds() - { - var entityType = getEntityType(); - var soundEvent = EntityTypeUtils.getSoundEvent(entityType); - - var sound = soundEvent.sound(); - if (sound == null) return; - - this.ambientInterval = soundEvent.interval(); - var pitch = isBaby() ? 1.5F : 1F; - - this.ambientSoundPrimary = SoundUtils.toBukkitSound(soundEvent, pitch); - - if (entityType == EntityType.ALLAY) - { - var allaySecondary = SoundEvents.ALLAY_AMBIENT_WITH_ITEM; - var secSi = new EntityTypeUtils.SoundInfo(allaySecondary, SoundSource.NEUTRAL, ambientInterval, soundEvent.volume()); - this.ambientSoundSecondary = SoundUtils.toBukkitSound(secSi, pitch); - } } private final Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); public BiConsumer preUpdate; - public int ambientInterval = 0; - public Sound ambientSoundPrimary; - public Sound ambientSoundSecondary; - private int soundTime; - - @Override - public void resetAmbientSoundInterval() - { - soundTime = 0; - } - private final Random random = new Random(); private net.minecraft.world.entity.player.Player nmsPlayer; - private double soundFrequency = 0D; - @Override public void update(boolean isClone, DisguiseState state, Player player) { @@ -293,42 +252,6 @@ public void update(boolean isClone, DisguiseState state, Player player) if (preUpdate != null) preUpdate.accept(watcher, player); - soundTime++; - - // Java中浮点数除以0是正或负无穷 - // 因为soundFrequency永远大于等于0,而分子是1,因此frequencyScale的最大值是正无穷 - // 除非soundTime最后也加到了大于等于正无穷,否则不需要额外的判断,但这真的会发生吗( - double frequencyScale = 1.0D / soundFrequency; - - //logger.info("Sound: %s <-- %s(%s) --> %s".formatted(soundTime, frequency, soundFrequency, ambientInterval * frequency)); - if (ambientInterval != 0 && soundTime >= ambientInterval * frequencyScale && !player.isSneaking()) - { - var loc = player.getLocation(); - boolean playSecondary = false; - - if (getEntityType() == EntityType.ALLAY) - { - var eq = player.getEquipment(); - if (!eq.getItemInMainHand().getType().isAir()) playSecondary = true; - } - - Sound sound = playSecondary ? ambientSoundSecondary : ambientSoundPrimary; - - var isSpectator = nmsPlayer.isSpectator(); - - // 和原版行为保持一致, 并且不要为旁观者播放音效: - // net.minecraft.world.entity.Mob#baseTick() - if (isSpectator) - { - soundTime = -(int)(ambientInterval * frequencyScale); - } - else if (sound != null && random.nextInt((int)(1000 * frequencyScale)) < soundTime) - { - soundTime = -(int)(ambientInterval * frequencyScale); - player.getWorld().playSound(sound, loc.getX(), loc.getY(), loc.getZ()); - } - } - //对克隆的伪装手动更新一些属性 if (!isClone) return; @@ -371,7 +294,6 @@ else if (sound != null && random.nextInt((int)(1000 * frequencyScale)) < soundTi private void invalidateCompound() { this.tagValid = false; - MorphPlugin.getInstance().schedule(this::initializeSounds); } @Override diff --git a/src/main/java/xiamomc/morph/events/CommonEventProcessor.java b/src/main/java/xiamomc/morph/events/CommonEventProcessor.java index f45a67f2..6e0c4f4b 100644 --- a/src/main/java/xiamomc/morph/events/CommonEventProcessor.java +++ b/src/main/java/xiamomc/morph/events/CommonEventProcessor.java @@ -143,7 +143,7 @@ public void onPlayerTookDamage(EntityDamageEvent e) if (state != null) { - state.getDisguiseWrapper().resetAmbientSoundInterval(); + state.getSoundHandler().resetAmbientSoundInterval(); //如果伤害是0,那么取消事件 if (e.getDamage() > 0d) diff --git a/src/main/java/xiamomc/morph/misc/DisguiseState.java b/src/main/java/xiamomc/morph/misc/DisguiseState.java index 66d3bf2c..9b3a8ed0 100644 --- a/src/main/java/xiamomc/morph/misc/DisguiseState.java +++ b/src/main/java/xiamomc/morph/misc/DisguiseState.java @@ -2,8 +2,11 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.world.entity.Entity; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -32,11 +35,15 @@ import xiamomc.morph.skills.SkillType; import xiamomc.morph.skills.impl.NoneMorphSkill; import xiamomc.morph.storage.playerdata.PlayerMeta; +import xiamomc.morph.utilities.EntityTypeUtils; import xiamomc.morph.utilities.ItemUtils; +import xiamomc.morph.utilities.MathUtils; +import xiamomc.morph.utilities.SoundUtils; import xiamomc.pluginbase.Annotations.Resolved; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.UUID; import static xiamomc.morph.utilities.DisguiseUtils.itemOrAir; @@ -54,6 +61,8 @@ public DisguiseState(Player player, @NotNull String id, @NotNull String skillId, this.playerOptions = playerOptions; this.morphConfiguration = playerMeta; + this.soundHandler = new SoundHandler(player); + this.setDisguise(id, skillId, disguiseInstance, isClone, targetEquipment); } @@ -408,9 +417,6 @@ public boolean shouldHandlePose() return shouldHandlePose; } - @Resolved(shouldSolveImmediately = true) - private AbilityHandler abilityHandler; - @Resolved(shouldSolveImmediately = true) private MorphSkillHandler skillHandler; @@ -511,6 +517,9 @@ public void setDisguise(@NotNull String identifier, @NotNull String skillIdentif //伪装类型是否支持设置伪装物品 supportsDisguisedItems = skillHandler.hasSpeficSkill(skillIdentifier, SkillType.INVENTORY); + //设置声音 + this.soundHandler.refreshSounds(getEntityType(), wrapper.isBaby()); + //重置伪装物品 if (shouldRefreshDisguiseItems) { @@ -633,6 +642,116 @@ public boolean toggleDisguisedItems() private final ItemStack[] emptyArmorStack = new ItemStack[]{ null, null, null, null }; + //region Sound Handling + + private final SoundHandler soundHandler; + + public SoundHandler getSoundHandler() + { + return soundHandler; + } + + public static class SoundHandler + { + public int ambientInterval = 0; + public Sound ambientSoundPrimary; + public Sound ambientSoundSecondary; + private int soundTime; + private double soundFrequency = 0D; + + public void resetAmbientSoundInterval() + { + soundTime = 0; + } + + private final Player bindingPlayer; + + @Nullable + private EntityType entityType; + + @NotNull + private EntityType getEntityType() + { + return entityType == null ? EntityType.PLAYER : entityType; + } + + public SoundHandler(Player bindingPlayer) + { + this.bindingPlayer = bindingPlayer; + } + + public void update() + { + soundTime++; + + // Java中浮点数除以0是正或负无穷 + // 因为soundFrequency永远大于等于0,而分子是1,因此frequencyScale的最大值是正无穷 + // 除非soundTime最后也加到了大于等于正无穷,否则不需要额外的判断,但这真的会发生吗( + double frequencyScale = 1.0D / soundFrequency; + + //logger.info("Sound: %s <-- %s(%s) --> %s".formatted(soundTime, frequency, soundFrequency, ambientInterval * frequency)); + if (ambientInterval != 0 && soundTime >= ambientInterval * frequencyScale && !bindingPlayer.isSneaking()) + { + var loc = bindingPlayer.getLocation(); + boolean playSecondary = false; + + if (getEntityType() == EntityType.ALLAY) + { + var eq = bindingPlayer.getEquipment(); + if (!eq.getItemInMainHand().getType().isAir()) playSecondary = true; + } + + Sound sound = playSecondary ? ambientSoundSecondary : ambientSoundPrimary; + + var nmsPlayer = NmsRecord.ofPlayer(bindingPlayer); + var isSpectator = nmsPlayer.isSpectator(); + + // 和原版行为保持一致, 并且不要为旁观者播放音效: + // net.minecraft.world.entity.Mob#baseTick() + if (isSpectator) + { + soundTime = -(int)(ambientInterval * frequencyScale); + } + else if (sound != null && random.nextInt((int)(1000 * frequencyScale)) < soundTime) + { + soundTime = -(int)(ambientInterval * frequencyScale); + bindingPlayer.getWorld().playSound(sound, loc.getX(), loc.getY(), loc.getZ()); + } + } + } + + private final Random random = new Random(); + + private final MorphConfigManager config = MorphConfigManager.getInstance(); + + public void refreshSounds(EntityType entityType, boolean isBaby) + { + this.entityType = entityType; + + soundFrequency = MathUtils.clamp(0, 2, config.getBindable(Double.class, ConfigOption.AMBIENT_FREQUENCY).get()); + + var soundEvent = EntityTypeUtils.getSoundEvent(entityType); + + var sound = soundEvent.sound(); + if (sound == null) return; + + this.ambientInterval = soundEvent.interval(); + var pitch = isBaby ? 1.5F : 1F; + + this.ambientSoundPrimary = SoundUtils.toBukkitSound(soundEvent, pitch); + + if (entityType == EntityType.ALLAY) + { + var allaySecondary = SoundEvents.ALLAY_AMBIENT_WITH_ITEM; + var secSi = new EntityTypeUtils.SoundInfo(allaySecondary, SoundSource.NEUTRAL, ambientInterval, soundEvent.volume()); + this.ambientSoundSecondary = SoundUtils.toBukkitSound(secSi, pitch); + } + } + + } + + //endregion Sound Handling + /** * 更新伪装物品显示 * @param showDisguised 是否显示默认盔甲 diff --git a/src/main/java/xiamomc/morph/skills/MorphSkillHandler.java b/src/main/java/xiamomc/morph/skills/MorphSkillHandler.java index da605fcd..2fc6a464 100644 --- a/src/main/java/xiamomc/morph/skills/MorphSkillHandler.java +++ b/src/main/java/xiamomc/morph/skills/MorphSkillHandler.java @@ -243,7 +243,7 @@ public void executeDisguiseSkill(Player player, boolean bypassPermission) var cd = skill.executeSkillGeneric(player, state, config, option); cdInfo.setLastInvoke(plugin.getCurrentTick()); - state.getDisguiseWrapper().resetAmbientSoundInterval(); + state.getSoundHandler().resetAmbientSoundInterval(); if (!state.haveCooldown()) state.setCooldownInfo(cdInfo); else state.setSkillCooldown(cd);