From f5deb8a823bb00d29ccd2f81e84b9c3a3bbaf8f4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Jan 2026 03:54:19 +0000 Subject: [PATCH] Fix Bard music restarting/duplicating when opening dialogs Two issues were causing the bug: 1. GuiDialogInteract.close() called stopAllSounds() unconditionally, which stopped Bard music even when the dialog had no sound or when a different Bard was playing nearby. 2. MusicController.stopMusic() didn't set playDelay, allowing Bards to immediately restart their music after dialog close. Changes: - MusicController.stopMusic() now sets playDelay=20 and clears entity reference to prevent immediate music restart - Added MusicController.stopSound(key) to stop specific sounds - Dialog GUIs now track their dialog sound and only stop that on close, preserving Bard music and other sounds --- .../client/controllers/MusicController.java | 24 +++++++++++++++++++ .../client/gui/player/GuiDialogInteract.java | 17 ++++++++++++- .../modern/GuiModernDialogInteract.java | 16 +++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/main/java/noppes/npcs/client/controllers/MusicController.java b/src/main/java/noppes/npcs/client/controllers/MusicController.java index fc2d9369b..98c30f2ac 100644 --- a/src/main/java/noppes/npcs/client/controllers/MusicController.java +++ b/src/main/java/noppes/npcs/client/controllers/MusicController.java @@ -66,6 +66,8 @@ public class MusicController { this.playingSound.stopSound(); this.sounds.remove(this.playingSound.sound); this.playingSound = null; + this.entity = null; + this.playDelay = 20; // Prevent immediate restart when music is stopped } else if (soundHandler != null) { try { soundHandler.stopSounds(); @@ -193,4 +195,26 @@ public class MusicController { } this.sounds.clear(); } + + /** + * Stops a specific sound by its resource key. + * This is used to stop dialog sounds without affecting Bard music. + * @param soundKey The sound resource key to stop + */ + public void stopSound(String soundKey) { + if (soundKey == null || soundKey.isEmpty()) { + return; + } + ScriptClientSound sound = this.sounds.remove(soundKey); + if (sound != null) { + SoundHandler soundHandler = Minecraft.getMinecraft().getSoundHandler(); + if (soundHandler != null) { + try { + soundHandler.stopSound(sound); + } catch (Exception ignored) { + } + } + sound.stopSound(); + } + } } diff --git a/src/main/java/noppes/npcs/client/gui/player/GuiDialogInteract.java b/src/main/java/noppes/npcs/client/gui/player/GuiDialogInteract.java index a49db2873..728649f6d 100644 --- a/src/main/java/noppes/npcs/client/gui/player/GuiDialogInteract.java +++ b/src/main/java/noppes/npcs/client/gui/player/GuiDialogInteract.java @@ -75,6 +75,12 @@ public class GuiDialogInteract extends GuiNPCInterface implements IGuiClose { */ private boolean sentClosePacket = false; + /** + * Tracks the dialog sound that was played, so we can stop only this sound + * on close without affecting Bard music or other sounds. + */ + private String dialogSound = null; + public GuiDialogInteract(EntityNPCInterface npc, Dialog dialog) { super(npc); this.dialog = dialog; @@ -671,8 +677,13 @@ public class GuiDialogInteract extends GuiNPCInterface implements IGuiClose { this.options = new ArrayList(); if (dialog.sound != null && !dialog.sound.isEmpty()) { + // Stop any previous dialog sound before playing new one + if (this.dialogSound != null) { + MusicController.Instance.stopSound(this.dialogSound); + } MusicController.Instance.stopMusic(); MusicController.Instance.playSound(dialog.sound, (float) npc.posX, (float) npc.posY, (float) npc.posZ); + this.dialogSound = dialog.sound; } if (!dialog.showPreviousBlocks) { @@ -707,7 +718,11 @@ public class GuiDialogInteract extends GuiNPCInterface implements IGuiClose { super.close(); if (parent != null) NoppesUtil.openGUI(player, parent); - MusicController.Instance.stopAllSounds(); + // Only stop the dialog sound, not Bard music or other sounds + if (this.dialogSound != null) { + MusicController.Instance.stopSound(this.dialogSound); + this.dialogSound = null; + } } @Override diff --git a/src/main/java/noppes/npcs/client/gui/player/modern/GuiModernDialogInteract.java b/src/main/java/noppes/npcs/client/gui/player/modern/GuiModernDialogInteract.java index fc4a221c7..3f382d98c 100644 --- a/src/main/java/noppes/npcs/client/gui/player/modern/GuiModernDialogInteract.java +++ b/src/main/java/noppes/npcs/client/gui/player/modern/GuiModernDialogInteract.java @@ -63,6 +63,12 @@ public class GuiModernDialogInteract extends GuiNPCInterface implements IGuiClos */ private boolean sentClosePacket = false; + /** + * Tracks the dialog sound that was played, so we can stop only this sound + * on close without affecting Bard music or other sounds. + */ + private String dialogSound = null; + public GuiModernDialogInteract(EntityNPCInterface npc, Dialog dialog) { super(npc); this.dialog = dialog; @@ -380,8 +386,13 @@ public class GuiModernDialogInteract extends GuiNPCInterface implements IGuiClos this.options = new ArrayList(); if (dialog.sound != null && !dialog.sound.isEmpty()) { + // Stop any previous dialog sound before playing new one + if (this.dialogSound != null) { + MusicController.Instance.stopSound(this.dialogSound); + } MusicController.Instance.stopMusic(); MusicController.Instance.playSound(dialog.sound, (float) npc.posX, (float) npc.posY, (float) npc.posZ); + this.dialogSound = dialog.sound; } if (!dialog.showPreviousBlocks) { @@ -440,6 +451,11 @@ public class GuiModernDialogInteract extends GuiNPCInterface implements IGuiClos } closed(); } + // Only stop the dialog sound, not Bard music or other sounds + if (this.dialogSound != null) { + MusicController.Instance.stopSound(this.dialogSound); + this.dialogSound = null; + } super.onGuiClosed(); } }