From 211aa0733ba6d054c163080538a8ed0945362d28 Mon Sep 17 00:00:00 2001 From: Dustin Norberg Date: Wed, 23 Sep 2026 15:20:07 -0400 Subject: [PATCH] Mute Immersive Portals preview world audio --- gradle.properties | 2 +- ...sivePortalsDestinationPreviewRenderer.java | 7 +++ .../ImmersivePortalsPreviewAudioGuard.java | 31 ++++++++++ .../mixin/client/ClientLevelSoundMixin.java | 59 +++++++++++++++++++ src/main/resources/rivencraft.mixins.json | 1 + 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java create mode 100644 src/main/java/net/dnorberg/rivencraft/mixin/client/ClientLevelSoundMixin.java diff --git a/gradle.properties b/gradle.properties index 51425c2..afa5fbe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -35,7 +35,7 @@ mod_name=Rivencraft # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=LGPL-3.0-or-later # The mod version. Rivencraft uses the x.y.z.b policy documented in README.md. -mod_version=0.3.2.1 +mod_version=0.3.2.2 immersive_portals_version=6.0.7 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. diff --git a/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsDestinationPreviewRenderer.java b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsDestinationPreviewRenderer.java index 0a4c246..39c2265 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsDestinationPreviewRenderer.java +++ b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsDestinationPreviewRenderer.java @@ -42,7 +42,11 @@ public final class ImmersivePortalsDestinationPreviewRenderer implements Destina @Override public void accept(LinkPreviewPayload payload) { + if (destination != null) { + ImmersivePortalsPreviewAudioGuard.clear(destination.dimension()); + } destination = payload; + ImmersivePortalsPreviewAudioGuard.mute(payload.dimension()); resetView(); } @@ -234,5 +238,8 @@ public final class ImmersivePortalsDestinationPreviewRenderer implements Destina public void close() { clearMovement(); hasCompletedFrame = false; + if (destination != null) { + ImmersivePortalsPreviewAudioGuard.clear(destination.dimension()); + } } } diff --git a/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java new file mode 100644 index 0000000..ab9f3d9 --- /dev/null +++ b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java @@ -0,0 +1,31 @@ +package net.dnorberg.rivencraft.client.preview; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; + +/** Prevents an Immersive Portals preview world from contributing sounds to a book screen. */ +public final class ImmersivePortalsPreviewAudioGuard { + private static ResourceKey mutedDimension; + + private ImmersivePortalsPreviewAudioGuard() { + } + + public static void mute(ResourceKey dimension) { + mutedDimension = dimension; + } + + public static void clear(ResourceKey dimension) { + if (dimension.equals(mutedDimension)) { + mutedDimension = null; + } + } + + public static boolean shouldMute(ClientLevel level) { + Minecraft minecraft = Minecraft.getInstance(); + return mutedDimension != null + && level.dimension().equals(mutedDimension) + && (minecraft.player == null || level != minecraft.player.level()); + } +} diff --git a/src/main/java/net/dnorberg/rivencraft/mixin/client/ClientLevelSoundMixin.java b/src/main/java/net/dnorberg/rivencraft/mixin/client/ClientLevelSoundMixin.java new file mode 100644 index 0000000..a2a05d0 --- /dev/null +++ b/src/main/java/net/dnorberg/rivencraft/mixin/client/ClientLevelSoundMixin.java @@ -0,0 +1,59 @@ +package net.dnorberg.rivencraft.mixin.client; + +import net.dnorberg.rivencraft.client.preview.ImmersivePortalsPreviewAudioGuard; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.Holder; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** Mutes only the remote client world displayed by a Rivencraft book preview. */ +@Mixin(value = ClientLevel.class, priority = 2000) +public abstract class ClientLevelSoundMixin { + @Inject( + method = "playSound(DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FFZJ)V", + at = @At("HEAD"), + cancellable = true + ) + private void rivencraft$mutePreviewPositionSound( + double x, double y, double z, SoundEvent sound, SoundSource source, + float volume, float pitch, boolean distanceDelay, long seed, CallbackInfo callback + ) { + rivencraft$cancelPreviewSound(callback); + } + + @Inject( + method = "playLocalSound(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V", + at = @At("HEAD"), + cancellable = true + ) + private void rivencraft$mutePreviewLocalEntitySound( + Entity entity, SoundEvent sound, SoundSource source, float volume, float pitch, + CallbackInfo callback + ) { + rivencraft$cancelPreviewSound(callback); + } + + @Inject( + method = "playSeededSound(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/Holder;Lnet/minecraft/sounds/SoundSource;FFJ)V", + at = @At("HEAD"), + cancellable = true + ) + private void rivencraft$mutePreviewSeededEntitySound( + Player player, Entity entity, Holder sound, SoundSource source, + float volume, float pitch, long seed, CallbackInfo callback + ) { + rivencraft$cancelPreviewSound(callback); + } + + private void rivencraft$cancelPreviewSound(CallbackInfo callback) { + if (ImmersivePortalsPreviewAudioGuard.shouldMute((ClientLevel)(Object)this)) { + callback.cancel(); + } + } +} diff --git a/src/main/resources/rivencraft.mixins.json b/src/main/resources/rivencraft.mixins.json index 5962154..0a02386 100644 --- a/src/main/resources/rivencraft.mixins.json +++ b/src/main/resources/rivencraft.mixins.json @@ -4,6 +4,7 @@ "package": "net.dnorberg.rivencraft.mixin", "compatibilityLevel": "JAVA_21", "client": [ + "client.ClientLevelSoundMixin", "client.LevelRendererMixin" ], "injectors": {