Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9a044308f | |||
| 1aabc0c792 | |||
| b1b0642fbe | |||
| eecb28d11f | |||
| 90564f2537 | |||
| ded0b979cf | |||
| ed9cc5485c | |||
| cbd5974657 | |||
| 0e5fba58ab | |||
| 2943e63382 | |||
| 30564aade7 | |||
| aabb90ada6 | |||
| 963a8dc53f | |||
| aa6d69385b | |||
| f42c9cf8fb | |||
| 92e0011c8d | |||
| c20d95a7c7 | |||
| 353aa1ed2c | |||
| 5aa43ebcc8 | |||
| b6145461b6 | |||
| 478e431076 | |||
| 6feb7f1b42 | |||
| 016fc66293 | |||
| 6d3e30d425 | |||
| 5be5c5a5bc | |||
| ed5aeb8951 | |||
| 7f0ddadf26 |
@@ -38,7 +38,7 @@ public final class ModInfo
|
|||||||
public static final String NAME = "DistantHorizons";
|
public static final String NAME = "DistantHorizons";
|
||||||
/** Human-readable version of NAME */
|
/** Human-readable version of NAME */
|
||||||
public static final String READABLE_NAME = "Distant Horizons";
|
public static final String READABLE_NAME = "Distant Horizons";
|
||||||
public static final String VERSION = "2.4.0-b";
|
public static final String VERSION = "2.4.3-b";
|
||||||
/** Returns true if the current build is an unstable developer build, false otherwise. */
|
/** Returns true if the current build is an unstable developer build, false otherwise. */
|
||||||
public static final boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
public static final boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
||||||
|
|
||||||
|
|||||||
@@ -20,36 +20,41 @@
|
|||||||
package com.seibel.distanthorizons.core;
|
package com.seibel.distanthorizons.core;
|
||||||
|
|
||||||
import com.github.luben.zstd.ZstdOutputStream;
|
import com.github.luben.zstd.ZstdOutputStream;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory;
|
||||||
import com.seibel.distanthorizons.core.sql.DatabaseUpdater;
|
import com.seibel.distanthorizons.core.sql.DatabaseUpdater;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
|
||||||
import com.seibel.distanthorizons.core.world.DhApiWorldProxy;
|
import com.seibel.distanthorizons.core.world.DhApiWorldProxy;
|
||||||
import com.seibel.distanthorizons.core.api.external.methods.config.DhApiConfig;
|
import com.seibel.distanthorizons.core.api.external.methods.config.DhApiConfig;
|
||||||
import com.seibel.distanthorizons.core.api.external.methods.data.DhApiTerrainDataRepo;
|
import com.seibel.distanthorizons.core.api.external.methods.data.DhApiTerrainDataRepo;
|
||||||
import com.seibel.distanthorizons.api.DhApi;
|
import com.seibel.distanthorizons.api.DhApi;
|
||||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||||
import net.jpountz.lz4.LZ4FrameOutputStream;
|
import net.jpountz.lz4.LZ4FrameOutputStream;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.sqlite.SQLiteJDBCLoader;
|
import org.sqlite.SQLiteJDBCLoader;
|
||||||
import org.sqlite.util.OSInfo;
|
|
||||||
import org.tukaani.xz.XZOutputStream;
|
import org.tukaani.xz.XZOutputStream;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.lang.management.GarbageCollectorMXBean;
|
||||||
import java.io.File;
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/** Handles first time Core setup. */
|
/** Handles first time Core setup. */
|
||||||
public class Initializer
|
public class Initializer
|
||||||
{
|
{
|
||||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void init()
|
public static void init()
|
||||||
{
|
{
|
||||||
|
LOGGER.info("Running library validation...");
|
||||||
|
|
||||||
// confirm that all referenced libraries are available to use
|
// confirm that all referenced libraries are available to use
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -57,6 +62,17 @@ public class Initializer
|
|||||||
// will throw an error (not an exception)
|
// will throw an error (not an exception)
|
||||||
Class<?> lz4Compressor = LZ4FrameOutputStream.class;
|
Class<?> lz4Compressor = LZ4FrameOutputStream.class;
|
||||||
Class<?> zstdCompressor = ZstdOutputStream.class;
|
Class<?> zstdCompressor = ZstdOutputStream.class;
|
||||||
|
|
||||||
|
{
|
||||||
|
byte[] testCompressByteArray = new byte[1024];
|
||||||
|
for (int i = 0; i < testCompressByteArray.length; i++)
|
||||||
|
{
|
||||||
|
testCompressByteArray[i] = (byte) (i % 126);
|
||||||
|
}
|
||||||
|
byte[] compressedBytes = com.github.luben.zstd.Zstd.compress(testCompressByteArray);
|
||||||
|
com.github.luben.zstd.Zstd.decompress(compressedBytes);
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> lzmaCompressor = XZOutputStream.class;
|
Class<?> lzmaCompressor = XZOutputStream.class;
|
||||||
//Class<?> networking = ByteBuf.class;
|
//Class<?> networking = ByteBuf.class;
|
||||||
Class<?> config = com.electronwill.nightconfig.core.Config.class;
|
Class<?> config = com.electronwill.nightconfig.core.Config.class;
|
||||||
@@ -73,9 +89,7 @@ public class Initializer
|
|||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
LOGGER.fatal("Critical programmer error: One or more libraries aren't present. Error: [" + e.getMessage() + "].", e);
|
MC_CLIENT.crashMinecraft("Distant Horizons critical setup error: One or more libraries are either in-accessible, corrupted, or overwritten by another mod. Error: [" + e.getMessage() + "].", e);
|
||||||
// throwing here should crash the game, notifying the developer that something is wrong
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// confirm the resource directory is present
|
// confirm the resource directory is present
|
||||||
@@ -89,8 +103,7 @@ public class Initializer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LOGGER.fatal("Critical programmer error: Can't read SQL Scripts resource folder is either missing or malformed. Error: [" + e.getMessage() + "].");
|
MC_CLIENT.crashMinecraft("Critical programmer error: Can't read SQL Scripts resource folder is either missing or malformed. Error: [" + e.getMessage() + "].", e);
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This code has been disabled since it can cause Mac
|
// This code has been disabled since it can cause Mac
|
||||||
@@ -121,6 +134,43 @@ public class Initializer
|
|||||||
LOGGER.error("Programmer Error: No ["+IWrapperFactory.class.getSimpleName()+"] assigned to the DhApi.");
|
LOGGER.error("Programmer Error: No ["+IWrapperFactory.class.getSimpleName()+"] assigned to the DhApi.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log a warning if G1GC is being used
|
||||||
|
// (this garbage collector is known to cause stuttering)
|
||||||
|
{
|
||||||
|
boolean g1GcInUse = false;
|
||||||
|
|
||||||
|
StringBuilder garbageCollectorNames = new StringBuilder();
|
||||||
|
List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
|
||||||
|
for (GarbageCollectorMXBean gcMxBean : gcMxBeans)
|
||||||
|
{
|
||||||
|
if (!garbageCollectorNames.toString().isEmpty())
|
||||||
|
{
|
||||||
|
garbageCollectorNames.append(", ");
|
||||||
|
}
|
||||||
|
garbageCollectorNames.append(gcMxBean.getName());
|
||||||
|
|
||||||
|
// "G1 Young Generation" // "G1 Concurrent GC" // "G1 Old Generation"
|
||||||
|
if (gcMxBean.getName().toLowerCase().contains("g1 "))
|
||||||
|
{
|
||||||
|
g1GcInUse = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOGGER.info("Garbage collectors: ["+garbageCollectorNames+"]");
|
||||||
|
|
||||||
|
|
||||||
|
if (g1GcInUse
|
||||||
|
&& Config.Common.Logging.Warning.logGarbageCollectorWarning.get())
|
||||||
|
{
|
||||||
|
LOGGER.warn(
|
||||||
|
"Distant Horizons: G1 Garbage collector detected. \n" +
|
||||||
|
"This garbage collector can cause FPS stuttering. \n" +
|
||||||
|
"It's recommended to use a concurrent garbage collector \n" +
|
||||||
|
"like ZGC (Java 21+) or Shenandoah (Java 8 through 17) for a smoother experience. \n" +
|
||||||
|
"");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.management.GarbageCollectorMXBean;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
@@ -93,6 +95,7 @@ public class ClientApi
|
|||||||
private boolean isDevBuildMessagePrinted = false;
|
private boolean isDevBuildMessagePrinted = false;
|
||||||
private boolean lowMemoryWarningPrinted = false;
|
private boolean lowMemoryWarningPrinted = false;
|
||||||
private boolean highVanillaRenderDistanceWarningPrinted = false;
|
private boolean highVanillaRenderDistanceWarningPrinted = false;
|
||||||
|
private boolean g1GarbageCollectorWarningPrinted = false;
|
||||||
|
|
||||||
private long lastStaticWarningMessageSentMsTime = 0L;
|
private long lastStaticWarningMessageSentMsTime = 0L;
|
||||||
|
|
||||||
@@ -318,35 +321,6 @@ public class ClientApi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============//
|
|
||||||
// clint tick //
|
|
||||||
//============//
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void clientTickEvent()
|
|
||||||
{
|
|
||||||
IProfilerWrapper profiler = MC_CLIENT.getProfiler();
|
|
||||||
profiler.push("DH-ClientTick");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IDhClientWorld clientWorld = SharedApi.tryGetDhClientWorld();
|
|
||||||
if (clientWorld != null)
|
|
||||||
{
|
|
||||||
clientWorld.clientTick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
// handle errors here to prevent blowing up a mixin or API up stream
|
|
||||||
LOGGER.error("Unexpected error in ClientApi.clientTickEvent(), error: "+e.getMessage(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
profiler.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============//
|
//============//
|
||||||
// networking //
|
// networking //
|
||||||
//============//
|
//============//
|
||||||
@@ -405,8 +379,11 @@ public class ClientApi
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// make sure the GLProxy is created for future use
|
||||||
|
GLProxy.getInstance();
|
||||||
|
|
||||||
// these tasks always need to be called, regardless of whether the renderer is enabled or not to prevent memory leaks
|
// these tasks always need to be called, regardless of whether the renderer is enabled or not to prevent memory leaks
|
||||||
GLProxy.getInstance().runRenderThreadTasks();
|
GLProxy.runRenderThreadTasks();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -674,7 +651,8 @@ public class ClientApi
|
|||||||
{
|
{
|
||||||
// dev build
|
// dev build
|
||||||
if (ModInfo.IS_DEV_BUILD
|
if (ModInfo.IS_DEV_BUILD
|
||||||
&& !this.isDevBuildMessagePrinted && MC_CLIENT.playerExists())
|
&& !this.isDevBuildMessagePrinted
|
||||||
|
&& MC_CLIENT.playerExists())
|
||||||
{
|
{
|
||||||
this.isDevBuildMessagePrinted = true;
|
this.isDevBuildMessagePrinted = true;
|
||||||
this.lastStaticWarningMessageSentMsTime = System.currentTimeMillis();
|
this.lastStaticWarningMessageSentMsTime = System.currentTimeMillis();
|
||||||
@@ -720,10 +698,11 @@ public class ClientApi
|
|||||||
if (!this.highVanillaRenderDistanceWarningPrinted
|
if (!this.highVanillaRenderDistanceWarningPrinted
|
||||||
&& Config.Common.Logging.Warning.showHighVanillaRenderDistanceWarning.get())
|
&& Config.Common.Logging.Warning.showHighVanillaRenderDistanceWarning.get())
|
||||||
{
|
{
|
||||||
|
this.highVanillaRenderDistanceWarningPrinted = true;
|
||||||
|
|
||||||
// DH generally doesn't need a vanilla render distance above 12
|
// DH generally doesn't need a vanilla render distance above 12
|
||||||
if (MC_RENDER.getRenderDistance() > 12)
|
if (MC_RENDER.getRenderDistance() > 12)
|
||||||
{
|
{
|
||||||
this.highVanillaRenderDistanceWarningPrinted = true;
|
|
||||||
this.lastStaticWarningMessageSentMsTime = System.currentTimeMillis();
|
this.lastStaticWarningMessageSentMsTime = System.currentTimeMillis();
|
||||||
|
|
||||||
String message =
|
String message =
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ public class ClientPluginChannelApi
|
|||||||
|
|
||||||
LOGGER.info("Server level key received: [" + msg.levelKey + "].");
|
LOGGER.info("Server level key received: [" + msg.levelKey + "].");
|
||||||
|
|
||||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
GLProxy.queueRunningOnRenderThread(() ->
|
||||||
{
|
{
|
||||||
IClientLevelWrapper clientLevel = MC.getWrappedClientLevel(true);
|
IClientLevelWrapper clientLevel = MC.getWrappedClientLevel(true);
|
||||||
IServerKeyedClientLevel existingKeyedClientLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
|
IServerKeyedClientLevel existingKeyedClientLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ import com.seibel.distanthorizons.core.config.types.enums.*;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
|
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -420,6 +419,14 @@ public class Config
|
|||||||
"")
|
"")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static ConfigEntry<Integer> fadeDistanceInBlocks = new ConfigEntry.Builder<Integer>()
|
||||||
|
.setMinDefaultMax(0, 1_600, 30_000_000)
|
||||||
|
.comment("" +
|
||||||
|
"The distance in blocks from the camera where the SSAO will fade out to. \n"+
|
||||||
|
"This is done to prevent banding and noise at extreme distances. \n"+
|
||||||
|
"")
|
||||||
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GenericRendering
|
public static class GenericRendering
|
||||||
@@ -786,6 +793,11 @@ public class Config
|
|||||||
+ "A comma separated list of block resource locations that won't be rendered by DH. \n"
|
+ "A comma separated list of block resource locations that won't be rendered by DH. \n"
|
||||||
+ "Air is always included in this list. \n"
|
+ "Air is always included in this list. \n"
|
||||||
+ "Requires a restart to change. \n"
|
+ "Requires a restart to change. \n"
|
||||||
|
+ "\n"
|
||||||
|
+ "Note:\n"
|
||||||
|
+ "If you see gaps, or holes you may have to change\n"
|
||||||
|
+ "worldCompression to ["+EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS+"] and re-generate the LODs.\n"
|
||||||
|
+ "Black spots may happen occur to block lighting being zero for covered blocks.\n"
|
||||||
+ "")
|
+ "")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -1246,20 +1258,14 @@ public class Config
|
|||||||
public static ConfigUIButton uiButtonTest = new ConfigUIButton(() ->
|
public static ConfigUIButton uiButtonTest = new ConfigUIButton(() ->
|
||||||
{
|
{
|
||||||
// running on a separate thread is necessary to prevent locking
|
// running on a separate thread is necessary to prevent locking
|
||||||
new Thread(() ->
|
new Thread(() -> onButtonPressed()).start();
|
||||||
{
|
|
||||||
if (!GraphicsEnvironment.isHeadless())
|
|
||||||
{
|
|
||||||
LOGGER.info("Attempting to show tinyfd message box...");
|
|
||||||
boolean buttonPress = TinyFileDialogs.tinyfd_messageBox("Button pressed!", "UITester dialog", "ok", "info", false);
|
|
||||||
LOGGER.info("dialog returned with ["+(buttonPress ? "TRUE" : "FALSE")+"]");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGGER.info("button pressed!");
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
});
|
});
|
||||||
|
public static void onButtonPressed()
|
||||||
|
{
|
||||||
|
LOGGER.info("Attempting to show tinyfd message box...");
|
||||||
|
boolean buttonPress = NativeDialogUtil.showDialog("Button pressed!", "UITester dialog", "ok", "info");
|
||||||
|
LOGGER.info("dialog returned with ["+(buttonPress ? "TRUE" : "FALSE")+"]");
|
||||||
|
}
|
||||||
|
|
||||||
public static ConfigCategory categoryTest = new ConfigCategory.Builder().set(CategoryTest.class).build();
|
public static ConfigCategory categoryTest = new ConfigCategory.Builder().set(CategoryTest.class).build();
|
||||||
|
|
||||||
@@ -1661,6 +1667,15 @@ public class Config
|
|||||||
+ "")
|
+ "")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static ConfigEntry<Boolean> logGarbageCollectorWarning = new ConfigEntry.Builder<Boolean>()
|
||||||
|
.set(true)
|
||||||
|
.comment(""
|
||||||
|
+ "If enabled, a message will be logged if the garbage \n"
|
||||||
|
+ "collector Java is currently using is known \n"
|
||||||
|
+ "to cause stutters and/or issues. \n"
|
||||||
|
+ "")
|
||||||
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -107,7 +107,7 @@ public class LodBufferContainer implements AutoCloseable
|
|||||||
|
|
||||||
|
|
||||||
// upload on MC's render thread
|
// upload on MC's render thread
|
||||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
GLProxy.queueRunningOnRenderThread(() ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -295,7 +295,7 @@ public class LodBufferContainer implements AutoCloseable
|
|||||||
{
|
{
|
||||||
this.buffersUploaded = false;
|
this.buffersUploaded = false;
|
||||||
|
|
||||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
GLProxy.queueRunningOnRenderThread(() ->
|
||||||
{
|
{
|
||||||
for (GLVertexBuffer buffer : this.vbos)
|
for (GLVertexBuffer buffer : this.vbos)
|
||||||
{
|
{
|
||||||
|
|||||||
+17
-15
@@ -399,31 +399,33 @@ public class LodQuadBuilder
|
|||||||
}
|
}
|
||||||
private void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte normalIndex, byte irisBlockMaterialId, byte skylight, byte blocklight, int mx, int my, int mz)
|
private void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte normalIndex, byte irisBlockMaterialId, byte skylight, byte blocklight, int mx, int my, int mz)
|
||||||
{
|
{
|
||||||
skylight %= 16;
|
|
||||||
blocklight %= 16;
|
|
||||||
|
|
||||||
bb.putShort(x);
|
bb.putShort(x);
|
||||||
bb.putShort(y);
|
bb.putShort(y);
|
||||||
bb.putShort(z);
|
bb.putShort(z);
|
||||||
|
|
||||||
short meta = 0;
|
short meta = 0;
|
||||||
meta |= (skylight | (blocklight << 4));
|
{
|
||||||
byte mirco = 0;
|
skylight %= 16;
|
||||||
// mirco offset which is a xyz 2bit value
|
blocklight %= 16;
|
||||||
// 0b00 = no offset
|
meta |= (short) (skylight | (blocklight << 4));
|
||||||
// 0b01 = positive offset
|
|
||||||
// 0b11 = negative offset
|
|
||||||
// format is: 0b00zzyyxx
|
|
||||||
if (mx != 0) mirco |= mx > 0 ? 0b01 : 0b11;
|
|
||||||
if (my != 0) mirco |= my > 0 ? 0b0100 : 0b1100;
|
|
||||||
if (mz != 0) mirco |= mz > 0 ? 0b010000 : 0b110000;
|
|
||||||
meta |= mirco << 8;
|
|
||||||
|
|
||||||
|
byte mircoOffset = 0;
|
||||||
|
// mirco offset which is a xyz 2bit value
|
||||||
|
// 0b00 = no offset
|
||||||
|
// 0b01 = positive offset
|
||||||
|
// 0b11 = negative offset
|
||||||
|
// format is: 0b00zzyyxx
|
||||||
|
if (mx != 0) { mircoOffset |= (byte) (mx > 0 ? 0b01 : 0b11); }
|
||||||
|
if (my != 0) { mircoOffset |= (byte) (my > 0 ? 0b0100 : 0b1100); }
|
||||||
|
if (mz != 0) { mircoOffset |= (byte) (mz > 0 ? 0b010000 : 0b110000); }
|
||||||
|
meta |= (short) (mircoOffset << 8);
|
||||||
|
}
|
||||||
bb.putShort(meta);
|
bb.putShort(meta);
|
||||||
|
|
||||||
byte r = (byte) ColorUtil.getRed(color);
|
byte r = (byte) ColorUtil.getRed(color);
|
||||||
byte g = (byte) ColorUtil.getGreen(color);
|
byte g = (byte) ColorUtil.getGreen(color);
|
||||||
byte b = (byte) ColorUtil.getBlue(color);
|
byte b = (byte) ColorUtil.getBlue(color);
|
||||||
byte a = this.doTransparency ? (byte) ColorUtil.getAlpha(color) : (byte) 255; // TODO should this be called here or happen somewhere else?
|
byte a = this.doTransparency ? (byte) ColorUtil.getAlpha(color) : (byte) 255;
|
||||||
bb.put(r);
|
bb.put(r);
|
||||||
bb.put(g);
|
bb.put(g);
|
||||||
bb.put(b);
|
bb.put(b);
|
||||||
|
|||||||
+128
-77
@@ -118,14 +118,18 @@ public class DhLightingEngine
|
|||||||
* @param centerChunk the chunk we want to apply lighting to
|
* @param centerChunk the chunk we want to apply lighting to
|
||||||
* @param nearbyChunkList should also contain centerChunk
|
* @param nearbyChunkList should also contain centerChunk
|
||||||
* @param maxSkyLight should be a value between 0 and 15
|
* @param maxSkyLight should be a value between 0 and 15
|
||||||
|
*
|
||||||
|
* @return the number of light positions iterated over, can be used for profiling.
|
||||||
*/
|
*/
|
||||||
private void lightChunk(
|
private int lightChunk(
|
||||||
@NotNull IChunkWrapper centerChunk, @NotNull ArrayList<IChunkWrapper> nearbyChunkList,
|
@NotNull IChunkWrapper centerChunk, @NotNull ArrayList<IChunkWrapper> nearbyChunkList,
|
||||||
int maxSkyLight, boolean updateBlockLight, boolean updateSkyLight)
|
int maxSkyLight, boolean updateBlockLight, boolean updateSkyLight)
|
||||||
{
|
{
|
||||||
DhChunkPos centerChunkPos = centerChunk.getChunkPos();
|
DhChunkPos centerChunkPos = centerChunk.getChunkPos();
|
||||||
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(centerChunk);
|
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(centerChunk);
|
||||||
|
|
||||||
|
// how many positions we've walked over, can be used for profiling/debugging
|
||||||
|
int posIterations = 0;
|
||||||
|
|
||||||
// try-finally to handle the stableArray resources
|
// try-finally to handle the stableArray resources
|
||||||
StableLightPosStack blockLightWorldPosQueue = null;
|
StableLightPosStack blockLightWorldPosQueue = null;
|
||||||
@@ -245,13 +249,15 @@ public class DhLightingEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// block light
|
// block light
|
||||||
if (updateBlockLight)
|
if (updateBlockLight)
|
||||||
{
|
{
|
||||||
// done to prevent a rare issue where the light values are incorrectly set to -1
|
// done to prevent a rare issue where the light values are incorrectly set to -1
|
||||||
centerChunk.clearDhBlockLighting();
|
centerChunk.clearDhBlockLighting();
|
||||||
|
|
||||||
this.propagateChunkLightPosList(blockLightWorldPosQueue, adjacentChunkHolder,
|
posIterations += this.propagateChunkLightPosList(blockLightWorldPosQueue, adjacentChunkHolder,
|
||||||
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
|
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
|
||||||
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue),
|
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue),
|
||||||
true);
|
true);
|
||||||
@@ -262,7 +268,7 @@ public class DhLightingEngine
|
|||||||
{
|
{
|
||||||
centerChunk.clearDhSkyLighting();
|
centerChunk.clearDhSkyLighting();
|
||||||
|
|
||||||
this.propagateChunkLightPosList(skyLightWorldPosQueue, adjacentChunkHolder,
|
posIterations += this.propagateChunkLightPosList(skyLightWorldPosQueue, adjacentChunkHolder,
|
||||||
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
|
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
|
||||||
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue),
|
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue),
|
||||||
false);
|
false);
|
||||||
@@ -287,10 +293,12 @@ public class DhLightingEngine
|
|||||||
{
|
{
|
||||||
centerChunk.setIsDhSkyLightCorrect(true);
|
centerChunk.setIsDhSkyLightCorrect(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return posIterations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Applies each {@link LightPos} from the queue to the given set of {@link IChunkWrapper}'s. */
|
/** Applies each {@link LightPos} from the queue to the given set of {@link IChunkWrapper}'s. */
|
||||||
private void propagateChunkLightPosList(
|
private int propagateChunkLightPosList(
|
||||||
StableLightPosStack lightPosQueue, AdjacentChunkHolder adjacentChunkHolder,
|
StableLightPosStack lightPosQueue, AdjacentChunkHolder adjacentChunkHolder,
|
||||||
IGetLightFunc getLightFunc, ISetLightFunc setLightFunc,
|
IGetLightFunc getLightFunc, ISetLightFunc setLightFunc,
|
||||||
boolean propagatingBlockLights)
|
boolean propagatingBlockLights)
|
||||||
@@ -320,66 +328,89 @@ public class DhLightingEngine
|
|||||||
IBlockStateWrapper previousBlockState = null;
|
IBlockStateWrapper previousBlockState = null;
|
||||||
|
|
||||||
|
|
||||||
// update each light position
|
int iterations = 0;
|
||||||
while (!lightPosQueue.isEmpty())
|
|
||||||
|
// update each light level
|
||||||
|
for (int currentLightLevel = LodUtil.MAX_MC_LIGHT; currentLightLevel >= LodUtil.MIN_MC_LIGHT; currentLightLevel--)
|
||||||
{
|
{
|
||||||
// since we don't care about the order the positions are processed,
|
// Walking down from the top light level to the bottom can reduce iterating over
|
||||||
// we can grab the last position instead of the first for a slight performance increase (this way the array doesn't need to be shifted over every loop)
|
// the same positions multiple times.
|
||||||
lightPosQueue.popMutate(lightPos);
|
// At best this seems to behave at roughly 2x the speed of just blindly putting light pos
|
||||||
|
// in a queue and at worse slightly faster than the blind queue.
|
||||||
|
|
||||||
int lightValue = lightPos.lightValue;
|
lightPos.lightValue = currentLightLevel;
|
||||||
|
|
||||||
|
// update each light position
|
||||||
// propagate the lighting in each cardinal direction, IE: -x, +x, -y, +y, -z, +z
|
while (!lightPosQueue.isLightLevelEmpty(currentLightLevel))
|
||||||
for (EDhDirection direction : EDhDirection.ALL) // since this is an array instead of an ArrayList this advanced for-loop shouldn't cause any GC issues
|
|
||||||
{
|
{
|
||||||
lightPos.mutateOffset(direction, neighbourBlockPos);
|
// since we don't care about the order the positions are processed,
|
||||||
neighbourBlockPos.mutateToChunkRelativePos(relNeighbourBlockPos);
|
// we can grab the last position instead of the first for a slight performance increase (this way the array doesn't need to be shifted over every loop)
|
||||||
|
lightPosQueue.popMutate(lightPos, currentLightLevel);
|
||||||
|
iterations++;
|
||||||
|
|
||||||
|
int lightValue = lightPos.lightValue;
|
||||||
|
|
||||||
|
|
||||||
// only continue if the light position is inside one of our chunks
|
// propagate the lighting in each cardinal direction, IE: -x, +x, -y, +y, -z, +z
|
||||||
IChunkWrapper neighbourChunk = adjacentChunkHolder.getByBlockPos(neighbourBlockPos.getX(), neighbourBlockPos.getZ());
|
for (EDhDirection direction : EDhDirection.ALL) // since this is an array instead of an ArrayList this advanced for-loop shouldn't cause any GC issues
|
||||||
if (neighbourChunk == null)
|
|
||||||
{
|
{
|
||||||
// the light pos is outside our generator's range, ignore it
|
lightPos.mutateOffset(direction, neighbourBlockPos);
|
||||||
continue;
|
neighbourBlockPos.mutateToChunkRelativePos(relNeighbourBlockPos);
|
||||||
}
|
|
||||||
|
|
||||||
if (relNeighbourBlockPos.getY() < neighbourChunk.getMinNonEmptyHeight()
|
|
||||||
|| relNeighbourBlockPos.getY() >= neighbourChunk.getExclusiveMaxBuildHeight())
|
|
||||||
{
|
|
||||||
// the light pos is outside the chunk's min/max height,
|
|
||||||
// this can happen if given a chunk that hasn't finished generating
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int currentBlockLight = getLightFunc.getLight(neighbourChunk, relNeighbourBlockPos);
|
// only continue if the light position is inside one of our chunks
|
||||||
if (currentBlockLight >= (lightValue - 1))
|
IChunkWrapper neighbourChunk = adjacentChunkHolder.getByBlockPos(neighbourBlockPos.getX(), neighbourBlockPos.getZ());
|
||||||
{
|
if (neighbourChunk == null)
|
||||||
// short circuit for when the light value at this position
|
{
|
||||||
// is already greater-than what we could set it
|
// the light pos is outside our generator's range, ignore it
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (relNeighbourBlockPos.getY() < neighbourChunk.getMinNonEmptyHeight()
|
||||||
|
|| relNeighbourBlockPos.getY() >= neighbourChunk.getExclusiveMaxBuildHeight())
|
||||||
|
{
|
||||||
|
// the light pos is outside the chunk's min/max height,
|
||||||
|
// this can happen if given a chunk that hasn't finished generating
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IBlockStateWrapper neighbourBlockState = neighbourChunk.getBlockState(relNeighbourBlockPos, mcBlockPos, previousBlockState);
|
int currentBlockLight = getLightFunc.getLight(neighbourChunk, relNeighbourBlockPos);
|
||||||
previousBlockState = neighbourBlockState;
|
if (currentBlockLight >= (lightValue - 1))
|
||||||
|
{
|
||||||
|
// short circuit for when the light value at this position
|
||||||
|
// is already greater-than what we could set it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Math.max(1, ...) is used so that the propagated light level always drops by at least 1, preventing infinite cycles.
|
|
||||||
int targetLevel = lightValue - Math.max(1, neighbourBlockState.getOpacity());
|
|
||||||
if (targetLevel > currentBlockLight)
|
|
||||||
{
|
|
||||||
// this position is darker than the new light value, update/set it
|
|
||||||
setLightFunc.setLight(neighbourChunk, relNeighbourBlockPos, targetLevel);
|
|
||||||
|
|
||||||
// now that light has been propagated to this blockPos
|
IBlockStateWrapper neighbourBlockState = neighbourChunk.getBlockState(relNeighbourBlockPos, mcBlockPos, previousBlockState);
|
||||||
// we need to queue it up so its neighbours can be propagated as well
|
previousBlockState = neighbourBlockState;
|
||||||
lightPosQueue.push(neighbourBlockPos.getX(), neighbourBlockPos.getY(), neighbourBlockPos.getZ(), targetLevel);
|
|
||||||
|
// Math.max(1, ...) is used so that the propagated light level always drops by at least 1, preventing infinite cycles.
|
||||||
|
int targetLightLevel = lightValue - Math.max(1, neighbourBlockState.getOpacity());
|
||||||
|
if (targetLightLevel > currentBlockLight)
|
||||||
|
{
|
||||||
|
// this position is darker than the new light value, update/set it
|
||||||
|
setLightFunc.setLight(neighbourChunk, relNeighbourBlockPos, targetLightLevel);
|
||||||
|
|
||||||
|
// now that light has been propagated to this blockPos
|
||||||
|
// we need to queue it up so its neighbours can be propagated as well
|
||||||
|
lightPosQueue.push(neighbourBlockPos.getX(), neighbourBlockPos.getY(), neighbourBlockPos.getZ(), targetLightLevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int currentLightLevel = LodUtil.MAX_MC_LIGHT; currentLightLevel >= LodUtil.MIN_MC_LIGHT; currentLightLevel--)
|
||||||
|
{
|
||||||
|
if (!lightPosQueue.isLightLevelEmpty(currentLightLevel))
|
||||||
|
{
|
||||||
|
LodUtil.assertNotReach("Non empty light pos queue for light level ["+currentLightLevel+"] after light engine running");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// can be enabled if troubleshooting lighting issues
|
// can be enabled if troubleshooting lighting issues
|
||||||
if (RENDER_BLOCK_LIGHT_WIREFRAME
|
if (RENDER_BLOCK_LIGHT_WIREFRAME
|
||||||
@@ -395,6 +426,7 @@ public class DhLightingEngine
|
|||||||
|
|
||||||
|
|
||||||
// propagation complete
|
// propagation complete
|
||||||
|
return iterations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -748,16 +780,24 @@ public class DhLightingEngine
|
|||||||
private static final Queue<StableLightPosStack> lightArrayCache = new ArrayDeque<>();
|
private static final Queue<StableLightPosStack> lightArrayCache = new ArrayDeque<>();
|
||||||
|
|
||||||
/** the index of the last item in the array, -1 if empty */
|
/** the index of the last item in the array, -1 if empty */
|
||||||
private int index = -1;
|
private int[] indexByLightLevel = new int[LodUtil.MAX_MC_LIGHT + 1];
|
||||||
|
|
||||||
/** x, y, z, and lightValue. */
|
/** x, y, z */
|
||||||
public static final int INTS_PER_LIGHT_POS = 4;
|
public static final int INTS_PER_LIGHT_POS = 3;
|
||||||
|
|
||||||
/**
|
private final IntArrayList[] lightPositionsByLightLevel = new IntArrayList[LodUtil.MAX_MC_LIGHT + 1];
|
||||||
* When tested with a normal 1.20 world James saw a maximum of 36,709 block and 2,355 sky lights,
|
|
||||||
* so 40,000 should be a good starting point that can contain most lighting tasks.
|
|
||||||
*/
|
public StableLightPosStack()
|
||||||
private final IntArrayList lightPositions = new IntArrayList(40_000 * INTS_PER_LIGHT_POS);
|
{
|
||||||
|
for (int i = 0; i < this.lightPositionsByLightLevel.length; i++)
|
||||||
|
{
|
||||||
|
// When tested with a normal 1.20 world James saw a maximum of 36,709 block and 2,355 sky lights,
|
||||||
|
// so 40,000 should be a good starting point that can contain most lighting tasks.
|
||||||
|
this.lightPositionsByLightLevel[i] = new IntArrayList(40_000 * INTS_PER_LIGHT_POS);
|
||||||
|
this.indexByLightLevel[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -804,45 +844,56 @@ public class DhLightingEngine
|
|||||||
// stack methods //
|
// stack methods //
|
||||||
//===============//
|
//===============//
|
||||||
|
|
||||||
public boolean isEmpty() { return this.index == -1; }
|
public boolean isLightLevelEmpty(int lightLevel) { return this.indexByLightLevel[lightLevel] == -1; }
|
||||||
public int size() { return this.index+1; }
|
//public int size() { return this.index+1; }
|
||||||
|
|
||||||
public void push(int blockX, int blockY, int blockZ, int lightValue)
|
public void push(int blockX, int blockY, int blockZ, int lightLevel)
|
||||||
{
|
{
|
||||||
this.index++;
|
IntArrayList lightPositions = this.lightPositionsByLightLevel[lightLevel];
|
||||||
int subIndex = this.index * INTS_PER_LIGHT_POS;
|
|
||||||
if (subIndex < this.lightPositions.size())
|
this.indexByLightLevel[lightLevel]++;
|
||||||
|
int subIndex = this.indexByLightLevel[lightLevel] * INTS_PER_LIGHT_POS;
|
||||||
|
if (subIndex < lightPositions.size())
|
||||||
{
|
{
|
||||||
this.lightPositions.set(subIndex, blockX);
|
lightPositions.set(subIndex, blockX);
|
||||||
this.lightPositions.set(subIndex + 1, blockY);
|
lightPositions.set(subIndex + 1, blockY);
|
||||||
this.lightPositions.set(subIndex + 2, blockZ);
|
lightPositions.set(subIndex + 2, blockZ);
|
||||||
this.lightPositions.set(subIndex + 3, lightValue);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// add a new pos
|
// add a new pos
|
||||||
this.lightPositions.add(blockX);
|
lightPositions.add(blockX);
|
||||||
this.lightPositions.add(blockY);
|
lightPositions.add(blockY);
|
||||||
this.lightPositions.add(blockZ);
|
lightPositions.add(blockZ);
|
||||||
this.lightPositions.add(lightValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** mutates the given {@link LightPos} to match the next {@link LightPos} in the queue. */
|
/** mutates the given {@link LightPos} to match the next {@link LightPos} in the queue. */
|
||||||
public void popMutate(LightPos pos)
|
public void popMutate(LightPos pos, int lightLevel)
|
||||||
{
|
{
|
||||||
int subIndex = this.index * INTS_PER_LIGHT_POS;
|
int subIndex = this.indexByLightLevel[lightLevel] * INTS_PER_LIGHT_POS;
|
||||||
|
IntArrayList lightPositions = this.lightPositionsByLightLevel[lightLevel];
|
||||||
|
|
||||||
pos.setX(this.lightPositions.getInt(subIndex));
|
pos.setX(lightPositions.getInt(subIndex));
|
||||||
pos.setY(this.lightPositions.getInt(subIndex + 1));
|
pos.setY(lightPositions.getInt(subIndex + 1));
|
||||||
pos.setZ(this.lightPositions.getInt(subIndex + 2));
|
pos.setZ(lightPositions.getInt(subIndex + 2));
|
||||||
pos.lightValue = this.lightPositions.getInt(subIndex + 3);
|
|
||||||
|
|
||||||
this.index--;
|
this.indexByLightLevel[lightLevel]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return this.index + "/" + (this.lightPositions.size() / INTS_PER_LIGHT_POS); }
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < this.indexByLightLevel.length; i++)
|
||||||
|
{
|
||||||
|
builder.append("light: ").append(i)
|
||||||
|
.append(" size: ").append(this.indexByLightLevel[i]).append("/").append(this.lightPositionsByLightLevel[i].size() / INTS_PER_LIGHT_POS).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||||
import com.seibel.distanthorizons.core.sql.repo.FullDataSourceV2Repo;
|
import com.seibel.distanthorizons.core.sql.repo.FullDataSourceV2Repo;
|
||||||
|
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.jar.gui.BaseJFrame;
|
import com.seibel.distanthorizons.core.jar.gui.BaseJFrame;
|
||||||
import com.seibel.distanthorizons.core.jar.gui.cusomJObject.JBox;
|
import com.seibel.distanthorizons.core.jar.gui.cusomJObject.JBox;
|
||||||
@@ -31,7 +32,6 @@ import com.seibel.distanthorizons.core.jar.installer.WebDownloader;
|
|||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.apache.logging.log4j.core.LoggerContext;
|
import org.apache.logging.log4j.core.LoggerContext;
|
||||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -441,7 +441,7 @@ public class JarMain
|
|||||||
installMod.addActionListener(e -> {
|
installMod.addActionListener(e -> {
|
||||||
if (minecraftDirPop.getSelectedFile() == null)
|
if (minecraftDirPop.getSelectedFile() == null)
|
||||||
{
|
{
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, "Please select your install directory", "ok", "warning", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, "Please select your install directory", "ok", "warning");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,11 +455,11 @@ public class JarMain
|
|||||||
ModInfo.NAME + "-" + ModrinthGetter.releaseNames.get(downloadID.get()) + ".jar"
|
ModInfo.NAME + "-" + ModrinthGetter.releaseNames.get(downloadID.get()) + ".jar"
|
||||||
).toFile());
|
).toFile());
|
||||||
|
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, "Installation done. \nYou can now close the installer", "ok", "info", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, "Installation done. \nYou can now close the installer", "ok", "info");
|
||||||
}
|
}
|
||||||
catch (Exception f)
|
catch (Exception f)
|
||||||
{
|
{
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, "Download failed. Check your internet connection \nStacktrace: " + f.getMessage(), "error", "info", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, "Download failed. Check your internet connection \nStacktrace: " + f.getMessage(), "error", "info");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
frame.add(installMod);
|
frame.add(installMod);
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
|||||||
import com.seibel.distanthorizons.core.jar.installer.WebDownloader;
|
import com.seibel.distanthorizons.core.jar.installer.WebDownloader;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
|
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||||
import com.seibel.distanthorizons.coreapi.util.jar.DeleteOnUnlock;
|
import com.seibel.distanthorizons.coreapi.util.jar.DeleteOnUnlock;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -174,7 +174,7 @@ public class SelfUpdater
|
|||||||
|
|
||||||
if (!GitlabGetter.INSTANCE.getDownloads(pipeline.get("id")).containsKey(mcVersion))
|
if (!GitlabGetter.INSTANCE.getDownloads(pipeline.get("id")).containsKey(mcVersion))
|
||||||
{
|
{
|
||||||
LOGGER.warn("Minecraft version ["+ mcVersion +"] is not findable on Gitlab, findable versions are ["+ StringUtil.join(",", GitlabGetter.INSTANCE.getDownloads(pipeline.get("id")).keySet().toArray()) +"].");
|
LOGGER.warn("Minecraft version ["+ mcVersion +"] is not findable on Gitlab, findable versions are ["+ StringUtil.join(", ", GitlabGetter.INSTANCE.getDownloads(pipeline.get("id")).keySet().toArray()) +"].");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,14 +258,13 @@ public class SelfUpdater
|
|||||||
|
|
||||||
deleteOldJarOnJvmShutdown = true;
|
deleteOldJarOnJvmShutdown = true;
|
||||||
|
|
||||||
// TODO one of these messages contains something TinyFd doesn't like, find it and fix it
|
String successMessage = "Distant Horizons successfully updated. It will apply on game`s relaunch";
|
||||||
String successMessage = "Distant Horizons successfully updated. It will apply on game's relaunch";
|
|
||||||
LOGGER.info(successMessage);
|
LOGGER.info(successMessage);
|
||||||
new Thread(() ->
|
new Thread(() ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, successMessage, "ok", "info", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, successMessage, "ok", "info");
|
||||||
}
|
}
|
||||||
catch (Exception ignore) { }
|
catch (Exception ignore) { }
|
||||||
}).start();
|
}).start();
|
||||||
@@ -288,7 +287,7 @@ public class SelfUpdater
|
|||||||
LOGGER.error(failMessage, e);
|
LOGGER.error(failMessage, e);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, failMessage, "ok", "error", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, failMessage, "ok", "error");
|
||||||
}
|
}
|
||||||
catch (Exception ignore) { }
|
catch (Exception ignore) { }
|
||||||
|
|
||||||
@@ -386,7 +385,7 @@ public class SelfUpdater
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, successMessage, "ok", "info", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, successMessage, "ok", "info");
|
||||||
}
|
}
|
||||||
catch (Exception ignore) { }
|
catch (Exception ignore) { }
|
||||||
}).start();
|
}).start();
|
||||||
@@ -424,7 +423,7 @@ public class SelfUpdater
|
|||||||
LOGGER.error(failMessage, e);
|
LOGGER.error(failMessage, e);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, failMessage, "ok", "error", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, failMessage, "ok", "error");
|
||||||
}
|
}
|
||||||
catch (Exception ignore) { }
|
catch (Exception ignore) { }
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -92,7 +92,8 @@ public class NetworkSession extends AbstractNetworkEventSource
|
|||||||
{
|
{
|
||||||
LOGGER.error("Failed to handle the message. New messages will be ignored.", e);
|
LOGGER.error("Failed to handle the message. New messages will be ignored.", e);
|
||||||
LOGGER.error("Message: ["+message+"]");
|
LOGGER.error("Message: ["+message+"]");
|
||||||
this.close();
|
|
||||||
|
this.close(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
//=============//
|
//=============//
|
||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
//region constructor
|
||||||
|
|
||||||
public LodRenderSection(
|
public LodRenderSection(
|
||||||
long pos,
|
long pos,
|
||||||
@@ -153,11 +154,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
|
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion constructor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//======================================//
|
//======================================//
|
||||||
// render data generation and uploading //
|
// render data generation and uploading //
|
||||||
//======================================//
|
//======================================//
|
||||||
|
//region render data uploading
|
||||||
|
|
||||||
/** @return true if the upload started, false if it wasn't able to for any reason */
|
/** @return true if the upload started, false if it wasn't able to for any reason */
|
||||||
public synchronized boolean uploadRenderDataToGpuAsync()
|
public synchronized boolean uploadRenderDataToGpuAsync()
|
||||||
@@ -314,7 +318,10 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/** async is done so each thread can run without waiting on others */
|
/**
|
||||||
|
* async is done so each thread can run without waiting on others
|
||||||
|
* @param direction the direction to load relative to the given position, null will return the given position
|
||||||
|
*/
|
||||||
private CompletableFuture<ColumnRenderSource> getRenderSourceForPosAsync(long pos, @Nullable EDhDirection direction)
|
private CompletableFuture<ColumnRenderSource> getRenderSourceForPosAsync(long pos, @Nullable EDhDirection direction)
|
||||||
{
|
{
|
||||||
if (direction != null)
|
if (direction != null)
|
||||||
@@ -400,11 +407,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion render data uploading
|
||||||
|
|
||||||
|
|
||||||
//========================//
|
|
||||||
// getters and properties //
|
//====================//
|
||||||
//========================//
|
// enabling rendering //
|
||||||
|
//====================//
|
||||||
|
//region enabling rendering
|
||||||
|
|
||||||
public boolean canRender() { return this.bufferContainer != null; }
|
public boolean canRender() { return this.bufferContainer != null; }
|
||||||
|
|
||||||
@@ -439,11 +449,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
|
|
||||||
public boolean gpuUploadInProgress() { return this.getAndBuildRenderDataFuture != null; }
|
public boolean gpuUploadInProgress() { return this.getAndBuildRenderDataFuture != null; }
|
||||||
|
|
||||||
|
//endregion enabling rendering
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=================================//
|
//=================================//
|
||||||
// full data retrieval (world gen) //
|
// full data retrieval (world gen) //
|
||||||
//=================================//
|
//=================================//
|
||||||
|
//region full data retrieval
|
||||||
|
|
||||||
public boolean isFullyGenerated()
|
public boolean isFullyGenerated()
|
||||||
{
|
{
|
||||||
@@ -551,11 +564,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion full data retrieval
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=================//
|
//=================//
|
||||||
// beacon handling //
|
// beacon handling //
|
||||||
//=================//
|
//=================//
|
||||||
|
//region beacon handling
|
||||||
|
|
||||||
/** gets the active beacon list and stops/starts beacon rendering as necessary */
|
/** gets the active beacon list and stops/starts beacon rendering as necessary */
|
||||||
private void getAndRefreshRenderingBeacons()
|
private void getAndRefreshRenderingBeacons()
|
||||||
@@ -629,11 +645,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion beacon handling
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
// base methods //
|
// base methods //
|
||||||
//==============//
|
//==============//
|
||||||
|
//region base methods
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debugRender(DebugRenderer debugRenderer)
|
public void debugRender(DebugRenderer debugRenderer)
|
||||||
@@ -720,6 +739,8 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//endregion base methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,13 +56,13 @@ public class GLProxy
|
|||||||
|
|
||||||
public static final Set<String> LOGGED_GL_MESSAGES = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
|
public static final Set<String> LOGGED_GL_MESSAGES = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
|
||||||
|
|
||||||
|
private static final ConcurrentLinkedQueue<Runnable> RENDER_THREAD_RUNNABLE_QUEUE = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static GLProxy instance = null;
|
private static GLProxy instance = null;
|
||||||
|
|
||||||
|
|
||||||
private final ConcurrentLinkedQueue<Runnable> renderThreadRunnableQueue = new ConcurrentLinkedQueue<>();
|
|
||||||
|
|
||||||
/** Minecraft's GL capabilities */
|
/** Minecraft's GL capabilities */
|
||||||
public final GLCapabilities glCapabilities;
|
public final GLCapabilities glCapabilities;
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ public class GLProxy
|
|||||||
return uploadOverride;
|
return uploadOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean runningOnRenderThread()
|
public static boolean runningOnRenderThread()
|
||||||
{
|
{
|
||||||
long currentContext = GLFW.glfwGetCurrentContext();
|
long currentContext = GLFW.glfwGetCurrentContext();
|
||||||
return currentContext != 0L; // if the context isn't null, it's the MC context
|
return currentContext != 0L; // if the context isn't null, it's the MC context
|
||||||
@@ -243,12 +243,12 @@ public class GLProxy
|
|||||||
// Worker Thread Runnables //
|
// Worker Thread Runnables //
|
||||||
//=========================//
|
//=========================//
|
||||||
|
|
||||||
public void queueRunningOnRenderThread(Runnable renderCall)
|
public static void queueRunningOnRenderThread(Runnable renderCall)
|
||||||
{
|
{
|
||||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||||
this.renderThreadRunnableQueue.add(() -> this.runOpenGlCall(renderCall, stackTrace));
|
RENDER_THREAD_RUNNABLE_QUEUE.add(() -> runOpenGlCall(renderCall, stackTrace));
|
||||||
}
|
}
|
||||||
private void runOpenGlCall(Runnable renderCall, StackTraceElement[] stackTrace)
|
private static void runOpenGlCall(Runnable renderCall, StackTraceElement[] stackTrace)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -266,11 +266,11 @@ public class GLProxy
|
|||||||
* Doesn't do any thread/GL Context validation.
|
* Doesn't do any thread/GL Context validation.
|
||||||
* Running this outside of the render thread may cause crashes or other issues.
|
* Running this outside of the render thread may cause crashes or other issues.
|
||||||
*/
|
*/
|
||||||
public void runRenderThreadTasks()
|
public static void runRenderThreadTasks()
|
||||||
{
|
{
|
||||||
long startTime = System.nanoTime();
|
long startTime = System.nanoTime();
|
||||||
|
|
||||||
Runnable runnable = this.renderThreadRunnableQueue.poll();
|
Runnable runnable = RENDER_THREAD_RUNNABLE_QUEUE.poll();
|
||||||
while(runnable != null)
|
while(runnable != null)
|
||||||
{
|
{
|
||||||
runnable.run();
|
runnable.run();
|
||||||
@@ -283,7 +283,7 @@ public class GLProxy
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
runnable = this.renderThreadRunnableQueue.poll();
|
runnable = RENDER_THREAD_RUNNABLE_QUEUE.poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -100,7 +100,7 @@ public class GLBuffer implements AutoCloseable
|
|||||||
|
|
||||||
protected void create(boolean asBufferStorage)
|
protected void create(boolean asBufferStorage)
|
||||||
{
|
{
|
||||||
if (!GLProxy.getInstance().runningOnRenderThread())
|
if (!GLProxy.runningOnRenderThread())
|
||||||
{
|
{
|
||||||
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ public class GLBuffer implements AutoCloseable
|
|||||||
BUFFER_ID_TO_PHANTOM.remove(id);
|
BUFFER_ID_TO_PHANTOM.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
GLProxy.queueRunningOnRenderThread(() ->
|
||||||
{
|
{
|
||||||
// destroy the buffer if it exists,
|
// destroy the buffer if it exists,
|
||||||
// the buffer may not exist if the destroy method is called twice
|
// the buffer may not exist if the destroy method is called twice
|
||||||
|
|||||||
+2
-3
@@ -44,7 +44,7 @@ public class QuadElementBuffer extends GLElementBuffer
|
|||||||
|
|
||||||
public int getCapacity()
|
public int getCapacity()
|
||||||
{
|
{
|
||||||
return super.getSize() / GLEnums.getTypeSize(getType());
|
return super.getSize() / GLEnums.getTypeSize(this.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void buildBufferByte(int quadCount, ByteBuffer buffer)
|
private static void buildBufferByte(int quadCount, ByteBuffer buffer)
|
||||||
@@ -140,7 +140,6 @@ public class QuadElementBuffer extends GLElementBuffer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int vertexCount = quadCount * 4; // 4 vertices per quad
|
int vertexCount = quadCount * 4; // 4 vertices per quad
|
||||||
GLProxy gl = GLProxy.getInstance();
|
|
||||||
|
|
||||||
if (vertexCount < 255)
|
if (vertexCount < 255)
|
||||||
{ // Reserve 1 for the reset index
|
{ // Reserve 1 for the reset index
|
||||||
@@ -158,7 +157,7 @@ public class QuadElementBuffer extends GLElementBuffer
|
|||||||
|
|
||||||
ByteBuffer buffer = MemoryUtil.memAlloc(this.indicesCount * GLEnums.getTypeSize(this.type));
|
ByteBuffer buffer = MemoryUtil.memAlloc(this.indicesCount * GLEnums.getTypeSize(this.type));
|
||||||
buildBuffer(quadCount, buffer, this.type);
|
buildBuffer(quadCount, buffer, this.type);
|
||||||
if (!gl.bufferStorageSupported)
|
if (!GLProxy.getInstance().bufferStorageSupported)
|
||||||
{
|
{
|
||||||
|
|
||||||
this.bind();
|
this.bind();
|
||||||
|
|||||||
+1
-1
@@ -95,7 +95,7 @@ public class ShaderProgram
|
|||||||
|
|
||||||
for (int i = 0; i < attributes.length; i++)
|
for (int i = 0; i < attributes.length; i++)
|
||||||
{
|
{
|
||||||
GL32.glBindAttribLocation(id, i, attributes[i]);
|
GL32.glBindAttribLocation(this.id, i, attributes[i]);
|
||||||
}
|
}
|
||||||
GL32.glLinkProgram(this.id);
|
GL32.glLinkProgram(this.id);
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -59,8 +59,10 @@ public final class VertexPointer
|
|||||||
/** Always aligned to 4 bytes */
|
/** Always aligned to 4 bytes */
|
||||||
public static VertexPointer addUnsignedBytePointer(boolean normalized, boolean useInteger) { return new VertexPointer(1, GL32.GL_UNSIGNED_BYTE, normalized, 4, useInteger); }
|
public static VertexPointer addUnsignedBytePointer(boolean normalized, boolean useInteger) { return new VertexPointer(1, GL32.GL_UNSIGNED_BYTE, normalized, 4, useInteger); }
|
||||||
/** aligned to 4 bytes */
|
/** aligned to 4 bytes */
|
||||||
public static VertexPointer addUnsignedBytesPointer(int elementCount, boolean normalized, boolean useInteger) { return new VertexPointer(elementCount, GL32.GL_UNSIGNED_BYTE, normalized, _align(elementCount), useInteger); }
|
public static VertexPointer addUnsignedBytesPointer(int elementCount, boolean normalized, boolean useInteger)
|
||||||
public static VertexPointer addUnsignedShortsPointer(int elementCount, boolean normalized, boolean useInteger) { return new VertexPointer(elementCount, GL32.GL_UNSIGNED_SHORT, normalized, _align(elementCount * 2), useInteger); }
|
{ return new VertexPointer(elementCount, GL32.GL_UNSIGNED_BYTE, normalized, _align(elementCount), useInteger); }
|
||||||
|
public static VertexPointer addUnsignedShortsPointer(int elementCount, boolean normalized, boolean useInteger)
|
||||||
|
{ return new VertexPointer(elementCount, GL32.GL_UNSIGNED_SHORT, normalized, _align(elementCount * 2), useInteger); }
|
||||||
public static VertexPointer addShortsPointer(int elementCount, boolean normalized, boolean useInteger) { return new VertexPointer(elementCount, GL32.GL_SHORT, normalized, _align(elementCount * 2), useInteger); }
|
public static VertexPointer addShortsPointer(int elementCount, boolean normalized, boolean useInteger) { return new VertexPointer(elementCount, GL32.GL_SHORT, normalized, _align(elementCount * 2), useInteger); }
|
||||||
public static VertexPointer addIntPointer(boolean normalized, boolean useInteger) { return new VertexPointer(1, GL32.GL_INT, normalized, 4, useInteger); }
|
public static VertexPointer addIntPointer(boolean normalized, boolean useInteger) { return new VertexPointer(1, GL32.GL_INT, normalized, 4, useInteger); }
|
||||||
public static VertexPointer addIVec2Pointer(boolean normalized, boolean useInteger) { return new VertexPointer(2, GL32.GL_INT, normalized, 8, useInteger); }
|
public static VertexPointer addIVec2Pointer(boolean normalized, boolean useInteger) { return new VertexPointer(2, GL32.GL_INT, normalized, 8, useInteger); }
|
||||||
|
|||||||
+10
-7
@@ -96,16 +96,19 @@ public class DhFadeRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.fadeTexture = GL32.glGenTextures();
|
this.fadeTexture = GL32.glGenTextures();
|
||||||
GLMC.glBindTexture(this.fadeTexture);
|
{
|
||||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
GLMC.glBindTexture(this.fadeTexture);
|
||||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
||||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||||
|
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||||
|
|
||||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fadeTexture, 0);
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fadeTexture, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -64,7 +64,7 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
|||||||
public int uNoiseDropoff = -1;
|
public int uNoiseDropoff = -1;
|
||||||
|
|
||||||
// Debug Uniform
|
// Debug Uniform
|
||||||
public int uWhiteWorld = -1;
|
public int uIsWhiteWorld = -1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
|||||||
this.uNoiseDropoff = this.getUniformLocation("uNoiseDropoff");
|
this.uNoiseDropoff = this.getUniformLocation("uNoiseDropoff");
|
||||||
|
|
||||||
// Debug Uniform
|
// Debug Uniform
|
||||||
this.uWhiteWorld = this.getUniformLocation("uWhiteWorld");
|
this.uIsWhiteWorld = this.getUniformLocation("uIsWhiteWorld");
|
||||||
|
|
||||||
|
|
||||||
// TODO: Add better use of the LODFormat thing
|
// TODO: Add better use of the LODFormat thing
|
||||||
@@ -192,7 +192,7 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
|||||||
this.setUniform(this.uNoiseDropoff, Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get());
|
this.setUniform(this.uNoiseDropoff, Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get());
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
this.setUniform(this.uWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
|
this.setUniform(this.uIsWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
|
||||||
|
|
||||||
// Clip Uniform
|
// Clip Uniform
|
||||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocksForFading(renderParameters.partialTicks);
|
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocksForFading(renderParameters.partialTicks);
|
||||||
|
|||||||
+10
-8
@@ -88,15 +88,17 @@ public class FogRenderer
|
|||||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fogFramebuffer);
|
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fogFramebuffer);
|
||||||
|
|
||||||
this.fogTexture = GLMC.glGenTextures();
|
this.fogTexture = GLMC.glGenTextures();
|
||||||
GLMC.glBindTexture(this.fogTexture);
|
{
|
||||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
GLMC.glBindTexture(this.fogTexture);
|
||||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
||||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fogTexture, 0);
|
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||||
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fogTexture, 0);
|
||||||
|
|
||||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -493,12 +493,8 @@ public class LodRenderer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GLProxy.hasInstance())
|
// GLProxy should have already been created by this point, but just in case create it now
|
||||||
{
|
GLProxy.getInstance();
|
||||||
// shouldn't normally happen, but just in case
|
|
||||||
LOGGER.warn("Renderer setup called but GLProxy has not yet been setup!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-7
@@ -88,14 +88,16 @@ public class SSAORenderer
|
|||||||
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
|
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
|
||||||
|
|
||||||
this.ssaoTexture = GLMC.glGenTextures();
|
this.ssaoTexture = GLMC.glGenTextures();
|
||||||
GLMC.glBindTexture(this.ssaoTexture);
|
{
|
||||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (ByteBuffer) null);
|
GLMC.glBindTexture(this.ssaoTexture);
|
||||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (ByteBuffer) null);
|
||||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||||
|
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||||
|
|
||||||
// disable mip-mapping since DH is just going to draw straight to the screen
|
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0);
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -337,7 +337,7 @@ public class RenderableBoxGroup
|
|||||||
@Override
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
GLProxy.queueRunningOnRenderThread(() ->
|
||||||
{
|
{
|
||||||
if (this.instanceChunkPosVbo != 0)
|
if (this.instanceChunkPosVbo != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
+8
@@ -178,6 +178,14 @@ public class FogShader extends AbstractShaderRenderer
|
|||||||
float farFogMax = Config.Client.Advanced.Graphics.Fog.farFogMax.get().floatValue();
|
float farFogMax = Config.Client.Advanced.Graphics.Fog.farFogMax.get().floatValue();
|
||||||
float farFogDensity = Config.Client.Advanced.Graphics.Fog.farFogDensity.get().floatValue();
|
float farFogDensity = Config.Client.Advanced.Graphics.Fog.farFogDensity.get().floatValue();
|
||||||
|
|
||||||
|
// override fog if underwater
|
||||||
|
if (MC_RENDER.isFogStateSpecial())
|
||||||
|
{
|
||||||
|
// hide everything behind fog
|
||||||
|
farFogStart = 0.0f;
|
||||||
|
farFogEnd = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
this.shader.setUniform(this.uFarFogStart, farFogStart);
|
this.shader.setUniform(this.uFarFogStart, farFogStart);
|
||||||
this.shader.setUniform(this.uFarFogLength, farFogEnd - farFogStart);
|
this.shader.setUniform(this.uFarFogLength, farFogEnd - farFogStart);
|
||||||
this.shader.setUniform(this.uFarFogMin, farFogMin);
|
this.shader.setUniform(this.uFarFogMin, farFogMin);
|
||||||
|
|||||||
+8
@@ -25,8 +25,10 @@ import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
|||||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.SSAORenderer;
|
import com.seibel.distanthorizons.core.render.renderer.SSAORenderer;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||||
|
import com.seibel.distanthorizons.core.util.NumberUtil;
|
||||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
|
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +60,7 @@ public class SSAOShader extends AbstractShaderRenderer
|
|||||||
public int uMinLight;
|
public int uMinLight;
|
||||||
public int uBias;
|
public int uBias;
|
||||||
public int uDepthMap;
|
public int uDepthMap;
|
||||||
|
public int uFadeDistanceInBlocks;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -81,6 +84,7 @@ public class SSAOShader extends AbstractShaderRenderer
|
|||||||
this.uMinLight = this.shader.getUniformLocation("uMinLight");
|
this.uMinLight = this.shader.getUniformLocation("uMinLight");
|
||||||
this.uBias = this.shader.getUniformLocation("uBias");
|
this.uBias = this.shader.getUniformLocation("uBias");
|
||||||
this.uDepthMap = this.shader.getUniformLocation("uDepthMap");
|
this.uDepthMap = this.shader.getUniformLocation("uDepthMap");
|
||||||
|
this.uFadeDistanceInBlocks = this.shader.getUniformLocation("uFadeDistanceInBlocks");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -120,6 +124,10 @@ public class SSAOShader extends AbstractShaderRenderer
|
|||||||
this.shader.setUniform(this.uBias, bias.floatValue());
|
this.shader.setUniform(this.uBias, bias.floatValue());
|
||||||
|
|
||||||
GL32.glUniform1i(this.uDepthMap, 0);
|
GL32.glUniform1i(this.uDepthMap, 0);
|
||||||
|
|
||||||
|
float fadeDistanceInBlocks = Config.Client.Advanced.Graphics.Ssao.fadeDistanceInBlocks.get().floatValue();
|
||||||
|
fadeDistanceInBlocks = MathUtil.clamp(0.0f, fadeDistanceInBlocks, Float.MAX_VALUE); // clamp to prevent accidentally setting a negative number
|
||||||
|
this.shader.setUniform(this.uFadeDistanceInBlocks, fadeDistanceInBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.seibel.distanthorizons.core.util;
|
||||||
|
|
||||||
|
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be used instead of the direct call to {@link TinyFileDialogs}
|
||||||
|
* so we can run additional validation and/or string cleanup.
|
||||||
|
* Otherwise, we may get error messages back.
|
||||||
|
*
|
||||||
|
* @see TinyFileDialogs
|
||||||
|
*/
|
||||||
|
public class NativeDialogUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param dialogType the dialog type. One of:<br><table><tr><td>"ok"</td><td>"okcancel"</td><td>"yesno"</td><td>"yesnocancel"</td></tr></table>
|
||||||
|
* @param iconType the icon type. One of:<br><table><tr><td>"info"</td><td>"warning"</td><td>"error"</td><td>"question"</td></tr></table>
|
||||||
|
*/
|
||||||
|
public static boolean showDialog(String title, String message, String dialogType, String iconType)
|
||||||
|
{
|
||||||
|
// Tinyfd doesn't support the following characters, attempting to display them will cause the message
|
||||||
|
// to be replaced with an error message
|
||||||
|
String unsafeCharsRegex = "['\"`]";
|
||||||
|
|
||||||
|
title = title.replaceAll(unsafeCharsRegex, "`");
|
||||||
|
message = message.replaceAll(unsafeCharsRegex, "`");
|
||||||
|
|
||||||
|
return TinyFileDialogs.tinyfd_messageBox(title, message, dialogType, iconType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.core.util.objects;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.CompletionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
public class EventLoop implements AutoCloseable
|
|
||||||
{
|
|
||||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
|
||||||
|
|
||||||
private final boolean PAUSE_ON_ERROR = ModInfo.IS_DEV_BUILD;
|
|
||||||
private final ExecutorService executorService;
|
|
||||||
|
|
||||||
private final Runnable runnable;
|
|
||||||
/** the future related to the given runnable */
|
|
||||||
private CompletableFuture<Void> runnableFuture;
|
|
||||||
|
|
||||||
private boolean isRunning = true;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public EventLoop(ExecutorService executorService, Runnable runnable)
|
|
||||||
{
|
|
||||||
this.executorService = executorService;
|
|
||||||
this.runnable = runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void tick()
|
|
||||||
{
|
|
||||||
if (runnableFuture != null && runnableFuture.isDone())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
runnableFuture.join();
|
|
||||||
}
|
|
||||||
catch (CompletionException ce)
|
|
||||||
{
|
|
||||||
LOGGER.error("Uncaught exception in event loop", ce.getCause());
|
|
||||||
if (PAUSE_ON_ERROR)
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
LOGGER.error("Exception in event loop", e);
|
|
||||||
if (PAUSE_ON_ERROR)
|
|
||||||
{
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
runnableFuture = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runnableFuture == null && isRunning)
|
|
||||||
{
|
|
||||||
runnableFuture = CompletableFuture.runAsync(runnable, executorService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close()
|
|
||||||
{
|
|
||||||
if (runnableFuture != null)
|
|
||||||
{
|
|
||||||
runnableFuture.cancel(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
runnableFuture = null;
|
|
||||||
executorService.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRunning() { return runnableFuture != null && !runnableFuture.isDone(); }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -21,27 +21,21 @@ package com.seibel.distanthorizons.core.world;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.core.level.DhClientServerLevel;
|
import com.seibel.distanthorizons.core.level.DhClientServerLevel;
|
||||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||||
import com.seibel.distanthorizons.core.util.objects.EventLoop;
|
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
public class DhClientServerWorld extends AbstractDhServerWorld<DhClientServerLevel> implements IDhClientWorld
|
public class DhClientServerWorld extends AbstractDhServerWorld<DhClientServerLevel> implements IDhClientWorld
|
||||||
{
|
{
|
||||||
private final Set<DhClientServerLevel> dhLevels = Collections.synchronizedSet(new HashSet<>());
|
private final Set<DhClientServerLevel> dhLevels = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
public ExecutorService dhTickerThread = ThreadUtil.makeSingleThreadPool("Client Server World Ticker", 2);
|
private final Timer clientTickTimer = TimerUtil.CreateTimer("ClientTickTimer");
|
||||||
public EventLoop eventLoop = new EventLoop(this.dhTickerThread, this::_clientTick); //TODO: Rate-limit the loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -53,6 +47,15 @@ public class DhClientServerWorld extends AbstractDhServerWorld<DhClientServerLev
|
|||||||
{
|
{
|
||||||
super(EWorldEnvironment.CLIENT_SERVER);
|
super(EWorldEnvironment.CLIENT_SERVER);
|
||||||
LOGGER.info("Started DhWorld of type " + this.environment);
|
LOGGER.info("Started DhWorld of type " + this.environment);
|
||||||
|
|
||||||
|
this.clientTickTimer.scheduleAtFixedRate(new TimerTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
DhClientServerWorld.this.dhLevels.forEach(DhClientServerLevel::clientTick);
|
||||||
|
}
|
||||||
|
}, 0, IDhClientWorld.TICK_RATE_IN_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,19 +139,6 @@ public class DhClientServerWorld extends AbstractDhServerWorld<DhClientServerLev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _clientTick()
|
|
||||||
{
|
|
||||||
//LOGGER.info("Client world tick with {} levels", levels.size());
|
|
||||||
this.dhLevels.forEach(DhClientServerLevel::clientTick);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clientTick()
|
|
||||||
{
|
|
||||||
//LOGGER.info("Client world tick");
|
|
||||||
this.eventLoop.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
@@ -194,8 +184,8 @@ public class DhClientServerWorld extends AbstractDhServerWorld<DhClientServerLev
|
|||||||
|
|
||||||
|
|
||||||
this.dhLevelByLevelWrapper.clear();
|
this.dhLevelByLevelWrapper.clear();
|
||||||
this.eventLoop.close();
|
this.clientTickTimer.cancel();
|
||||||
LOGGER.info("Closed DhWorld of type " + this.environment);
|
LOGGER.info("Closed DhWorld of type [" + this.environment + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,17 +24,17 @@ import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
|||||||
import com.seibel.distanthorizons.core.level.DhClientLevel;
|
import com.seibel.distanthorizons.core.level.DhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.multiplayer.client.ClientNetworkState;
|
import com.seibel.distanthorizons.core.multiplayer.client.ClientNetworkState;
|
||||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||||
import com.seibel.distanthorizons.core.util.objects.EventLoop;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
||||||
{
|
{
|
||||||
@@ -42,8 +42,7 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
|||||||
public final ClientOnlySaveStructure saveStructure;
|
public final ClientOnlySaveStructure saveStructure;
|
||||||
public final ClientNetworkState networkState = new ClientNetworkState();
|
public final ClientNetworkState networkState = new ClientNetworkState();
|
||||||
|
|
||||||
public final ExecutorService dhTickerThread = ThreadUtil.makeSingleThreadPool("Client World Ticker");
|
private final Timer clientTickTimer = TimerUtil.CreateTimer("ClientTickTimer");
|
||||||
public final EventLoop eventLoop = new EventLoop(this.dhTickerThread, this::_clientTick);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -59,6 +58,15 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
|||||||
this.levels = new ConcurrentHashMap<>();
|
this.levels = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
LOGGER.info("Started DhWorld of type " + this.environment);
|
LOGGER.info("Started DhWorld of type " + this.environment);
|
||||||
|
|
||||||
|
this.clientTickTimer.scheduleAtFixedRate(new TimerTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
DhClientWorld.this.levels.values().forEach(DhClientLevel::clientTick);
|
||||||
|
}
|
||||||
|
}, 0, IDhClientWorld.TICK_RATE_IN_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -127,11 +135,6 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _clientTick() { this.levels.values().forEach(DhClientLevel::clientTick); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clientTick() { this.eventLoop.tick(); }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDebugMenuStringsToList(List<String> messageList)
|
public void addDebugMenuStringsToList(List<String> messageList)
|
||||||
{
|
{
|
||||||
@@ -143,7 +146,6 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
|||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
this.networkState.close();
|
this.networkState.close();
|
||||||
this.dhTickerThread.shutdownNow();
|
|
||||||
|
|
||||||
ArrayList<CompletableFuture<Void>> closeFutures = new ArrayList<>();
|
ArrayList<CompletableFuture<Void>> closeFutures = new ArrayList<>();
|
||||||
for (DhClientLevel dhClientLevel : this.levels.values())
|
for (DhClientLevel dhClientLevel : this.levels.values())
|
||||||
@@ -175,7 +177,7 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.levels.clear();
|
this.levels.clear();
|
||||||
this.eventLoop.close();
|
this.clientTickTimer.cancel();
|
||||||
LOGGER.info("Closed DhWorld of type [" + this.environment + "].");
|
LOGGER.info("Closed DhWorld of type [" + this.environment + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
|||||||
|
|
||||||
public interface IDhClientWorld extends IDhWorld
|
public interface IDhClientWorld extends IDhWorld
|
||||||
{
|
{
|
||||||
void clientTick();
|
/** how long in between client ticks in milliseconds */
|
||||||
|
long TICK_RATE_IN_MS = 100L;
|
||||||
|
|
||||||
default IDhClientLevel getOrLoadClientLevel(ILevelWrapper levelWrapper) { return (IDhClientLevel) this.getOrLoadLevel(levelWrapper); }
|
default IDhClientLevel getOrLoadClientLevel(ILevelWrapper levelWrapper) { return (IDhClientLevel) this.getOrLoadLevel(levelWrapper); }
|
||||||
default IDhClientLevel getClientLevel(ILevelWrapper levelWrapper) { return (IDhClientLevel) this.getLevel(levelWrapper); }
|
default IDhClientLevel getClientLevel(ILevelWrapper levelWrapper) { return (IDhClientLevel) this.getLevel(levelWrapper); }
|
||||||
|
|||||||
-2
@@ -126,8 +126,6 @@ public interface IChunkWrapper extends IBindable
|
|||||||
|
|
||||||
IBiomeWrapper getBiome(int relX, int relY, int relZ);
|
IBiomeWrapper getBiome(int relX, int relY, int relZ);
|
||||||
|
|
||||||
boolean isStillValid();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//========================//
|
//========================//
|
||||||
|
|||||||
+4
@@ -52,6 +52,10 @@ public interface ILevelWrapper extends IDhApiLevelWrapper, IBindable
|
|||||||
@Override
|
@Override
|
||||||
IDimensionTypeWrapper getDimensionType();
|
IDimensionTypeWrapper getDimensionType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes both the namespace and name. <br>
|
||||||
|
* example: "minecraft:overworld"
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
String getDimensionName();
|
String getDimensionName();
|
||||||
|
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"Blur Radius",
|
"Blur Radius",
|
||||||
"distanthorizons.config.client.advanced.graphics.ssao.blurRadius.@tooltip":
|
"distanthorizons.config.client.advanced.graphics.ssao.blurRadius.@tooltip":
|
||||||
"The radius, measured in pixels, that blurring is calculated for the SSAO. \nHigher numbers will reduce banding at the cost of GPU performance.",
|
"The radius, measured in pixels, that blurring is calculated for the SSAO. \nHigher numbers will reduce banding at the cost of GPU performance.",
|
||||||
|
"distanthorizons.config.client.advanced.graphics.ssao.fadeDistanceInBlocks":
|
||||||
|
"Fade Distance",
|
||||||
|
"distanthorizons.config.client.advanced.graphics.ssao.fadeDistanceInBlocks.@tooltip":
|
||||||
|
"The distance in blocks from the camera where the SSAO will fade out to. \nThis is done to prevent banding and noise at extreme distances.",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -733,6 +737,8 @@
|
|||||||
"Show Slow World Gen Warnings",
|
"Show Slow World Gen Warnings",
|
||||||
"distanthorizons.config.common.logging.warning.showModCompatibilityWarningsOnStartup":
|
"distanthorizons.config.common.logging.warning.showModCompatibilityWarningsOnStartup":
|
||||||
"Show Mod Compatibility Warnings",
|
"Show Mod Compatibility Warnings",
|
||||||
|
"distanthorizons.config.common.logging.warning.logGarbageCollectorWarning":
|
||||||
|
"Log Garbage Collector Warning",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ uniform float uMinLight;
|
|||||||
uniform float uBias;
|
uniform float uBias;
|
||||||
uniform mat4 uInvProj;
|
uniform mat4 uInvProj;
|
||||||
uniform mat4 uProj;
|
uniform mat4 uProj;
|
||||||
|
uniform float uFadeDistanceInBlocks;
|
||||||
|
|
||||||
const float EPSILON = 1.e-6;
|
const float EPSILON = 1.e-6;
|
||||||
const float GOLDEN_ANGLE = 2.39996323;
|
const float GOLDEN_ANGLE = 2.39996323;
|
||||||
@@ -99,16 +100,30 @@ void main()
|
|||||||
{
|
{
|
||||||
vec3 viewPos = calcViewPosition(vec3(TexCoord, fragmentDepth));
|
vec3 viewPos = calcViewPosition(vec3(TexCoord, fragmentDepth));
|
||||||
|
|
||||||
#ifdef GL_ARB_derivative_control
|
// fading is done to prevent banding/noise
|
||||||
// Get higher precision derivatives when available
|
// at super far distance
|
||||||
vec3 viewNormal = cross(dFdxFine(viewPos.xyz), dFdyFine(viewPos.xyz));
|
float distanceFromCamera = length(viewPos);
|
||||||
#else
|
float fadeDistance = uFadeDistanceInBlocks;
|
||||||
vec3 viewNormal = cross(dFdx(viewPos.xyz), dFdy(viewPos.xyz));
|
if (distanceFromCamera < fadeDistance)
|
||||||
#endif
|
{
|
||||||
|
#ifdef GL_ARB_derivative_control
|
||||||
|
// Get higher precision derivatives when available
|
||||||
|
vec3 viewNormal = cross(dFdxFine(viewPos.xyz), dFdyFine(viewPos.xyz));
|
||||||
|
#else
|
||||||
|
vec3 viewNormal = cross(dFdx(viewPos.xyz), dFdy(viewPos.xyz));
|
||||||
|
#endif
|
||||||
|
|
||||||
viewNormal = normalize(viewNormal);
|
viewNormal = normalize(viewNormal);
|
||||||
|
occlusion = GetSpiralOcclusion(TexCoord, viewPos, viewNormal);
|
||||||
|
|
||||||
occlusion = GetSpiralOcclusion(TexCoord, viewPos, viewNormal);
|
// linearly fade with distance
|
||||||
|
occlusion *= (fadeDistance - distanceFromCamera) / fadeDistance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we're out of range, no need to do any SSAO calculations
|
||||||
|
occlusion = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fragColor = vec4(vec3(1.0 - occlusion), 1.0);
|
fragColor = vec4(vec3(1.0 - occlusion), 1.0);
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ out vec4 vertexColor;
|
|||||||
out vec3 vertexWorldPos;
|
out vec3 vertexWorldPos;
|
||||||
out float vertexYPos;
|
out float vertexYPos;
|
||||||
|
|
||||||
uniform bool uWhiteWorld;
|
uniform bool uIsWhiteWorld;
|
||||||
|
|
||||||
uniform mat4 uCombinedMatrix;
|
uniform mat4 uCombinedMatrix;
|
||||||
uniform vec3 uModelOffset;
|
uniform vec3 uModelOffset;
|
||||||
uniform float uWorldYOffset;
|
uniform float uWorldYOffset;
|
||||||
|
|
||||||
uniform int uWorldSkyLight;
|
|
||||||
uniform sampler2D uLightMap;
|
uniform sampler2D uLightMap;
|
||||||
uniform float uMircoOffset;
|
uniform float uMircoOffset;
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ void main()
|
|||||||
float light = (float(lights/16u)+0.5) / 16.0;
|
float light = (float(lights/16u)+0.5) / 16.0;
|
||||||
vertexColor = vec4(texture(uLightMap, vec2(light, light2)).xyz, 1.0);
|
vertexColor = vec4(texture(uLightMap, vec2(light, light2)).xyz, 1.0);
|
||||||
|
|
||||||
if (!uWhiteWorld)
|
if (!uIsWhiteWorld)
|
||||||
{
|
{
|
||||||
vertexColor *= color;
|
vertexColor *= color;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user