Merge branch 'immersivePortals'
Thanks Acuadragon100!
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
package com.seibel.distanthorizons.common.commonMixins;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.modAccessor.AbstractImmersivePortalsAccessorCommon;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class MixinImmersivePortalsRenderStatesCommon
|
||||
{
|
||||
/**
|
||||
* Used to access variables that will change when rendering
|
||||
* different levels with Immersive Portals
|
||||
* (ie player/camera position level reference)
|
||||
* but that we only want for the loaded level.
|
||||
*/
|
||||
public static void saveVolatileOriginals()
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
AbstractImmersivePortalsAccessorCommon.actualLevel = mc.level;
|
||||
|
||||
|
||||
// clear everything if the player is missing
|
||||
// (ie the world hasn't loaded yet)
|
||||
if (mc.player == null)
|
||||
{
|
||||
AbstractImmersivePortalsAccessorCommon.actualBlockPos = null;
|
||||
AbstractImmersivePortalsAccessorCommon.actualChunkPos = null;
|
||||
AbstractImmersivePortalsAccessorCommon.actualCameraPos = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// player block pos
|
||||
BlockPos playerBlockPos = mc.player.blockPosition();
|
||||
AbstractImmersivePortalsAccessorCommon.actualBlockPos = new DhBlockPos(playerBlockPos.getX(), playerBlockPos.getY(), playerBlockPos.getZ());
|
||||
|
||||
// player chunk pos
|
||||
#if MC_VER < MC_1_17_1
|
||||
ChunkPos playerChunkPos = new ChunkPos(mc.player.blockPosition());
|
||||
#else
|
||||
ChunkPos playerChunkPos = mc.player.chunkPosition();
|
||||
#endif
|
||||
AbstractImmersivePortalsAccessorCommon.actualChunkPos = McObjectConverter.Convert(playerChunkPos);
|
||||
|
||||
// camera pos
|
||||
#if MC_VER <= MC_1_21_10
|
||||
Vec3 cameraPos = mc.gameRenderer.getMainCamera().getPosition();
|
||||
#else
|
||||
Vec3 cameraPos = mc.gameRenderer.getMainCamera().position();
|
||||
#endif
|
||||
AbstractImmersivePortalsAccessorCommon.actualCameraPos = new Vec3d(cameraPos.x(), cameraPos.y(), cameraPos.z());
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
+18
@@ -7,6 +7,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -26,6 +27,7 @@ import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_3
|
||||
@@ -50,6 +52,11 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#else
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
import net.minecraft.client.renderer.fog.FogData;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -104,6 +111,15 @@ public class MixinVanillaFogCommon
|
||||
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
|
||||
|
||||
|
||||
// since DH won't render through immersive portals
|
||||
// the vanilla fog should be enabled
|
||||
IImmersivePortalsAccessor immersivePortals = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
|
||||
if (immersivePortals != null
|
||||
&& immersivePortals.isRenderingPortal())
|
||||
{
|
||||
cancelFog = false;
|
||||
}
|
||||
|
||||
return cancelFog;
|
||||
}
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@@ -124,4 +140,6 @@ public class MixinVanillaFogCommon
|
||||
|
||||
return cameraNotInFluid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+135
-16
@@ -1,5 +1,6 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.level;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
@@ -8,17 +9,27 @@ import net.minecraft.client.multiplayer.WorldClient;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
#endif
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class KeyedClientLevelManager implements IKeyedClientLevelManager
|
||||
{
|
||||
public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager();
|
||||
|
||||
/** This is set and managed by the ClientApi for servers with support for DH. */
|
||||
@Nullable
|
||||
private IServerKeyedClientLevel serverKeyedLevel = null;
|
||||
/** Stores the server-provided keys indexed by dimension name for persistence. */
|
||||
private final Map<String, KeyInfo> keysByDimensionName = new ConcurrentHashMap<>();
|
||||
|
||||
/** Cache for already keyed level wrappers to maintain object identity. */
|
||||
private final Map<#if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif, IServerKeyedClientLevel>
|
||||
keyedLevelsCache = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
/** Allows to keep level manager enabled between loading different keyed levels */
|
||||
private boolean enabled = false;
|
||||
private volatile boolean enabled = false;
|
||||
|
||||
|
||||
|
||||
@@ -41,32 +52,140 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public IServerKeyedClientLevel getServerKeyedLevel() { return this.serverKeyedLevel; }
|
||||
public IServerKeyedClientLevel getServerKeyedLevel()
|
||||
{
|
||||
#if MC_VER > MC_1_12_2
|
||||
return this.getServerKeyedLevel(Minecraft.getInstance().level);
|
||||
#else
|
||||
return this.getServerKeyedLevel(Minecraft.getMinecraft().world);
|
||||
#endif
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IServerKeyedClientLevel getServerKeyedLevel(@Nullable #if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif level)
|
||||
{
|
||||
if (level == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// We synchronize on the cache map to ensure atomicity of the lookup-and-populate sequence.
|
||||
// This prevents multiple threads from creating duplicate wrappers for the same level.
|
||||
synchronized (this.keyedLevelsCache)
|
||||
{
|
||||
// Check the cache first
|
||||
IServerKeyedClientLevel cached = this.keyedLevelsCache.get(level);
|
||||
if (cached != null)
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Determine the dimension name for this level
|
||||
// We use bypassLevelKeyManager=true to avoid recursion back into this manager
|
||||
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level, true);
|
||||
if (wrappedLevel == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String dimensionName = wrappedLevel.getDimensionName();
|
||||
KeyInfo info = this.keysByDimensionName.get(dimensionName);
|
||||
if (info == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create and cache a new keyed wrapper
|
||||
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevelWrapper(level, info.serverKey, info.levelKey);
|
||||
this.keyedLevelsCache.put(level, keyedLevel);
|
||||
return keyedLevel;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String serverKey, String levelKey)
|
||||
{
|
||||
IServerKeyedClientLevel keyedLevel;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
keyedLevel = new ServerKeyedClientLevelWrapper((WorldClient) clientLevel.getWrappedMcObject(), serverKey, levelKey);
|
||||
#else
|
||||
keyedLevel = new ServerKeyedClientLevelWrapper((ClientLevel) clientLevel.getWrappedMcObject(), serverKey, levelKey);
|
||||
#endif
|
||||
// 1. Determine the target dimension name
|
||||
String targetDimensionName = clientLevel.getDimensionName();
|
||||
int separatorIndex = levelKey.lastIndexOf("@");
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
targetDimensionName = levelKey.substring(separatorIndex + 1);
|
||||
}
|
||||
|
||||
this.serverKeyedLevel = keyedLevel;
|
||||
final String finalTargetDimensionName = targetDimensionName;
|
||||
|
||||
// 2. Store the key for this dimension
|
||||
this.keysByDimensionName.put(finalTargetDimensionName, new KeyInfo(serverKey, levelKey));
|
||||
this.enabled = true;
|
||||
return keyedLevel;
|
||||
|
||||
// 3. Clear the cache for this dimension to ensure new wrappers are created with the new key
|
||||
// (though in practice keys shouldn't change mid-session)
|
||||
//
|
||||
// We synchronize manually on the map to ensure atomicity of the compound removal operation
|
||||
// and to prevent race conditions or deadlocks with other threads accessing the map.
|
||||
// We avoid calling ClientLevelWrapper.getWrapper() inside the lock to prevent circular lock dependencies.
|
||||
synchronized (this.keyedLevelsCache)
|
||||
{
|
||||
this.keyedLevelsCache.keySet().removeIf(level ->
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
String levelDim = level.provider.getDimensionType().getName() + ":" + level.provider.getDimension();
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
String levelDim = level.dimension().location().toString();
|
||||
#else
|
||||
String levelDim = level.dimension().identifier().toString();
|
||||
#endif
|
||||
|
||||
return levelDim.equals(finalTargetDimensionName);
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Return the keyed wrapper for whatever level the core passed us,
|
||||
// but only if it matches the dimension we just keyed.
|
||||
return this.getServerKeyedLevel((#if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif) clientLevel.getWrappedMcObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearKeyedLevel() { this.serverKeyedLevel = null; }
|
||||
public void clearKeyedLevel()
|
||||
{
|
||||
synchronized (this.keyedLevelsCache)
|
||||
{
|
||||
this.keyedLevelsCache.clear();
|
||||
this.keysByDimensionName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() { return this.enabled; }
|
||||
|
||||
@Override
|
||||
public void disable() { this.enabled = false; }
|
||||
public void disable()
|
||||
{
|
||||
this.enabled = false;
|
||||
this.clearKeyedLevel();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
private static class KeyInfo
|
||||
{
|
||||
public final String serverKey;
|
||||
public final String levelKey;
|
||||
|
||||
public KeyInfo(String serverKey, String levelKey)
|
||||
{
|
||||
this.serverKey = serverKey;
|
||||
this.levelKey = levelKey;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
#else
|
||||
import net.minecraft.world.WorldServer;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#elif MC_VER > MC_1_12_2
|
||||
import net.minecraft.core.Registry;
|
||||
#endif
|
||||
|
||||
public abstract class AbstractMinecraftSharedWrapper implements IMinecraftSharedWrapper
|
||||
{
|
||||
|
||||
@Nullable
|
||||
protected ResourceKey<Level> deserializeDimensionResourceKey(String dimensionResourceLocation)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
int dimensionID;
|
||||
try
|
||||
{
|
||||
dimensionID = Integer.parseInt(dimensionResourceLocation.substring(dimensionResourceLocation.indexOf(":")+1));
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
#if MC_VER <= MC_1_21_10
|
||||
ResourceLocation dimResourceLocation = ResourceLocation.tryParse(dimensionResourceLocation);
|
||||
#else
|
||||
Identifier dimResourceLocation = Identifier.tryParse(dimensionResourceLocation);
|
||||
#endif
|
||||
if (dimResourceLocation == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
ResourceKey<Level> dimensionKey = ResourceKey.create(Registries.DIMENSION, dimResourceLocation);
|
||||
#else
|
||||
ResourceKey<Level> dimensionKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, dimResourceLocation);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return dimensionKey;
|
||||
}
|
||||
|
||||
}
|
||||
+77
-2
@@ -26,9 +26,13 @@ import com.mojang.blaze3d.platform.Window;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.NativeDialogUtil;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
@@ -48,14 +52,20 @@ import net.minecraft.profiler.Profiler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
#else
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.client.CloudStatus;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
#endif
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -74,13 +84,25 @@ import net.minecraft.client.GraphicsStatus;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#elif MC_VER > MC_1_12_2
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft object.
|
||||
*
|
||||
* @author James Seibel
|
||||
*/
|
||||
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
|
||||
public class MinecraftClientWrapper extends AbstractMinecraftSharedWrapper implements IMinecraftClientWrapper
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
@@ -95,6 +117,12 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
|
||||
private ProfilerWrapper profilerWrapper;
|
||||
|
||||
/** Delayed accessing is necessary since this object will be created before the mod accessors are bound. */
|
||||
private static class DelayedAccessors
|
||||
{
|
||||
public static final IImmersivePortalsAccessor IMMERSIVE_PORTALS = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
@@ -232,6 +260,15 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
return new DhBlockPos(0, 0, 0);
|
||||
}
|
||||
|
||||
if (DelayedAccessors.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
DhBlockPos pos = DelayedAccessors.IMMERSIVE_PORTALS.getActualPlayerBlockPos();
|
||||
if (pos != null)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
BlockPos playerPos = player.getPosition();
|
||||
#else
|
||||
@@ -253,7 +290,16 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
return new DhChunkPos(0, 0);
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (DelayedAccessors.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
DhChunkPos pos = DelayedAccessors.IMMERSIVE_PORTALS.getActualPlayerChunkPos();
|
||||
if (pos != null)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
ChunkPos playerPos = new ChunkPos(player.getPosition());
|
||||
#elif MC_VER < MC_1_17_1
|
||||
ChunkPos playerPos = new ChunkPos(player.blockPosition());
|
||||
@@ -285,6 +331,16 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
@Nullable
|
||||
public IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager)
|
||||
{
|
||||
if (!bypassLevelKeyManager
|
||||
&& DelayedAccessors.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
IClientLevelWrapper level = DelayedAccessors.IMMERSIVE_PORTALS.getActualClientLevelWrapper();
|
||||
if (level != null)
|
||||
{
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldClient level = MINECRAFT.world;
|
||||
#else
|
||||
@@ -583,6 +639,25 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IServerLevelWrapper getWrappedServerLevelWithDimensionResourceLocation(String dimensionResourceLocation)
|
||||
{
|
||||
if (!this.hasSinglePlayerServer())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ResourceKey<Level> dimensionKey = this.deserializeDimensionResourceKey(dimensionResourceLocation);
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldServer mcLevel = MINECRAFT.getIntegratedServer().getWorld(dimensionKey);
|
||||
#else
|
||||
ServerLevel mcLevel = MINECRAFT.getSingleplayerServer().getLevel(dimensionKey);
|
||||
#endif
|
||||
return ServerLevelWrapper.getWrapper(mcLevel);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
+69
-55
@@ -22,6 +22,8 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
import java.awt.Color;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
@@ -30,20 +32,24 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiRenderingApi;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
#elif MC_VER < MC_1_21_3
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
#else
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import net.minecraft.client.renderer.fog.FogData;
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
#endif
|
||||
@@ -60,6 +66,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@@ -101,6 +108,7 @@ import com.mojang.blaze3d.opengl.GlTexture;
|
||||
#else
|
||||
import net.minecraft.world.attribute.EnvironmentAttributes;
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
import org.joml.Vector4f;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -112,6 +120,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
@@ -121,6 +130,12 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
#endif
|
||||
|
||||
/** Delayed accessing is necessary since this object will be created before the mod accessors are bound. */
|
||||
private static class DelayedAccessors
|
||||
{
|
||||
public static final IImmersivePortalsAccessor IMMERSIVE_PORTALS = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
|
||||
* Requiring the use of multiple {@link LightMapWrapper}.
|
||||
@@ -202,6 +217,12 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public Vec3d getCameraExactPosition()
|
||||
{
|
||||
if (DelayedAccessors.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
Vec3d cameraPos = DelayedAccessors.IMMERSIVE_PORTALS.getActualCameraPos();
|
||||
if (cameraPos != null) return cameraPos;
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
RenderManager rm = MC.getRenderManager();
|
||||
return new Vec3d(rm.viewerPosX, rm.viewerPosY, rm.viewerPosZ);
|
||||
@@ -571,9 +592,6 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
|
||||
|
||||
@Override
|
||||
public boolean isFogStateSpecial()
|
||||
{
|
||||
@@ -598,94 +616,90 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// lightmap //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
|
||||
|
||||
/**
|
||||
* It's better to use {@link MinecraftRenderWrapper#setLightmapId(int, IClientLevelWrapper)} if possible,
|
||||
* It's better to use {@link MinecraftRenderWrapper#setLightmapId(int)} if possible,
|
||||
* however old MC versions don't support it.
|
||||
*/
|
||||
#if MC_VER > MC_1_12_2
|
||||
public void updateLightmap(NativeImage lightPixels, IClientLevelWrapper level)
|
||||
public void updateLightmap(NativeImage lightPixels)
|
||||
{
|
||||
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
|
||||
// object for the same MC level and/or the same hash,
|
||||
// so this will have to do for now
|
||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||
IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
|
||||
|
||||
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||
wrapper.uploadLightmap(lightPixels);
|
||||
}
|
||||
#endif
|
||||
|
||||
public void setLightmapId(int tetxureId, IClientLevelWrapper level)
|
||||
public void setLightmapId(int textureId)
|
||||
{
|
||||
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
|
||||
// object for the same MC level and/or the same hash,
|
||||
// so this will have to do for now
|
||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||
IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
|
||||
|
||||
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||
wrapper.setLightmapId(tetxureId);
|
||||
wrapper.setLightmapId(textureId);
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#else
|
||||
public void setLightmapGpuTexture(GpuTexture gpuTexture, IClientLevelWrapper level)
|
||||
public void setLightmapGpuTexture(GpuTexture gpuTexture)
|
||||
{
|
||||
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
|
||||
// object for the same MC level and/or the same hash,
|
||||
// so this will have to do for now
|
||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||
IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
|
||||
|
||||
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||
wrapper.setLightmapGpuTexture(gpuTexture);
|
||||
}
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public float getShade(EDhDirection lodDirection)
|
||||
/** special logic is necessary in order for Immersive Portals to work correctly */
|
||||
private static @Nullable IClientLevelWrapper getLightmapClientLevelWrapper()
|
||||
{
|
||||
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
|
||||
switch (lodShading)
|
||||
IClientLevelWrapper clientLevel = ClientApi.RENDER_STATE.clientLevelWrapper;
|
||||
if (clientLevel == null)
|
||||
{
|
||||
default:
|
||||
case AUTO:
|
||||
#if MC_VER <= MC_1_12_2
|
||||
// 1.12.2 has no getShade, fall through to ENABLED
|
||||
#else
|
||||
if (MC.level != null)
|
||||
{
|
||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||
#if MC_VER <= MC_1_21_11
|
||||
return MC.level.getShade(mcDir, true);
|
||||
#else
|
||||
return MC.level.cardinalLighting().byFace(mcDir);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
case ENABLED:
|
||||
switch (lodDirection)
|
||||
{
|
||||
case DOWN:
|
||||
return 0.5F;
|
||||
default:
|
||||
case UP:
|
||||
return 1.0F;
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
return 0.8F;
|
||||
case WEST:
|
||||
case EAST:
|
||||
return 0.6F;
|
||||
}
|
||||
|
||||
case DISABLED:
|
||||
return 1.0F;
|
||||
clientLevel = MC_CLIENT.getWrappedClientLevel();
|
||||
}
|
||||
|
||||
return clientLevel;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+42
-2
@@ -1,12 +1,34 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
#else
|
||||
import net.minecraft.world.WorldServer;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#elif MC_VER > MC_1_12_2
|
||||
import net.minecraft.core.Registry;
|
||||
#endif
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
||||
public class MinecraftServerWrapper extends AbstractMinecraftSharedWrapper
|
||||
{
|
||||
public static final MinecraftServerWrapper INSTANCE = new MinecraftServerWrapper();
|
||||
|
||||
@@ -64,5 +86,23 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IServerLevelWrapper getWrappedServerLevelWithDimensionResourceLocation(String dimensionResourceLocation)
|
||||
{
|
||||
if (this.dedicatedServer == null)
|
||||
{
|
||||
throw new IllegalStateException("Trying to get the server mcLevel before dedicated server completed initialization!");
|
||||
}
|
||||
|
||||
ResourceKey<Level> dimensionKey = this.deserializeDimensionResourceKey(dimensionResourceLocation);
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldServer mcLevel = dedicatedServer.getWorld(dimensionKey);
|
||||
#else
|
||||
ServerLevel mcLevel = dedicatedServer.getLevel(dimensionKey);
|
||||
#endif
|
||||
return ServerLevelWrapper.getWrapper(mcLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.wrappers.modAccessor;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public abstract class AbstractImmersivePortalsAccessorCommon {}
|
||||
|
||||
#else
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
import org.joml.Matrix4f;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
import java.lang.reflect.Field;
|
||||
#endif
|
||||
|
||||
public abstract class AbstractImmersivePortalsAccessorCommon extends AbstractImmersivePortalsAccessor
|
||||
{
|
||||
// We don't use the fields in RenderStates because they are not volatile.
|
||||
@Nullable
|
||||
public static volatile ClientLevel actualLevel;
|
||||
@Nullable
|
||||
public static volatile DhBlockPos actualBlockPos;
|
||||
@Nullable
|
||||
public static volatile DhChunkPos actualChunkPos;
|
||||
@Nullable
|
||||
public static volatile Vec3d actualCameraPos;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DhBlockPos getActualPlayerBlockPos() { return actualBlockPos; }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DhChunkPos getActualPlayerChunkPos() { return actualChunkPos; }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public IClientLevelWrapper getActualClientLevelWrapper() { return ClientLevelWrapper.getWrapper(actualLevel, false); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Vec3d getActualCameraPos() { return actualCameraPos; }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+178
-21
@@ -1,5 +1,6 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.world;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper;
|
||||
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
|
||||
@@ -9,13 +10,20 @@ import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource;
|
||||
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.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.level.*;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
@@ -32,6 +40,7 @@ import net.minecraft.block.state.IBlockState;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
#endif
|
||||
@@ -44,9 +53,7 @@ import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -80,7 +87,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
private static final Map<
|
||||
#if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif,
|
||||
WeakReference<ClientLevelWrapper>> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
|
||||
private static final KeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = KeyedClientLevelManager.INSTANCE;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final Minecraft MINECRAFT = Minecraft.getMinecraft();
|
||||
@@ -90,6 +97,12 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
|
||||
private static final ThreadLocal<DhBlockPosMutable> MUTABLE_BLOCK_POS_THREAD_LOCAL = ThreadLocal.withInitial(DhBlockPosMutable::new);
|
||||
|
||||
private static final Timer CLIENT_CLEANUP_TIMER = TimerUtil.CreateTimer("ClientLevelTickCleanup");
|
||||
private static final TimerTask CLIENT_CLEANUP_TASK = TimerUtil.createTimerTask(ClientLevelWrapper::tickCleanup);
|
||||
|
||||
/** how long in milliseconds can a level be unused before it's automatically unloaded */
|
||||
private static final long INACTIVE_TIME_BEFORE_UNLOADED_IN_MS = 30 * 1000;
|
||||
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@@ -110,8 +123,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 lastAccessTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
|
||||
@@ -126,11 +140,88 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// instance methods //
|
||||
//==================//
|
||||
//======================//
|
||||
// inactivity unloading //
|
||||
//======================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public synchronized void markAccessed() { this.lastAccessTime = System.currentTimeMillis(); }
|
||||
public synchronized long getLastAccessTime() { return this.lastAccessTime; }
|
||||
|
||||
static
|
||||
{
|
||||
// fire 20 times per second (i.e. 50ms interval)
|
||||
CLIENT_CLEANUP_TIMER.scheduleAtFixedRate(CLIENT_CLEANUP_TASK, 0, 1000 / 20);
|
||||
}
|
||||
|
||||
public static void tickCleanup()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldClient clientLevel = MINECRAFT.world;
|
||||
#else
|
||||
ClientLevel clientLevel = MINECRAFT.level;
|
||||
#endif
|
||||
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
ArrayList<ClientLevelWrapper> levelsToUnload = new ArrayList<>();
|
||||
synchronized(LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL) // should only be run on one thread at a time, but just in case
|
||||
{
|
||||
for (WeakReference<ClientLevelWrapper> ref : LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.values())
|
||||
{
|
||||
ClientLevelWrapper levelWrapper = ref.get();
|
||||
if (levelWrapper != null
|
||||
&& levelWrapper.level != clientLevel)
|
||||
{
|
||||
// We use the synchronized getter to prevent race conditions with markAccessed()
|
||||
long inactiveTimeMs = currentTime - levelWrapper.getLastAccessTime();
|
||||
if (inactiveTimeMs > INACTIVE_TIME_BEFORE_UNLOADED_IN_MS)
|
||||
{
|
||||
levelsToUnload.add(levelWrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ClientLevelWrapper wrapper : levelsToUnload)
|
||||
{
|
||||
// Re-verify all conditions inside a synchronized block on the wrapper
|
||||
// to ensure atomicity with respect to markAccessed()
|
||||
synchronized(wrapper)
|
||||
{
|
||||
long inactiveTimeMs = currentTime - wrapper.getLastAccessTime();
|
||||
if (wrapper.level != clientLevel
|
||||
&& inactiveTimeMs > INACTIVE_TIME_BEFORE_UNLOADED_IN_MS)
|
||||
{
|
||||
LOGGER.debug("Unloading level [" + wrapper.getDhIdentifier() + "] due to inactivity");
|
||||
wrapper.tryUnloadFromWorld();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// level handling //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void setDhLevel(IDhLevel dhLevel) { this.dhLevel = dhLevel; }
|
||||
@Override
|
||||
public IDhLevel getDhLevel() { return this.dhLevel; }
|
||||
|
||||
/**
|
||||
* can be used when speed is important and the same level is likely to be passed in,
|
||||
* IE rendering.
|
||||
@@ -140,9 +231,13 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
@Nullable IClientLevelWrapper levelWrapper,
|
||||
@NotNull #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level)
|
||||
{
|
||||
if (KEYED_CLIENT_LEVEL_MANAGER.isEnabled() && KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel() != levelWrapper)
|
||||
if (KEYED_CLIENT_LEVEL_MANAGER.isEnabled())
|
||||
{
|
||||
return getWrapper(level);
|
||||
IServerKeyedClientLevel keyedLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel(level);
|
||||
if (keyedLevel != levelWrapper)
|
||||
{
|
||||
return getWrapper(level);
|
||||
}
|
||||
}
|
||||
|
||||
ClientLevelWrapper clientLevelWrapper = (ClientLevelWrapper)levelWrapper;
|
||||
@@ -172,9 +267,28 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
}
|
||||
|
||||
// used if the client is connected to a server that defines the currently loaded level
|
||||
IServerKeyedClientLevel overrideLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
|
||||
IServerKeyedClientLevel overrideLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel(level);
|
||||
if (overrideLevel != null)
|
||||
{
|
||||
// if the currently loaded level wrapper doesn't match what's incoming, unload it
|
||||
WeakReference<ClientLevelWrapper> levelRef = LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.get(level);
|
||||
if (levelRef != null
|
||||
&& levelRef.get() != overrideLevel)
|
||||
{
|
||||
ClientLevelWrapper levelWrapper = levelRef.get();
|
||||
if (levelWrapper != null)
|
||||
{
|
||||
levelWrapper.tryUnloadFromWorld();
|
||||
}
|
||||
levelRef = null;
|
||||
}
|
||||
|
||||
if (levelRef == null
|
||||
&& overrideLevel instanceof ClientLevelWrapper)
|
||||
{
|
||||
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.put(level, new WeakReference<>((ClientLevelWrapper) overrideLevel));
|
||||
}
|
||||
|
||||
return overrideLevel;
|
||||
}
|
||||
}
|
||||
@@ -337,7 +451,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.dimensionName = this.level.provider.getDimensionType().getName();
|
||||
this.dimensionName = this.level.provider.getDimensionType().getName() + ":" + this.level.provider.getDimension();
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
this.dimensionName = this.level.dimension().location().toString();
|
||||
#else
|
||||
@@ -443,6 +557,15 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
@Override
|
||||
public #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif getWrappedMcObject() { return this.level; }
|
||||
|
||||
private void tryUnloadFromWorld()
|
||||
{
|
||||
AbstractDhWorld world = SharedApi.getAbstractDhWorld();
|
||||
if (world == null
|
||||
|| !world.unloadLevel(this))
|
||||
{
|
||||
this.onUnload();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onUnload()
|
||||
{
|
||||
@@ -504,16 +627,11 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
|
||||
|
||||
|
||||
//===================//
|
||||
// generic rendering //
|
||||
//===================//
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void setDhLevel(IDhLevel dhLevel) { this.dhLevel = dhLevel; }
|
||||
@Override
|
||||
public IDhLevel getDhLevel() { return this.dhLevel; }
|
||||
|
||||
@Override
|
||||
public IDhApiCustomRenderRegister getRenderRegister()
|
||||
{
|
||||
@@ -604,6 +722,45 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getShade(EDhDirection lodDirection)
|
||||
{
|
||||
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
|
||||
switch (lodShading)
|
||||
{
|
||||
default:
|
||||
case AUTO:
|
||||
#if MC_VER <= MC_1_12_2
|
||||
// 1.12.2 level doesn't have a getShade method, fall through to ENABLED
|
||||
#else
|
||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||
#if MC_VER <= MC_1_21_11
|
||||
return this.level.getShade(mcDir, true);
|
||||
#else
|
||||
return this.level.cardinalLighting().byFace(mcDir);
|
||||
#endif
|
||||
#endif
|
||||
case ENABLED:
|
||||
switch (lodDirection)
|
||||
{
|
||||
case DOWN:
|
||||
return 0.5F;
|
||||
default:
|
||||
case UP:
|
||||
return 1.0F;
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
return 0.8F;
|
||||
case WEST:
|
||||
case EAST:
|
||||
return 0.6F;
|
||||
}
|
||||
|
||||
case DISABLED:
|
||||
return 1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -210,7 +210,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
||||
public String getDimensionName()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.level.provider.getDimensionType().getName();
|
||||
return this.level.provider.getDimensionType().getName() + ":" + this.level.provider.getDimension();
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
return this.level.dimension().location().toString();
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user