add immersive portals support

This commit is contained in:
Michael Harvey
2025-12-20 00:27:37 +01:00
committed by Acuadragon100
parent 40040294e7
commit e65b1e2dfc
25 changed files with 195 additions and 71 deletions
@@ -0,0 +1,92 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.DhLogger;
/**
* Runtime detection and compatibility handling for Immersive Portals
*/
public class ImmersivePortalsCompat
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static volatile Boolean isImmersivePortalsPresent = null;
private static volatile Boolean isImmersivePortalsActive = null;
/**
* Check if Immersive Portals is present in the mod environment
*/
public static boolean isImmersivePortalsPresent()
{
if (isImmersivePortalsPresent == null)
{
synchronized (ImmersivePortalsCompat.class)
{
if (isImmersivePortalsPresent == null)
{
try
{
// Try to load an Immersive Portals class
Class.forName("qouteall.imm_ptl.core.IPMcHelper");
isImmersivePortalsPresent = true;
LOGGER.info("Immersive Portals detected - enabling compatibility features");
}
catch (ClassNotFoundException e)
{
isImmersivePortalsPresent = false;
LOGGER.debug("Immersive Portals not detected - using standard level management");
}
}
}
}
return isImmersivePortalsPresent;
}
/**
* Check if Immersive Portals compatibility should be active
* This checks both presence and configuration
*/
public static boolean isImmersivePortalsActive()
{
if (isImmersivePortalsActive == null)
{
synchronized (ImmersivePortalsCompat.class)
{
if (isImmersivePortalsActive == null)
{
// TODO: Add configuration check here
isImmersivePortalsActive = isImmersivePortalsPresent();
}
}
}
return isImmersivePortalsActive;
}
/**
* Reset detection cache (useful for testing)
*/
public static void resetDetection()
{
isImmersivePortalsPresent = null;
isImmersivePortalsActive = null;
}
}
@@ -6,6 +6,7 @@ import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.*;
@@ -79,9 +80,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper
private boolean cloudColorFailLogged = false;
private BlockStateWrapper dirtBlockWrapper;
private IDhLevel dhLevel;
private volatile BlockStateWrapper dirtBlockWrapper;
private volatile IDhLevel dhLevel;
private volatile long lastRenderTime = System.currentTimeMillis();
//=============//
@@ -100,6 +101,55 @@ public class ClientLevelWrapper implements IClientLevelWrapper
//==================//
//region
public synchronized void markRendered() {
this.lastRenderTime = System.currentTimeMillis();
}
public long getLastRenderTime() { return this.lastRenderTime; }
public boolean isDhLevelLoaded() {
return this.dhLevel != null;
}
public static void tickCleanup()
{
if (MINECRAFT.level == null) { return; }
long currentTime = System.currentTimeMillis();
long timeout = 30 * 1000;
java.util.List<ClientLevelWrapper> toUnload = new java.util.ArrayList<>();
synchronized(LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL)
{
for (java.lang.ref.WeakReference<ClientLevelWrapper> ref : LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.values())
{
ClientLevelWrapper wrapper = ref.get();
if (wrapper != null && wrapper.isDhLevelLoaded() && wrapper.level != MINECRAFT.level)
{
if (currentTime - wrapper.getLastRenderTime() > timeout)
{
toUnload.add(wrapper);
}
}
}
}
for (ClientLevelWrapper wrapper : toUnload)
{
// Re-verify all conditions inside a synchronized block on the wrapper
// to ensure atomicity with respect to markRendered()
synchronized(wrapper)
{
if (wrapper.isDhLevelLoaded() && wrapper.level != MINECRAFT.level && currentTime - wrapper.getLastRenderTime() > timeout)
{
LOGGER.debug("Unloading level " + wrapper.getDhIdentifier() + " due to inactivity");
ClientApi.INSTANCE.clientLevelUnloadEvent(wrapper);
}
}
}
}
/**
* can be used when speed is important and the same level is likely to be passed in,
* IE rendering.
@@ -62,7 +62,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
private static final Map<ServerLevel, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
private final ServerLevel level;
private IDhLevel dhLevel;
private volatile IDhLevel dhLevel;
/**
* this name is cached to prevent issues during shutdown where
+1 -22
View File
@@ -43,28 +43,7 @@ dependencies {
addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
// Canvas
addMod("io.vram:canvas-fabric-${rootProject.canvas_version}", rootProject.enable_canvas)
// Immersive Portals
if (rootProject.enable_immersive_portals == "1") {
modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}")
}
else if (rootProject.enable_immersive_portals == "2") {
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
api("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4")
annotationProcessor("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4")
}
addMod("io.vram:canvas-fabric-${project.canvas_version}", rootProject.enable_canvas)
}
@@ -171,6 +171,23 @@ public class MixinLevelRenderer
ClientApi.RENDER_STATE.partialTickTime = MinecraftRenderWrapper.INSTANCE.getPartialTickTime();
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
if (ClientApi.RENDER_STATE.clientLevelWrapper instanceof ClientLevelWrapper)
{
ClientLevelWrapper wrapper = (ClientLevelWrapper) ClientApi.RENDER_STATE.clientLevelWrapper;
// Apply Immersive Portals compatibility only when IP is detected
if (com.seibel.distanthorizons.common.ImmersivePortalsCompat.isImmersivePortalsActive())
{
if (!wrapper.isDhLevelLoaded())
{
LOGGER.debug("IP detected - On-demand loading level " + wrapper.getDhIdentifier() + " during rendering");
ClientApi.INSTANCE.clientLevelLoadEvent(wrapper);
}
}
wrapper.markRendered();
}
#if MC_VER < MC_1_21_6
@@ -196,6 +213,11 @@ public class MixinLevelRenderer
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrix);
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.level);
if (ClientApi.RENDER_STATE.clientLevelWrapper instanceof ClientLevelWrapper)
{
((ClientLevelWrapper) ClientApi.RENDER_STATE.clientLevelWrapper).markRendered();
}
// only crash during development
if (ModInfo.IS_DEV_BUILD)
{
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.fabric.mixins.client;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
@@ -91,7 +92,12 @@ public class MixinLightTexture
return;
}
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
IClientLevelWrapper clientLevel = ClientApi.RENDER_STATE.clientLevelWrapper;
if (clientLevel == null)
{
clientLevel = mc.getWrappedClientLevel();
}
if (clientLevel == null)
{
return;
@@ -102,20 +102,31 @@ public abstract class MixinMinecraft
@Inject(at = @At("HEAD"), method = "updateLevelInEngines")
public void updateLevelInEngines(ClientLevel level, CallbackInfo ci)
{
if (this.lastLevel != null && level != this.lastLevel)
// Skip normal level events when Immersive Portals is active
// IP suppresses these events and we use render-driven loading instead
if (!com.seibel.distanthorizons.common.ImmersivePortalsCompat.isImmersivePortalsActive())
{
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.lastLevel));
if (this.lastLevel != null && level != this.lastLevel)
{
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.lastLevel));
}
if (level != null)
{
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level, true));
}
}
if (level != null)
{
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level, true));
}
this.lastLevel = level;
}
@Inject(at = @At("HEAD"), method = "close()V")
public void close(CallbackInfo ci) { SelfUpdater.onClose(); }
@Inject(at = @At("HEAD"), method = "tick")
private void onTick(CallbackInfo ci)
{
ClientLevelWrapper.tickCleanup();
}
}
-2
View File
@@ -25,7 +25,6 @@ fabric_api_version=0.42.0+1.16
sodium_version=mc1.16.5-0.2.0
iris_version=1.4.4+1.16.5
bclib_version=
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -44,7 +43,6 @@ fabric_api_version=0.42.0+1.16
enable_iris=1
# not available via github, use curse.maven if necessary
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -25,7 +25,6 @@ fabric_api_version=0.46.1+1.17
sodium_version=mc1.17.1-0.3.4
iris_version=1.17.x-v1.2.7
bclib_version=0.5.5
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -43,7 +42,6 @@ fabric_api_version=0.46.1+1.17
enable_sodium=1
enable_iris=0
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -26,7 +26,6 @@ fabric_api_version=0.76.0+1.18.2
sodium_version=mc1.18.2-0.4.1
iris_version=1.6.10+1.18.2
bclib_version=1.4.6
immersive_portals_version=v1.4.11-1.18
canvas_version=mc118:1.0.2616
# iris - needs 1.7.4+ to support the DH API
@@ -44,7 +43,6 @@ fabric_api_version=0.76.0+1.18.2
enable_lithium=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
quilt_loader_version=0.19.1
-2
View File
@@ -24,7 +24,6 @@ fabric_api_version=0.76.1+1.19.2
sodium_version=mc1.19.2-0.4.4
iris_version=1.6.10+1.19.2
bclib_version=2.1.6
immersive_portals_version=
canvas_version=mc119-1.0.2480
# iris - needs 1.7.4+ to support the DH API
@@ -42,7 +41,6 @@ fabric_api_version=0.76.1+1.19.2
enable_lithium=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.87.1+1.19.4
sodium_version=mc1.19.4-0.4.10
iris_version=1.6.10+1.19.4
bclib_version=2.3.3
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -41,7 +40,6 @@ fabric_api_version=0.87.1+1.19.4
enable_lithium=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.92.6+1.20.1
sodium_version=mc1.20.1-0.5.3
iris_version=1.6.10+1.20.1
bclib_version=3.0.13
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -41,7 +40,6 @@ fabric_api_version=0.92.6+1.20.1
enable_lithium=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.90.4+1.20.2
sodium_version=mc1.20.2-0.5.3
iris_version=1.6.10+1.20.2
bclib_version=3.0.13
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -41,7 +40,6 @@ fabric_api_version=0.90.4+1.20.2
enable_lithium=0
enable_iris=1
enable_bclib=1
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -24,7 +24,6 @@ fabric_api_version=0.91.2+1.20.4
sodium_version=mc1.20.3-0.5.4
iris_version=1.6.13+1.20.4
bclib_version=
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -42,7 +41,6 @@ fabric_api_version=0.91.2+1.20.4
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# Forge loader
-2
View File
@@ -24,7 +24,6 @@ fabric_api_version=0.97.8+1.20.6
sodium_version=mc1.20.6-0.5.8
iris_version=1.7.0+1.20.6
bclib_version=
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -42,7 +41,6 @@ fabric_api_version=0.97.8+1.20.6
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -24,7 +24,6 @@ fabric_api_version=0.116.11+1.21.1
sodium_version=mc1.21.1-0.6.2-fabric
iris_version=1.8.1+1.21.1-fabric
bclib_version=
immersive_portals_version=
canvas_version=
# iris - needs 1.7.4+ to support the DH API
@@ -42,7 +41,6 @@ fabric_api_version=0.116.11+1.21.1
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.138.4+1.21.10
sodium_version=mc1.21.10-0.7.2-fabric
iris_version=1.9.6+1.21.10-fabric
bclib_version=
immersive_portals_version=
canvas_version=
fabric_incompatibility_list={ }
@@ -40,7 +39,6 @@ fabric_api_version=0.138.4+1.21.10
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.139.4+1.21.11
sodium_version=mc1.21.11-0.8.0-fabric
iris_version=1.10.0+1.21.11-fabric
bclib_version=
immersive_portals_version=
canvas_version=
fabric_incompatibility_list={ }
@@ -40,7 +39,6 @@ fabric_api_version=0.139.4+1.21.11
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -24,7 +24,6 @@ fabric_api_version=0.110.0+1.21.3
sodium_version=mc1.21.3-0.6.0-fabric
iris_version=1.8.0+1.21.3-fabric
bclib_version=
immersive_portals_version=
canvas_version=
# fabric-api 0.110.0 fixed a bug in MC 1.21.3 with the rendering API DH relied on
@@ -42,7 +41,6 @@ fabric_api_version=0.110.0+1.21.3
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -24,7 +24,6 @@ fabric_api_version=0.110.5+1.21.4
sodium_version=mc1.21.4-0.6.2-fabric
iris_version=1.8.2+1.21.4-fabric
bclib_version=
immersive_portals_version=
canvas_version=
fabric_incompatibility_list={ }
@@ -41,7 +40,6 @@ fabric_api_version=0.110.5+1.21.4
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.119.5+1.21.5
sodium_version=mc1.21.5-0.6.11-fabric
iris_version=1.8.10+1.21.5-fabric
bclib_version=
immersive_portals_version=
canvas_version=
# Iris - some versions of 1.8.11 nightly builds may not work, but the ones after 2025-03-30 should
@@ -41,7 +40,6 @@ fabric_api_version=0.119.5+1.21.5
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.127.0+1.21.6
sodium_version=mc1.21.6-0.6.13-fabric
iris_version=1.9.0+1.21.6-fabric
bclib_version=
immersive_portals_version=
canvas_version=
fabric_incompatibility_list={ }
@@ -40,7 +39,6 @@ fabric_api_version=0.127.0+1.21.6
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.133.4+1.21.8
sodium_version=mc1.21.6-0.6.13-fabric
iris_version=1.9.1+1.21.7-fabric
bclib_version=
immersive_portals_version=
canvas_version=
fabric_incompatibility_list={ }
@@ -40,7 +39,6 @@ fabric_api_version=0.133.4+1.21.8
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader
-2
View File
@@ -23,7 +23,6 @@ fabric_api_version=0.134.0+1.21.9
sodium_version=mc1.21.10-0.7.2-fabric
iris_version=1.9.3+1.21.9-fabric
bclib_version=
immersive_portals_version=
canvas_version=
fabric_incompatibility_list={ }
@@ -40,7 +39,6 @@ fabric_api_version=0.134.0+1.21.9
enable_lithium=0
enable_iris=1
enable_bclib=0
enable_immersive_portals=0
enable_canvas=0
# NeoForge loader