diff --git a/gradle.properties b/gradle.properties index afa5fbe..c8fbf7e 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.2 +mod_version=0.3.2.3 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 39c2265..c9a5e88 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsDestinationPreviewRenderer.java +++ b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsDestinationPreviewRenderer.java @@ -122,6 +122,7 @@ public final class ImmersivePortalsDestinationPreviewRenderer implements Destina FRAMEBUFFER.clear(true); minecraft.getMainRenderTarget().bindWrite(true); MyRenderHelper.restoreViewPort(); + ImmersivePortalsPreviewAudioGuard.markCameraRestorePending(); GuiPortalRendering.submitNextFrameRendering(info, FRAMEBUFFER); hasCompletedFrame = true; graphics.renderOutline(left, top, width, height, exploring ? 0xFFE0C36A : 0xFF7B6AA8); diff --git a/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java index ab9f3d9..9783229 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java +++ b/src/main/java/net/dnorberg/rivencraft/client/preview/ImmersivePortalsPreviewAudioGuard.java @@ -1,6 +1,7 @@ package net.dnorberg.rivencraft.client.preview; import net.minecraft.client.Minecraft; +import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -8,6 +9,7 @@ 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 static boolean cameraRestorePending; private ImmersivePortalsPreviewAudioGuard() { } @@ -28,4 +30,33 @@ public final class ImmersivePortalsPreviewAudioGuard { && level.dimension().equals(mutedDimension) && (minecraft.player == null || level != minecraft.player.level()); } + + public static void markCameraRestorePending() { + cameraRestorePending = true; + } + + /** + * Immersive Portals' GUI renderer leaves the shared main camera in the + * remote world after its end-of-frame render. Restore it before the next + * frame uses that camera for rain effects and the sound listener. + */ + public static void restorePlayerCamera() { + Minecraft minecraft = Minecraft.getInstance(); + if (!cameraRestorePending) { + return; + } + cameraRestorePending = false; + if (minecraft.level == null || minecraft.getCameraEntity() == null) { + return; + } + + Camera camera = minecraft.gameRenderer.getMainCamera(); + camera.setup( + minecraft.level, + minecraft.getCameraEntity(), + !minecraft.options.getCameraType().isFirstPerson(), + minecraft.options.getCameraType().isMirrored(), + camera.getPartialTickTime() + ); + } } diff --git a/src/main/java/net/dnorberg/rivencraft/mixin/client/ImmersivePortalsGuiRenderingMixin.java b/src/main/java/net/dnorberg/rivencraft/mixin/client/ImmersivePortalsGuiRenderingMixin.java new file mode 100644 index 0000000..4bf1b26 --- /dev/null +++ b/src/main/java/net/dnorberg/rivencraft/mixin/client/ImmersivePortalsGuiRenderingMixin.java @@ -0,0 +1,18 @@ +package net.dnorberg.rivencraft.mixin.client; + +import net.dnorberg.rivencraft.client.preview.ImmersivePortalsPreviewAudioGuard; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** Restores the player camera after Immersive Portals finishes GUI-world rendering. */ +@Pseudo +@Mixin(targets = "qouteall.imm_ptl.core.render.GuiPortalRendering", remap = false) +public abstract class ImmersivePortalsGuiRenderingMixin { + @Inject(method = "_onGameRenderEnd", at = @At("RETURN"), remap = false) + private static void rivencraft$restorePlayerCamera(CallbackInfo callback) { + ImmersivePortalsPreviewAudioGuard.restorePlayerCamera(); + } +} diff --git a/src/main/resources/rivencraft.mixins.json b/src/main/resources/rivencraft.mixins.json index 0a02386..f785152 100644 --- a/src/main/resources/rivencraft.mixins.json +++ b/src/main/resources/rivencraft.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_21", "client": [ "client.ClientLevelSoundMixin", + "client.ImmersivePortalsGuiRenderingMixin", "client.LevelRendererMixin" ], "injectors": {