Compare commits

...

23 Commits

Author SHA1 Message Date
James Seibel 6feb7f1b42 remove dev from version number 2025-12-14 13:46:04 -06:00
James Seibel 016fc66293 Print a warning if G1GC is used
G1GC is known to cause stuttering
2025-12-13 16:46:59 -06:00
James Seibel 6d3e30d425 add Zstd decompress lib check in initalizer 2025-12-13 15:48:05 -06:00
James Seibel 5be5c5a5bc replace client ticks with a timer
Prevents DH loading issues when MC ticks are paused
2025-12-13 11:19:33 -06:00
James Seibel ed5aeb8951 minor texture setup reformatting 2025-12-13 10:43:01 -06:00
James Seibel 7f0ddadf26 up version number 2.4.0 -> 2.4.1-dev 2025-12-13 10:20:44 -06:00
James Seibel a2c61ed278 up version number 2.3.7 -> 2.4.0 2025-12-13 10:19:50 -06:00
James Seibel 99eb4ac8a1 Fix infinite loop in DhSectionPos 2025-12-13 09:10:12 -06:00
James Seibel c75902d9d6 debug particle cleanup 2025-12-13 08:50:15 -06:00
James Seibel 1743949ba5 fix GeneratedFullDataSourceProvider not adding update listener 2025-12-13 08:49:45 -06:00
James Seibel a74a37a0e8 world gen queue refactoring 2025-12-13 08:49:31 -06:00
James Seibel 4ed7941288 fix missing localization 2025-12-12 07:45:12 -06:00
James Seibel ec59a5f754 comment cleanup and enum renaming for API use 2025-12-11 07:35:37 -06:00
James Seibel 895e04b7cc Remove unused wrapper functions and refactor 2025-12-10 18:50:35 -06:00
James Seibel 8f0930fa02 Allow world gen limits on singleplayer 2025-12-10 07:09:29 -06:00
James Seibel c1c4328fa5 rename API getSoftCache -> createSoftCahe 2025-12-09 20:57:27 -06:00
James Seibel 91240e4f7a disable mip-mapping on textures
necessary to fix MC 1.21.11 rendering
2025-12-09 20:57:09 -06:00
James Seibel 17c61a97cc revert long windows filepath char 2025-12-09 07:21:40 -06:00
James Seibel b78b852ffb Merge branch 'batchGenRefactor' 2025-12-09 07:16:18 -06:00
James Seibel 5edc73cc03 enable long file paths for the config file 2025-12-06 12:28:22 -06:00
James Seibel 6fcfc9379e Fix repo unit tests 2025-12-06 12:27:53 -06:00
James Seibel 149fbccfa5 Merge branch 'batchGenRefactor' 2025-12-06 12:19:17 -06:00
James Seibel 4e9559f230 enable long file paths on windows for the DB 2025-12-02 07:07:17 -06:00
70 changed files with 480 additions and 592 deletions
@@ -39,10 +39,6 @@ package com.seibel.distanthorizons.api.enums;
*/ */
public enum EDhApiDetailLevel public enum EDhApiDetailLevel
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* detail level: 0 <Br> * detail level: 0 <Br>
* width in Blocks: 1 * width in Blocks: 1
@@ -28,10 +28,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiBlocksToAvoid public enum EDhApiBlocksToAvoid
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
NONE(false), NONE(false),
NON_COLLIDING(true); NON_COLLIDING(true);
@@ -23,6 +23,7 @@ package com.seibel.distanthorizons.api.enums.config;
* UNCOMPRESSED <br> * UNCOMPRESSED <br>
* LZ4 <br> * LZ4 <br>
* Z_STD <br> * Z_STD <br>
* Z_STD_STREAM <br>
* LZMA2 <br><br> * LZMA2 <br><br>
* *
* Note: speed and compression ratios are examples * Note: speed and compression ratios are examples
@@ -33,10 +34,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiDataCompressionMode public enum EDhApiDataCompressionMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* Should only be used internally and for unit testing. <br><br> * Should only be used internally and for unit testing. <br><br>
* *
@@ -57,27 +54,31 @@ public enum EDhApiDataCompressionMode
LZ4(1), LZ4(1),
/** /**
* Decent speed and good compression. <br><br> * Great speed and good compression. <br><br>
*
* Read Speed: 2.1 MS / DTO <br>
* Write Speed: 4.9 MS / DTO <br>
* Compression ratio: 0.2606 <br>
*/
Z_STD_BLOCK(4),
/**
* Similar to {@link EDhApiDataCompressionMode#Z_STD_BLOCK}
* except slower. <br><br>
*
* This option is only provided for legacy support when processing old databases. <br><br>
* *
* Read Speed: 9.31 MS / DTO <br> * Read Speed: 9.31 MS / DTO <br>
* Write Speed: 15.13 MS / DTO <br> * Write Speed: 15.13 MS / DTO <br>
* Compression ratio: 0.2606 <br> * Compression ratio: 0.2606 <br>
*/ */
Z_STD(4),
/**
* Similar to {@link EDhApiDataCompressionMode#Z_STD}
* except slower.
* <br>
* This option is only provided for legacy support when processing old databases.
*/
@Deprecated @Deprecated
@DisallowSelectingViaConfigGui @DisallowSelectingViaConfigGui
Z_STD_STREAM(2), Z_STD_STREAM(2),
/** /**
* Extremely slow, but very good compression. <br><br> * Extremely slow, but very good compression. <br>
* Often causes whole computer stuttering due to memory bandwidth saturation. <br><br>
* *
* Read Speed: 13.29 MS / DTO <br> * Read Speed: 13.29 MS / DTO <br>
* Write Speed: 70.95 MS / DTO <br> * Write Speed: 70.95 MS / DTO <br>
@@ -44,9 +44,9 @@ public enum EDhApiGpuUploadMethod
/** Fast rendering but may stutter when uploading. */ /** Fast rendering but may stutter when uploading. */
SUB_DATA(false, false), SUB_DATA(false, false),
/** Don't upload, only should be used for debugging */ ///** Don't upload, only should be used for debugging */
@Deprecated // TODO remove before release //@Deprecated
NONE(false, false), //NONE(false, false),
/** /**
* May end up storing buffers in System memory. <br> * May end up storing buffers in System memory. <br>
@@ -29,10 +29,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiGrassSideRendering public enum EDhApiGrassSideRendering
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
AS_GRASS, AS_GRASS,
FADE_TO_DIRT, FADE_TO_DIRT,
AS_DIRT; AS_DIRT;
@@ -31,11 +31,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiHorizontalQuality public enum EDhApiHorizontalQuality
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
// Note: any quadraticBase less than 2.0f has issues with DetailDistanceUtil, and will always return the lowest detail level. // Note: any quadraticBase less than 2.0f has issues with DetailDistanceUtil, and will always return the lowest detail level.
// So for now we are limiting the lowest value to 2.0 // So for now we are limiting the lowest value to 2.0
// LOWEST was originally 1.0f and LOW was 1.5f // LOWEST was originally 1.0f and LOW was 1.5f
@@ -29,10 +29,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiLodShading public enum EDhApiLodShading
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* Uses Minecraft's shading for LODs. <Br> * Uses Minecraft's shading for LODs. <Br>
* This means if Minecraft's shading is disabled DH's shading will be as well. * This means if Minecraft's shading is disabled DH's shading will be as well.
@@ -33,10 +33,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiMcRenderingFadeMode public enum EDhApiMcRenderingFadeMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* No fading is done, there will be a pronounced border between * No fading is done, there will be a pronounced border between
* Minecraft and Distant Horizons. <br> * Minecraft and Distant Horizons. <br>
@@ -35,11 +35,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiServerFolderNameMode public enum EDhApiServerFolderNameMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** Only use the server name */ /** Only use the server name */
NAME_ONLY, NAME_ONLY,
@@ -34,11 +34,6 @@ package com.seibel.distanthorizons.api.enums.config;
@Deprecated // not currently in use, if the config this enum represents is re-implemented, the deprecated flag can be removed @Deprecated // not currently in use, if the config this enum represents is re-implemented, the deprecated flag can be removed
public enum EDhApiVanillaOverdraw public enum EDhApiVanillaOverdraw
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* Don't draw LODs where a minecraft chunk could be. * Don't draw LODs where a minecraft chunk could be.
* Use Overdraw Offset to tweak the border thickness. * Use Overdraw Offset to tweak the border thickness.
@@ -28,10 +28,6 @@ package com.seibel.distanthorizons.api.enums.config;
*/ */
public enum EDhApiWorldCompressionMode public enum EDhApiWorldCompressionMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* Every block/biome change is recorded in the database. <br> * Every block/biome change is recorded in the database. <br>
* This is what DH 2.0 and 2.0.1 all used by default and will store a lot of data. * This is what DH 2.0 and 2.0.1 all used by default and will store a lot of data.
@@ -35,10 +35,6 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui
*/ */
public enum EDhApiQualityPreset public enum EDhApiQualityPreset
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
@DisallowSelectingViaConfigGui @DisallowSelectingViaConfigGui
CUSTOM, CUSTOM,
@@ -34,10 +34,6 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui
*/ */
public enum EDhApiThreadPreset public enum EDhApiThreadPreset
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
@DisallowSelectingViaConfigGui @DisallowSelectingViaConfigGui
CUSTOM, CUSTOM,
@@ -33,11 +33,6 @@ package com.seibel.distanthorizons.api.enums.rendering;
*/ */
public enum EDhApiDebugRendering public enum EDhApiDebugRendering
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** LODs are rendered normally */ /** LODs are rendered normally */
OFF, OFF,
@@ -33,10 +33,6 @@ package com.seibel.distanthorizons.api.enums.rendering;
@Deprecated @Deprecated
public enum EDhApiFogDrawMode public enum EDhApiFogDrawMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** /**
* Use whatever Fog setting Optifine is using. * Use whatever Fog setting Optifine is using.
* If Optifine isn't installed this defaults to {@link EDhApiFogDrawMode#FOG_ENABLED}. * If Optifine isn't installed this defaults to {@link EDhApiFogDrawMode#FOG_ENABLED}.
@@ -30,11 +30,6 @@ package com.seibel.distanthorizons.api.enums.rendering;
*/ */
public enum EDhApiFogFalloff public enum EDhApiFogFalloff
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
LINEAR(0), LINEAR(0),
EXPONENTIAL(1), EXPONENTIAL(1),
EXPONENTIAL_SQUARED(2); EXPONENTIAL_SQUARED(2);
@@ -33,11 +33,6 @@ package com.seibel.distanthorizons.api.enums.rendering;
*/ */
public enum EDhApiHeightFogDirection public enum EDhApiHeightFogDirection
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
ABOVE_CAMERA (true, true, false), ABOVE_CAMERA (true, true, false),
BELOW_CAMERA (true, false, true), BELOW_CAMERA (true, false, true),
ABOVE_AND_BELOW_CAMERA (true, true, true), ABOVE_AND_BELOW_CAMERA (true, true, true),
@@ -29,11 +29,6 @@ package com.seibel.distanthorizons.api.enums.rendering;
*/ */
public enum EDhApiRendererMode public enum EDhApiRendererMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
DEFAULT, DEFAULT,
DEBUG, DEBUG,
DISABLED; DISABLED;
@@ -29,11 +29,6 @@ package com.seibel.distanthorizons.api.enums.rendering;
*/ */
public enum EDhApiTransparency public enum EDhApiTransparency
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
DISABLED(false, false), DISABLED(false, false),
FAKE(true, true), FAKE(true, true),
COMPLETE(true, false); COMPLETE(true, false);
@@ -34,11 +34,6 @@ package com.seibel.distanthorizons.api.enums.worldGeneration;
*/ */
public enum EDhApiDistantGeneratorMode public enum EDhApiDistantGeneratorMode
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
/** Don't generate any new terrain, just generate LODs for already generated chunks. */ /** Don't generate any new terrain, just generate LODs for already generated chunks. */
PRE_EXISTING_ONLY((byte) 1), PRE_EXISTING_ONLY((byte) 1),
@@ -31,11 +31,6 @@ package com.seibel.distanthorizons.api.enums.worldGeneration;
*/ */
public enum EDhApiDistantGeneratorProgressDisplayLocation public enum EDhApiDistantGeneratorProgressDisplayLocation
{ {
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
OVERLAY, OVERLAY,
CHAT, CHAT,
LOG, LOG,
@@ -161,9 +161,16 @@ public interface IDhApiTerrainDataRepo
//=========// //=========//
/** /**
* Creates a new cache you manage that can be used to speed up repeat
* read operations. <br>
* Without a cache each operation must: hit the backing database file,
* decompress it, and parse it; which is a fairly slow process. <br>
*
* @return a {@link IDhApiTerrainDataCache} backed by {@link java.lang.ref.SoftReference}'s. * @return a {@link IDhApiTerrainDataCache} backed by {@link java.lang.ref.SoftReference}'s.
* @since API 3.0.0 * @since API 5.0.0
*/ */
IDhApiTerrainDataCache getSoftCache(); IDhApiTerrainDataCache createSoftCache();
} }
@@ -31,7 +31,7 @@ import java.util.List;
* Contains a list of {@link DhApiTerrainDataPoint} representing the blocks in a Minecraft chunk. * Contains a list of {@link DhApiTerrainDataPoint} representing the blocks in a Minecraft chunk.
* *
* @author Builderb0y, James Seibel * @author Builderb0y, James Seibel
* @version 2024-7-21 * @version 2025-12-11
* @since API 2.0.0 * @since API 2.0.0
* *
* @see IDhApiWrapperFactory * @see IDhApiWrapperFactory
@@ -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.3.7-b-dev"; public static final String VERSION = "2.4.1-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");
@@ -25,23 +25,16 @@ 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 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.io.File;
/** Handles first time Core setup. */ /** Handles first time Core setup. */
public class Initializer public class Initializer
{ {
@@ -57,6 +50,7 @@ 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;
Runnable zstdBlockDecompress = () -> { com.github.luben.zstd.Zstd.decompress(new byte [0]); };
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;
@@ -521,7 +521,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
//=============// //=============//
@Override @Override
public IDhApiTerrainDataCache getSoftCache() { return new DhApiTerrainDataCache(); } public IDhApiTerrainDataCache createSoftCache() { return new DhApiTerrainDataCache(); }
@@ -23,16 +23,13 @@ import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode; import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
import com.seibel.distanthorizons.core.api.external.methods.data.DhApiTerrainDataRepo;
import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState; import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState;
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.network.messages.MessageRegistry; import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.render.DhApiRenderProxy; import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
import com.seibel.distanthorizons.core.render.renderer.VanillaFadeRenderer; import com.seibel.distanthorizons.core.render.renderer.*;
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
import com.seibel.distanthorizons.core.render.renderer.RenderParams;
import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.util.objects.Pair;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
@@ -46,9 +43,7 @@ import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.renderer.TestRenderer;
import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.core.world.AbstractDhWorld;
import com.seibel.distanthorizons.core.world.DhClientServerWorld;
import com.seibel.distanthorizons.core.world.DhClientWorld; import com.seibel.distanthorizons.core.world.DhClientWorld;
import com.seibel.distanthorizons.core.world.IDhClientWorld; import com.seibel.distanthorizons.core.world.IDhClientWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
@@ -61,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;
@@ -98,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;
@@ -323,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 //
//============// //============//
@@ -679,7 +648,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();
@@ -725,10 +695,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 =
@@ -744,6 +715,48 @@ public class ClientApi
MC_CLIENT.sendChatMessage(message); MC_CLIENT.sendChatMessage(message);
} }
} }
// print a warning if G1GC is being used
// (this garbage collector is known to cause stuttering)
if (this.staticStartupMessageSentRecently()) return;
if (!this.g1GarbageCollectorWarningPrinted
&& Config.Common.Logging.Warning.showGarbageCollectorWarning.get())
{
this.g1GarbageCollectorWarningPrinted = true;
try
{
boolean g1GcInUse = false;
List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean gcMxBean : gcMxBeans)
{
// "G1 Young Generation" // "G1 Concurrent GC" // "G1 Old Generation"
if (gcMxBean.getName().toLowerCase().contains("g1 "))
{
g1GcInUse = true;
break;
}
}
if (g1GcInUse)
{
ClientApi.INSTANCE.showChatMessageNextFrame(
// yellow text
"\u00A7e" + "Distant Horizons: G1 Garbage collector detected." + "\u00A7r \n" +
"This garbage collector can cause FPS stuttering. \n" +
"It's recommended to use a concurrent garbage collector \n" +
"like ZGC (Java 21+) for a smoother experience. \n" +
"");
}
}
catch (Exception re)
{
LOGGER.warn("Unable to determine garbage collector type. If stuttering occurs please try a concurrent garbage collector like ZGC.");
}
}
} }
/** done to prevent sending a bunch of startup messages all at once, causing some to be missed. */ /** done to prevent sending a bunch of startup messages all at once, causing some to be missed. */
private boolean staticStartupMessageSentRecently() private boolean staticStartupMessageSentRecently()
@@ -9,6 +9,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.network.event.internal.CloseInternalEvent; import com.seibel.distanthorizons.core.network.event.internal.CloseInternalEvent;
import com.seibel.distanthorizons.core.network.messages.base.LevelInitMessage; import com.seibel.distanthorizons.core.network.messages.base.LevelInitMessage;
import com.seibel.distanthorizons.core.network.session.NetworkSession; import com.seibel.distanthorizons.core.network.session.NetworkSession;
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -89,7 +90,7 @@ public class ClientPluginChannelApi
LOGGER.info("Server level key received: [" + msg.levelKey + "]."); LOGGER.info("Server level key received: [" + msg.levelKey + "].");
MC.executeOnRenderThread(() -> GLProxy.getInstance().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();
@@ -123,7 +123,6 @@ public class Config
{ {
// common config links need to have their destination // common config links need to have their destination
// since they aren't part of "client" config class // since they aren't part of "client" config class
// TODO determine their destination programically instead of hard coding the value
public static ConfigUIComment advancedHeader = new ConfigUIComment.Builder().setParentConfigClass(Advanced.class).build(); public static ConfigUIComment advancedHeader = new ConfigUIComment.Builder().setParentConfigClass(Advanced.class).build();
@@ -169,6 +168,20 @@ public class Config
public static ConfigCategory culling = new ConfigCategory.Builder().set(Culling.class).build(); public static ConfigCategory culling = new ConfigCategory.Builder().set(Culling.class).build();
public static ConfigUISpacer cullingSpacer = new ConfigUISpacer.Builder().build(); public static ConfigUISpacer cullingSpacer = new ConfigUISpacer.Builder().build();
public static ConfigEntry<Boolean> overrideVanillaGraphicsSettings = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment("" +
"If true some vanilla graphics settings will be automatically changed \n" +
"during DH setup to provide a better experience. \n" +
" \n" +
"IE disabling vanilla clouds (which render on top of DH LODs), \n" +
" and chunk fading (DH already fades MC chunks) \n" +
"")
.build();
public static ConfigUISpacer overrideVanillaSpacer = new ConfigUISpacer.Builder().build();
public static ConfigCategory experimental = new ConfigCategory.Builder().set(Experimental.class).build(); public static ConfigCategory experimental = new ConfigCategory.Builder().set(Experimental.class).build();
@@ -260,7 +273,7 @@ public class Config
public static ConfigEntry<Double> lodBias = new ConfigEntry.Builder<Double>() public static ConfigEntry<Double> lodBias = new ConfigEntry.Builder<Double>()
.setMinDefaultMax(0d, 0d, null) .setMinDefaultMax(0d, 0d, null)
.comment("" .comment(""
+ "What the value should vanilla Minecraft's texture LodBias be? \n" + "What value should vanilla Minecraft's texture LodBias be? \n"
+ "If set to 0 the mod wont overwrite vanilla's default (which so happens to also be 0)") + "If set to 0 the mod wont overwrite vanilla's default (which so happens to also be 0)")
.build(); .build();
@@ -1362,6 +1375,37 @@ public class Config
+ "") + "")
.build(); .build();
public static ConfigEntry<Integer> generationCenterChunkX = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.bounds.centerChunk.x")
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE)
.comment("" +
"The center X chunk position that the world gen max radius is centered around. \n" +
"")
.build();
public static ConfigEntry<Integer> generationCenterChunkZ = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.bounds.centerChunk.z")
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE)
.comment("" +
"The center Z chunk position that the world gen max radius is centered around. \n" +
"")
.build();
public static ConfigEntry<Integer> generationMaxChunkRadius = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.bounds.radiusInChunks")
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.setMinDefaultMax(0, 0, Integer.MAX_VALUE)
.comment("" +
"The max radius in chunks around the central point where world generation is allowed. \n" +
"If this value is set to 0, generation bounds are disabled and the render distance will be used. \n" +
"\n" +
"This should only be set if you have a pre-generated world that has a very limited size. \n" +
"Setting this on a normal MC world will prevent the world generator from filling \n" +
"out your render distance. \n" +
"")
.build();
} }
public static class LodBuilding public static class LodBuilding
@@ -1387,7 +1431,7 @@ public class Config
.build(); .build();
public static ConfigEntry<EDhApiDataCompressionMode> dataCompression = new ConfigEntry.Builder<EDhApiDataCompressionMode>() public static ConfigEntry<EDhApiDataCompressionMode> dataCompression = new ConfigEntry.Builder<EDhApiDataCompressionMode>()
.set(EDhApiDataCompressionMode.Z_STD) .set(EDhApiDataCompressionMode.Z_STD_BLOCK)
// only visible via the API since there is no reason to use any compressor except ZStandard as of 2025-11-24 // only visible via the API since there is no reason to use any compressor except ZStandard as of 2025-11-24
.setAppearance(EConfigEntryAppearance.ONLY_IN_API) .setAppearance(EConfigEntryAppearance.ONLY_IN_API)
.build(); .build();
@@ -1585,6 +1629,15 @@ public class Config
+ "") + "")
.build(); .build();
public static ConfigEntry<Boolean> showGarbageCollectorWarning = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If enabled, a chat message will be displayed if the garbage \n"
+ "collector Java is currently using is known \n"
+ "to cause stutters and/or issues. \n"
+ "")
.build();
public static ConfigEntry<Boolean> showReplayWarningOnStartup = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> showReplayWarningOnStartup = new ConfigEntry.Builder<Boolean>()
.set(true) .set(true)
.comment("" .comment(""
@@ -1686,32 +1739,6 @@ public class Config
"") "")
.build(); .build();
public static ConfigEntry<Integer> generationBoundsX = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.bounds.x")
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE)
.comment("" +
"Defines the X-coordinate of the central point for generation boundaries, in blocks. \n" +
"")
.build();
public static ConfigEntry<Integer> generationBoundsZ = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.bounds.z")
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE)
.comment("" +
"Defines the Z-coordinate of the central point for generation boundaries, in blocks. \n" +
"")
.build();
public static ConfigEntry<Integer> generationBoundsRadius = new ConfigEntry.Builder<Integer>()
.setChatCommandName("generation.bounds.radius")
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.setMinDefaultMax(0, 0, Integer.MAX_VALUE)
.comment("" +
"Defines the radius around the central point within which generation is allowed, in blocks. \n" +
"If this value is set to 0, generation bounds are disabled." +
"")
.build();
// Real-time updates // Real-time updates
public static ConfigEntry<Boolean> enableRealTimeUpdates = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> enableRealTimeUpdates = new ConfigEntry.Builder<Boolean>()
@@ -24,12 +24,14 @@ import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import com.seibel.distanthorizons.core.config.types.ConfigEntry; import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.jar.EPlatform;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
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 java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@@ -29,13 +29,14 @@ import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderDataPointUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.coreapi.util.MathUtil;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class ColumnBox public class ColumnBox
{ {
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
/** /**
* if the skylight has this value that means * if the skylight has this value that means
@@ -122,7 +123,7 @@ public class ColumnBox
&& !isTopTransparent; && !isTopTransparent;
if (!skipTop) if (!skipTop)
{ {
builder.addQuadUp(minX, maxY, minZ, width, width, ColorUtil.applyShade(color, MC.getShade(EDhDirection.UP)), irisBlockMaterialId, skyLightTop, blockLight); builder.addQuadUp(minX, maxY, minZ, width, width, ColorUtil.applyShade(color, MC_RENDER.getShade(EDhDirection.UP)), irisBlockMaterialId, skyLightTop, blockLight);
} }
} }
@@ -133,7 +134,7 @@ public class ColumnBox
&& !isBottomTransparent; && !isBottomTransparent;
if (!skipBottom) if (!skipBottom)
{ {
builder.addQuadDown(minX, minY, minZ, width, width, ColorUtil.applyShade(color, MC.getShade(EDhDirection.DOWN)), irisBlockMaterialId, skyLightBot, blockLight); builder.addQuadDown(minX, minY, minZ, width, width, ColorUtil.applyShade(color, MC_RENDER.getShade(EDhDirection.DOWN)), irisBlockMaterialId, skyLightBot, blockLight);
} }
} }
@@ -263,7 +264,7 @@ public class ColumnBox
// no adjacent data // // no adjacent data //
//==================// //==================//
color = ColorUtil.applyShade(color, MC.getShade(direction)); color = ColorUtil.applyShade(color, MC_RENDER.getShade(direction));
if (adjColumnView.size == 0 if (adjColumnView.size == 0
|| RenderDataPointUtil.hasZeroHeight(adjColumnView.get(0))) || RenderDataPointUtil.hasZeroHeight(adjColumnView.get(0)))
@@ -32,6 +32,7 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.util.ColorUtil; import com.seibel.distanthorizons.core.util.ColorUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.coreapi.util.MathUtil;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
@@ -44,7 +45,7 @@ import org.lwjgl.system.MemoryUtil;
public class LodQuadBuilder public class LodQuadBuilder
{ {
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final ArrayList<BufferQuad>[] opaqueQuads = (ArrayList<BufferQuad>[]) new ArrayList[6]; private final ArrayList<BufferQuad>[] opaqueQuads = (ArrayList<BufferQuad>[]) new ArrayList[6];
@@ -379,7 +380,7 @@ public class LodQuadBuilder
// for horizontal and bottom faces of grass blocks, use the dirt color to // for horizontal and bottom faces of grass blocks, use the dirt color to
// prevent green cliff walls // prevent green cliff walls
color = this.clientLevelWrapper.getDirtBlockColor(); color = this.clientLevelWrapper.getDirtBlockColor();
color = ColorUtil.applyShade(color, MC.getShade(quad.direction)); color = ColorUtil.applyShade(color, MC_RENDER.getShade(quad.direction));
} }
} }
} }
@@ -0,0 +1,12 @@
package com.seibel.distanthorizons.core.enums;
/**
* TODO
* might be deprecated in the future? in that case we'll probably want a wrapper
* function to handle colors for new MC versions
*
* source: https://minecraft.wiki/w/Formatting_codes
*/
public class EMinecraftColor
{
}
@@ -82,7 +82,8 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im
// constructor // // constructor //
//=============// //=============//
public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure) throws SQLException, IOException { super(level, saveStructure); } public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure) throws SQLException, IOException
{ this(level, saveStructure, null); }
public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride) throws SQLException, IOException public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride) throws SQLException, IOException
{ {
super(level, saveStructure, saveDirOverride); super(level, saveStructure, saveDirOverride);
@@ -227,7 +227,7 @@ public class FullDataUpdatePropagatorV2 implements IDebugRenderable, AutoCloseab
parentDataSource.applyToParent = true; parentDataSource.applyToParent = true;
} }
this.dataUpdater.updateDataSource(parentDataSource, false); this.dataUpdater.updateDataSource(parentDataSource);
} }
} }
} }
@@ -328,7 +328,7 @@ public class FullDataUpdatePropagatorV2 implements IDebugRenderable, AutoCloseab
childDataSource.applyToChildren = true; childDataSource.applyToChildren = true;
} }
this.dataUpdater.updateDataSource(childDataSource, false); this.dataUpdater.updateDataSource(childDataSource);
} }
} }
} }
@@ -63,7 +63,7 @@ public class FullDataUpdaterV2 implements IDebugRenderable, AutoCloseable
/** /**
* Can be used if you don't want to lock the current thread * Can be used if you don't want to lock the current thread
* Otherwise the sync version {@link FullDataUpdaterV2#updateDataSource(FullDataSourceV2, boolean)} may be a better choice. * Otherwise the sync version {@link FullDataUpdaterV2#updateDataSource(FullDataSourceV2)} may be a better choice.
*/ */
public CompletableFuture<Void> updateDataSourceAsync(@NotNull FullDataSourceV2 inputDataSource) public CompletableFuture<Void> updateDataSourceAsync(@NotNull FullDataSourceV2 inputDataSource)
{ {
@@ -86,7 +86,7 @@ public class FullDataUpdaterV2 implements IDebugRenderable, AutoCloseable
{ {
try try
{ {
this.updateDataSource(inputDataSource, true); this.updateDataSource(inputDataSource);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -107,7 +107,7 @@ public class FullDataUpdaterV2 implements IDebugRenderable, AutoCloseable
} }
/** After this method returns the inputData will be written to file. */ /** After this method returns the inputData will be written to file. */
public void updateDataSource(@NotNull FullDataSourceV2 inputData, boolean lockOnUpdatePos) public void updateDataSource(@NotNull FullDataSourceV2 inputData)
{ {
if (this.isShutdownRef.get()) if (this.isShutdownRef.get())
{ {
@@ -117,25 +117,20 @@ public class FullDataUpdaterV2 implements IDebugRenderable, AutoCloseable
long updatePos = inputData.getPos(); long updatePos = inputData.getPos();
boolean methodLocked = false;
// a lock is necessary to prevent two threads from writing to the same position at once, // a lock is necessary to prevent two threads from writing to the same position at once,
// if that happens only the second update will apply and the LOD will end up with hole(s) // if that happens only the second update will apply and the LOD will end up with hole(s)
ReentrantLock updateLock = this.updateLockProvider.getLock(updatePos); ReentrantLock updateLock = this.updateLockProvider.getLock(updatePos);
try try
{ {
if (lockOnUpdatePos)
{
methodLocked = true;
updateLock.lock(); updateLock.lock();
this.lockedPosSet.add(updatePos); this.lockedPosSet.add(updatePos);
}
// get or create the data source // get or create the data source
try (FullDataSourceV2 recipientDataSource = this.provider.get(updatePos)) try (FullDataSourceV2 recipientDataSource = this.provider.get(updatePos))
{ {
if (recipientDataSource != null) if (recipientDataSource != null) // will be null if the repo was shut down
{ {
boolean dataModified = recipientDataSource.updateFromDataSource(inputData); boolean dataModified = recipientDataSource.updateFromDataSource(inputData);
if (dataModified) if (dataModified)
@@ -169,14 +164,11 @@ public class FullDataUpdaterV2 implements IDebugRenderable, AutoCloseable
LOGGER.error("Error updating pos ["+DhSectionPos.toString(updatePos)+"], error: "+e.getMessage(), e); LOGGER.error("Error updating pos ["+DhSectionPos.toString(updatePos)+"], error: "+e.getMessage(), e);
} }
finally finally
{
if (methodLocked)
{ {
updateLock.unlock(); updateLock.unlock();
this.lockedPosSet.remove(updatePos); this.lockedPosSet.remove(updatePos);
} }
} }
}
private FullDataSourceV2DTO createDtoFromDataSource(FullDataSourceV2 dataSource) private FullDataSourceV2DTO createDtoFromDataSource(FullDataSourceV2 dataSource)
{ {
@@ -56,10 +56,8 @@ public class PregenManager
return pregenState; return pregenState;
} }
MC_SERVER.setPreventAutoPause(true);
pregenState.whenComplete((result, throwable) -> { pregenState.whenComplete((result, throwable) -> {
this.pregenFuture.set(null); this.pregenFuture.set(null);
MC_SERVER.setPreventAutoPause(false);
}); });
pregenState.fillPendingQueue(); pregenState.fillPendingQueue();
@@ -11,6 +11,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.WorldGenUtil;
import com.seibel.distanthorizons.core.util.objects.RollingAverage; import com.seibel.distanthorizons.core.util.objects.RollingAverage;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -110,12 +111,14 @@ public class RemoteWorldRetrievalQueue extends AbstractFullDataNetworkRequestQue
@Override @Override
protected boolean isSectionAllowedToGenerate(long sectionPos, DhBlockPos2D targetPos) protected boolean isSectionAllowedToGenerate(long sectionPos, DhBlockPos2D targetPos)
{ {
if (this.networkState.sessionConfig.getGenerationBoundsRadius() > 0) if (this.networkState.sessionConfig.getGenerationMaxChunkRadius() > 0)
{ {
if (DhSectionPos.getChebyshevSignedBlockDistance(sectionPos, new DhBlockPos2D( boolean posInRange = WorldGenUtil.isPosInWorldGenRange(
this.networkState.sessionConfig.getGenerationBoundsX(), sectionPos,
this.networkState.sessionConfig.getGenerationBoundsZ() this.networkState.sessionConfig.getGenerationCenterChunkX(), this.networkState.sessionConfig.getGenerationCenterChunkZ(),
)) > this.networkState.sessionConfig.getGenerationBoundsRadius()) this.networkState.sessionConfig.getGenerationMaxChunkRadius()
);
if (!posInRange)
{ {
return false; return false;
} }
@@ -210,7 +210,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
while (!this.isGeneratorBusy() while (!this.isGeneratorBusy()
&& taskStarted) && taskStarted)
{ {
taskStarted = this.startNextWorldGenTask(this.generationTargetPos); taskStarted = this.tryStartNextWorldGenTask(this.generationTargetPos);
} }
} }
catch (Exception e) catch (Exception e)
@@ -240,7 +240,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
* @param targetPos the position to center the generation around * @param targetPos the position to center the generation around
* @return false if no tasks were found to generate * @return false if no tasks were found to generate
*/ */
private boolean startNextWorldGenTask(DhBlockPos2D targetPos) private boolean tryStartNextWorldGenTask(DhBlockPos2D targetPos)
{ {
if (this.waitingTasks.isEmpty()) if (this.waitingTasks.isEmpty())
{ {
@@ -249,23 +249,23 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
Mapper closestTaskMap = this.waitingTasks.reduceEntries(1024, TaskDistancePair closestTaskPair = this.waitingTasks.reduceEntries(1024,
entry -> new Mapper(entry.getValue(), DhSectionPos.getSectionBBoxPos(entry.getValue().pos).getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())), entry -> new TaskDistancePair(entry.getValue(), DhSectionPos.getSectionBBoxPos(entry.getValue().pos).getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())),
(aMapper, bMapper) -> aMapper.dist < bMapper.dist ? aMapper : bMapper); (TaskDistancePair aTaskPair, TaskDistancePair bTaskPair) -> (aTaskPair.dist < bTaskPair.dist) ? aTaskPair : bTaskPair);
if (closestTaskMap == null) if (closestTaskPair == null)
{ {
// FIXME concurrency issue // FIXME concurrency issue
return false; return false;
} }
WorldGenTask closestTask = closestTaskMap.task; WorldGenTask closestTask = closestTaskPair.task;
// remove the task we found, we are going to start it and don't want to run it multiple times // remove the task we found, we are going to start it and don't want to run it multiple times
this.waitingTasks.remove(closestTask.pos, closestTask); this.waitingTasks.remove(closestTask.pos, closestTask);
// do we need to modify this task to generate it? // do we need to modify this task to generate it?
if (this.canGeneratePos(closestTask.pos)) if (this.canGenerateDetailLevel(DhSectionPos.getDetailLevel(closestTask.pos)))
{ {
// detail level is correct for generation, start generation // detail level is correct for generation, start generation
@@ -276,11 +276,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
{ {
// no task exists for this position, start one // no task exists for this position, start one
InProgressWorldGenTaskGroup newTaskGroup = new InProgressWorldGenTaskGroup(closestTaskGroup); InProgressWorldGenTaskGroup newTaskGroup = new InProgressWorldGenTaskGroup(closestTaskGroup);
boolean taskStarted = this.tryStartingWorldGenTaskGroup(newTaskGroup); this.startWorldGenTaskGroup(newTaskGroup);
if (!taskStarted)
{
//LOGGER.trace("Unable to start task: "+closestTask.pos+", skipping. Task position may have already been generated.");
}
} }
else else
{ {
@@ -289,7 +285,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
// the newly selected task, we cannot use it, // the newly selected task, we cannot use it,
// as some chunks may have already been written into. // as some chunks may have already been written into.
//LOGGER.trace("A task already exists for this position, todo: "+closestTask.pos); //LOGGER.warn("A task already exists for this position, todo: "+DhSectionPos.toString(closestTask.pos));
} }
// a task has been started // a task has been started
@@ -321,8 +317,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
return true; return true;
} }
} }
/** @return true if the task was started, false otherwise */ private void startWorldGenTaskGroup(InProgressWorldGenTaskGroup newTaskGroup)
private boolean tryStartingWorldGenTaskGroup(InProgressWorldGenTaskGroup newTaskGroup)
{ {
byte taskDetailLevel = newTaskGroup.group.dataDetail; byte taskDetailLevel = newTaskGroup.group.dataDetail;
long taskPos = newTaskGroup.group.pos; long taskPos = newTaskGroup.group.pos;
@@ -375,7 +370,6 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
}); });
this.inProgressGenTasksByLodPos.put(taskPos, newTaskGroup); this.inProgressGenTasksByLodPos.put(taskPos, newTaskGroup);
return true;
} }
private CompletableFuture<Void> startGenerationEvent( private CompletableFuture<Void> startGenerationEvent(
long requestPos, long requestPos,
@@ -689,9 +683,9 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
// helper methods // // helper methods //
//================// //================//
private boolean canGeneratePos(long taskPos) private boolean canGenerateDetailLevel(byte taskDetailLevel)
{ {
byte requestedDetailLevel = (byte) (DhSectionPos.getDetailLevel(taskPos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); byte requestedDetailLevel = (byte) (taskDetailLevel - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
return (this.highestDataDetail <= requestedDetailLevel && requestedDetailLevel <= this.lowestDataDetail); return (this.highestDataDetail <= requestedDetailLevel && requestedDetailLevel <= this.lowestDataDetail);
} }
@@ -701,11 +695,12 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
// helper classes // // helper classes //
//================// //================//
private static class Mapper private static class TaskDistancePair
{ {
public final WorldGenTask task; public final WorldGenTask task;
public final int dist; public final int dist;
public Mapper(WorldGenTask task, int dist)
public TaskDistancePair(WorldGenTask task, int dist)
{ {
this.task = task; this.task = task;
this.dist = dist; this.dist = dist;
@@ -21,6 +21,7 @@ import com.seibel.distanthorizons.core.network.messages.requests.CancelMessage;
import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.WorldGenUtil;
import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
@@ -147,17 +148,16 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I
return; return;
} }
if (Config.Server.generationBoundsRadius.get() > 0) boolean posInRange = WorldGenUtil.isPosInWorldGenRange(
{ message.sectionPos,
if (DhSectionPos.getChebyshevSignedBlockDistance(message.sectionPos, new DhBlockPos2D( Config.Common.WorldGenerator.generationCenterChunkX.get(), Config.Common.WorldGenerator.generationCenterChunkZ.get(),
serverPlayerState.sessionConfig.getGenerationBoundsX(), Config.Common.WorldGenerator.generationMaxChunkRadius.get()
serverPlayerState.sessionConfig.getGenerationBoundsZ() );
)) > Config.Server.generationBoundsRadius.get()) if (!posInRange)
{ {
message.sendResponse(new RequestOutOfRangeException("Section out of allowed bounds")); message.sendResponse(new RequestOutOfRangeException("Section out of allowed bounds"));
return; return;
} }
}
if (!Config.Server.Experimental.enableNSizedGeneration.get() && DhSectionPos.getDetailLevel(message.sectionPos) != DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) if (!Config.Server.Experimental.enableNSizedGeneration.get() && DhSectionPos.getDetailLevel(message.sectionPos) != DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
{ {
@@ -276,7 +276,7 @@ public class DhLogger implements IConfigListener
if (mc_client != null) if (mc_client != null)
{ {
mc_client.logToChat(level, msgStr); this.logToChat(level, msgStr);
messageLogged = true; messageLogged = true;
} }
} }
@@ -296,6 +296,41 @@ public class DhLogger implements IConfigListener
} }
private static boolean loggingLevelIsLessSpecificThan(Level thisLoggingLevel, Level requestedLogLevel) private static boolean loggingLevelIsLessSpecificThan(Level thisLoggingLevel, Level requestedLogLevel)
{ return thisLoggingLevel.intLevel() >= requestedLogLevel.intLevel(); } { return thisLoggingLevel.intLevel() >= requestedLogLevel.intLevel(); }
/** Sends the given message to chat with a formatted prefix and color based on the log level. */
private void logToChat(Level logLevel, String message)
{
String prefix = "[" + ModInfo.READABLE_NAME + "] ";
if (logLevel == Level.ERROR)
{
prefix += "\u00A74";
}
else if (logLevel == Level.WARN)
{
prefix += "\u00A76";
}
else if (logLevel == Level.INFO)
{
prefix += "\u00A7f";
}
else if (logLevel == Level.DEBUG)
{
prefix += "\u00A77";
}
else if (logLevel == Level.TRACE)
{
prefix += "\u00A78";
}
else
{
prefix += "\u00A7f";
}
prefix += "\u00A7l\u00A7u";
prefix += logLevel.name();
prefix += ":\u00A7r ";
mc_client.sendChatMessage(prefix + message);
}
@@ -33,9 +33,9 @@ public class SessionConfig implements INetworkObject
registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration, Boolean::logicalAnd); registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration, Boolean::logicalAnd);
registerConfigEntry(Config.Server.maxGenerationRequestDistance, Math::min); registerConfigEntry(Config.Server.maxGenerationRequestDistance, Math::min);
registerConfigEntry(Config.Server.generationBoundsX, (x, y) -> y); registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkX, (x, y) -> y);
registerConfigEntry(Config.Server.generationBoundsZ, (x, y) -> y); registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkZ, (x, y) -> y);
registerConfigEntry(Config.Server.generationBoundsRadius, (x, y) -> y); registerConfigEntry(Config.Common.WorldGenerator.generationMaxChunkRadius, (x, y) -> y);
registerConfigEntry(Config.Server.generationRequestRateLimit, Math::min); registerConfigEntry(Config.Server.generationRequestRateLimit, Math::min);
registerConfigEntry(Config.Server.enableRealTimeUpdates, Boolean::logicalAnd); registerConfigEntry(Config.Server.enableRealTimeUpdates, Boolean::logicalAnd);
@@ -68,9 +68,9 @@ public class SessionConfig implements INetworkObject
public boolean isDistantGenerationEnabled() { return this.getValue(Config.Common.WorldGenerator.enableDistantGeneration); } public boolean isDistantGenerationEnabled() { return this.getValue(Config.Common.WorldGenerator.enableDistantGeneration); }
public int getMaxGenerationRequestDistance() { return this.getValue(Config.Server.maxGenerationRequestDistance); } public int getMaxGenerationRequestDistance() { return this.getValue(Config.Server.maxGenerationRequestDistance); }
public Integer getGenerationBoundsX() { return this.getValue(Config.Server.generationBoundsX); } public Integer getGenerationCenterChunkX() { return this.getValue(Config.Common.WorldGenerator.generationCenterChunkX); }
public Integer getGenerationBoundsZ() { return this.getValue(Config.Server.generationBoundsZ); } public Integer getGenerationCenterChunkZ() { return this.getValue(Config.Common.WorldGenerator.generationCenterChunkZ); }
public Integer getGenerationBoundsRadius() { return this.getValue(Config.Server.generationBoundsRadius); } public Integer getGenerationMaxChunkRadius() { return this.getValue(Config.Common.WorldGenerator.generationMaxChunkRadius); }
public int getGenerationRequestRateLimit() { return this.getValue(Config.Server.generationRequestRateLimit); } public int getGenerationRequestRateLimit() { return this.getValue(Config.Server.generationRequestRateLimit); }
public boolean isRealTimeUpdatesEnabled() { return this.getValue(Config.Server.enableRealTimeUpdates); } public boolean isRealTimeUpdatesEnabled() { return this.getValue(Config.Server.enableRealTimeUpdates); }
@@ -102,8 +102,8 @@ public class ServerPlayerState implements Closeable
private void sendConfigMessage() private void sendConfigMessage()
{ {
double coordinateScale = this.getServerPlayer().getLevel().getDimensionType().getCoordinateScale(); double coordinateScale = this.getServerPlayer().getLevel().getDimensionType().getCoordinateScale();
this.sessionConfig.constrainValue(Config.Server.generationBoundsX, (int) (Config.Server.generationBoundsX.get() / coordinateScale)); this.sessionConfig.constrainValue(Config.Common.WorldGenerator.generationCenterChunkX, (int) (Config.Common.WorldGenerator.generationCenterChunkX.get() / coordinateScale));
this.sessionConfig.constrainValue(Config.Server.generationBoundsZ, (int) (Config.Server.generationBoundsZ.get() / coordinateScale)); this.sessionConfig.constrainValue(Config.Common.WorldGenerator.generationCenterChunkZ, (int) (Config.Common.WorldGenerator.generationCenterChunkZ.get() / coordinateScale));
this.networkSession.sendMessage(new SessionConfigMessage(this.sessionConfig)); this.networkSession.sendMessage(new SessionConfigMessage(this.sessionConfig));
} }
@@ -281,17 +281,24 @@ public class DhSectionPos
+ Math.abs(getCenterBlockPosZ(pos) - blockPos.z); + Math.abs(getCenterBlockPosZ(pos) - blockPos.z);
} }
/** see: {@link DhSectionPos#getChebyshevSignedBlockDistance(long, int, int)} */
public static int getChebyshevSignedBlockDistance(long pos, DhBlockPos blockPos)
{ return getChebyshevSignedBlockDistance(pos, blockPos.getX(), blockPos.getZ()); }
/** see: {@link DhSectionPos#getChebyshevSignedBlockDistance(long, int, int)} */
public static int getChebyshevSignedBlockDistance(long pos, DhBlockPos2D blockPos)
{ return getChebyshevSignedBlockDistance(pos, blockPos.x, blockPos.z); }
/** /**
* Returns the signed distance from a given block to a given section. <br> * Returns the signed distance from a given block to a given section. <br>
* Essentially acts like a distance from the block to the nearest edge of the section, * Essentially acts like a distance from the block to the nearest edge of the section,
* except inside the section it's negative. <br> * except inside the section it's negative. <br>
* Useful for detail level insensitive distance comparisons. * Useful for detail level insensitive distance comparisons.
*/ */
public static int getChebyshevSignedBlockDistance(long pos, DhBlockPos2D blockPos) public static int getChebyshevSignedBlockDistance(long pos, int blockPosX, int blockPosZ)
{ {
return Math.max( return Math.max(
Math.abs(getCenterBlockPosX(pos) - blockPos.x), Math.abs(getCenterBlockPosX(pos) - blockPosX),
Math.abs(getCenterBlockPosZ(pos) - blockPos.z) Math.abs(getCenterBlockPosZ(pos) - blockPosZ)
) - getBlockWidth(pos) / 2; ) - getBlockWidth(pos) / 2;
} }
@@ -762,7 +762,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
{ {
// walk through each node // walk through each node
Iterator<QuadNode<LodRenderSection>> nodeIterator = this.nodeIterator(); Iterator<QuadNode<LodRenderSection>> nodeIterator = this.nodeIterator();
ArrayList<CompletableFuture<Void>> renderDataBuildFutures = new ArrayList<>();
while (nodeIterator.hasNext()) while (nodeIterator.hasNext())
{ {
QuadNode<LodRenderSection> quadNode = nodeIterator.next(); QuadNode<LodRenderSection> quadNode = nodeIterator.next();
@@ -42,7 +42,7 @@ import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler; import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
import com.seibel.distanthorizons.core.util.PerfRecorder; import com.seibel.distanthorizons.core.util.WorldGenUtil;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker; import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -528,6 +528,18 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
} }
long pos = missingGenerationPos.removeLong(i); long pos = missingGenerationPos.removeLong(i);
boolean posInRange = WorldGenUtil.isPosInWorldGenRange(
pos,
Config.Common.WorldGenerator.generationCenterChunkX.get(), Config.Common.WorldGenerator.generationCenterChunkZ.get(),
Config.Common.WorldGenerator.generationMaxChunkRadius.get()
);
if (!posInRange)
{
continue;
}
boolean positionQueued = (this.fullDataSourceProvider.queuePositionForRetrieval(pos) != null); boolean positionQueued = (this.fullDataSourceProvider.queuePositionForRetrieval(pos) != null);
if (!positionQueued) if (!positionQueued)
{ {
@@ -198,8 +198,8 @@ public class GLBuffer implements AutoCloseable
switch (uploadMethod) switch (uploadMethod)
{ {
case NONE: //case NONE:
return; // return;
case AUTO: case AUTO:
LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!"); LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!");
case BUFFER_STORAGE: case BUFFER_STORAGE:
@@ -25,6 +25,10 @@ public class DHDepthTexture
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE); GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE); GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
// 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_MAX_LEVEL, 0);
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0); GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
} }
@@ -46,7 +46,7 @@ public class DhColorTexture
this.id = GL43C.glGenTextures(); this.id = GL43C.glGenTextures();
boolean isPixelFormatInteger = builder.internalFormat.getPixelFormat().isInteger(); boolean isPixelFormatInteger = builder.internalFormat.getPixelFormat().isInteger();
this.setupTexture(this.id, builder.width, builder.height, !isPixelFormatInteger); this.setupTexture(this.id, builder.width, builder.height, !isPixelFormatInteger); // this binds the texture
// Clean up after ourselves // Clean up after ourselves
// This is strictly defensive to ensure that other buggy code doesn't tamper with our textures // This is strictly defensive to ensure that other buggy code doesn't tamper with our textures
@@ -67,6 +67,10 @@ public class DhColorTexture
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST); GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE); GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE); GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
// 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_MAX_LEVEL, 0);
} }
private void resizeTexture(int texture, int width, int height) private void resizeTexture(int texture, int width, int height)
@@ -38,7 +38,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.util.math.Vec3f;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
@@ -213,7 +212,7 @@ public class DebugRenderer
// particle rendering // particle rendering
BoxParticle head = null; BoxParticle head = null;
while ((head = this.particles.poll()) != null && head.isDead(System.nanoTime())) while ((head = this.particles.poll()) != null && head.isDead())
{ /* remove dead particles */ } { /* remove dead particles */ }
if (head != null) if (head != null)
{ {
@@ -311,52 +310,50 @@ public class DebugRenderer
public static final class BoxParticle implements Comparable<BoxParticle> public static final class BoxParticle implements Comparable<BoxParticle>
{ {
public Box box; public Box box;
public long startTime; public long startMsTime;
public long duration; public long durationInMs;
public float yChange; public float yChange;
public BoxParticle(Box box, long startTime, long duration, float yChange) private BoxParticle(Box box, long startMsTime, long durationInMs, float yChange)
{ {
this.box = box; this.box = box;
this.startTime = startTime; this.startMsTime = startMsTime;
this.duration = duration; this.durationInMs = durationInMs;
this.yChange = yChange; this.yChange = yChange;
} }
public BoxParticle(Box box, long nanoSecondDuratoin, float yChange) { this(box, System.nanoTime(), nanoSecondDuratoin, yChange); } public BoxParticle(Box box, double secondDuration, float yChange) { this(box, System.currentTimeMillis(), (long) (secondDuration * 1_000), yChange); }
public BoxParticle(Box box, double secondDuration, float yChange) { this(box, System.nanoTime(), (long) (secondDuration * 1000000000), yChange); }
@Override @Override
public int compareTo(@NotNull BoxParticle particle) public int compareTo(@NotNull BoxParticle particle)
{ {
return Long.compare(this.startTime + this.duration, particle.startTime + particle.duration); return Long.compare(this.startMsTime + this.durationInMs, particle.startMsTime + particle.durationInMs);
} }
public Box getBox() public Box getBox()
{ {
long now = System.nanoTime(); long nowMs = System.currentTimeMillis();
float percent = (now - this.startTime) / (float) this.duration; float percent = (nowMs - this.startMsTime) / (float) this.durationInMs;
percent = (float) Math.pow(percent, 4); percent = (float) Math.pow(percent, 4);
float yDiff = this.yChange * percent; float yDiff = this.yChange * percent;
return new Box(new Vec3f(this.box.minPos.x, this.box.minPos.y + yDiff, this.box.minPos.z), new Vec3f(this.box.maxPos.x, this.box.maxPos.y + yDiff, this.box.maxPos.z), this.box.color); return new Box(new Vec3f(this.box.minPos.x, this.box.minPos.y + yDiff, this.box.minPos.z), new Vec3f(this.box.maxPos.x, this.box.maxPos.y + yDiff, this.box.maxPos.z), this.box.color);
} }
public boolean isDead(long time) { return (time - this.startTime) > this.duration; } public boolean isDead() { return (System.currentTimeMillis() - this.startMsTime) > this.durationInMs; }
} }
public static final class BoxWithLife implements IDebugRenderable, Closeable public static final class BoxWithLife implements IDebugRenderable, Closeable
{ {
public Box box; public Box box;
public BoxParticle particaleOnClose; public BoxParticle particleOnClose;
public BoxWithLife(Box box, long ns, float yChange, Color deathColor) public BoxWithLife(Box box, long ns, float yChange, Color deathColor)
{ {
this.box = box; this.box = box;
this.particaleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), -1, ns, yChange); this.particleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), -1, ns, yChange);
register(this, null); register(this, null);
} }
@@ -366,7 +363,7 @@ public class DebugRenderer
public BoxWithLife(Box box, double s, float yChange, Color deathColor) public BoxWithLife(Box box, double s, float yChange, Color deathColor)
{ {
this.box = box; this.box = box;
this.particaleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), s, yChange); this.particleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), s, yChange);
} }
public BoxWithLife(Box box, double s, float yChange) { this(box, s, yChange, box.color); } public BoxWithLife(Box box, double s, float yChange) { this(box, s, yChange, box.color); }
@@ -377,7 +374,7 @@ public class DebugRenderer
@Override @Override
public void close() public void close()
{ {
makeParticle(new BoxParticle(this.particaleOnClose.getBox(), System.nanoTime(), this.particaleOnClose.duration, this.particaleOnClose.yChange)); makeParticle(new BoxParticle(this.particleOnClose.getBox(), System.nanoTime(), this.particleOnClose.durationInMs, this.particleOnClose.yChange));
unregister(this, null); unregister(this, null);
} }
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLW
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL43C;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -95,11 +96,19 @@ public class DhFadeRenderer
} }
this.fadeTexture = GL32.glGenTextures(); this.fadeTexture = GL32.glGenTextures();
{
GLMC.glBindTexture(this.fadeTexture); 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); 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_MIN_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); 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
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_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);
} }
@@ -27,6 +27,7 @@ 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.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL43C;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -87,11 +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); 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); 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_MIN_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); 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); 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
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
}
} }
@@ -42,6 +42,7 @@ import com.seibel.distanthorizons.core.render.renderer.shaders.*;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.util.objects.SortedArraySet; import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
@@ -69,6 +70,7 @@ public class LodRenderer
.maxCountPerSecond(4) .maxCountPerSecond(4)
.build(); .build();
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class); private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class); private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
@@ -174,6 +176,13 @@ public class LodRenderer
return; return;
} }
// only do this once, that way they can still be reverted if desired
if (Config.Client.Advanced.Graphics.overrideVanillaGraphicsSettings.get())
{
MC.disableVanillaClouds();
MC.disableVanillaChunkFadeIn();
}
this.renderObjectsCreated = true; this.renderObjectsCreated = true;
} }
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLW
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.GL43C;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -87,10 +88,17 @@ 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); 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); 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_MIN_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); 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
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_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);
} }
@@ -164,10 +164,11 @@ public class FogShader extends AbstractShaderRenderer
// Fog uniforms // Fog uniforms
this.shader.setUniform(this.uFogColor, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks)); this.shader.setUniform(this.uFogColor, this.getFogColor(partialTicks));
this.shader.setUniform(this.uFogScale, 1.f / lodDrawDistance); this.shader.setUniform(this.uFogScale, 1.f / lodDrawDistance);
this.shader.setUniform(this.uFogVerticalScale, 1.f / MC.getWrappedClientLevel().getMaxHeight()); this.shader.setUniform(this.uFogVerticalScale, 1.f / MC.getWrappedClientLevel().getMaxHeight());
this.shader.setUniform(this.uFullFogMode, MC_RENDER.isFogStateSpecial() ? 1 : 0); // only used for debugging
this.shader.setUniform(this.uFullFogMode, 0); // 1 = render everything with fog color // 7 = use debug rendering
// fog config // fog config
@@ -229,7 +230,6 @@ public class FogShader extends AbstractShaderRenderer
return fogColor; return fogColor;
} }
private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); }
public void setProjectionMatrix(Mat4f projectionMatrix) public void setProjectionMatrix(Mat4f projectionMatrix)
{ {
@@ -0,0 +1,32 @@
package com.seibel.distanthorizons.core.util;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
public class WorldGenUtil
{
/** will always return true if a generation max radius isn't set */
public static boolean isPosInWorldGenRange(
long requestedPos,
int centerChunkX, int centerChunkZ,
int maxChunkRadius)
{
if (Config.Common.WorldGenerator.generationMaxChunkRadius.get() <= 0)
{
return true;
}
DhBlockPos centerBlockPos = new DhChunkPos(centerChunkX, centerChunkZ).centerBlockPos();
int blockDistanceFromCenter = DhSectionPos.getChebyshevSignedBlockDistance(requestedPos, centerBlockPos);
int maxBlockRadius = maxChunkRadius * LodUtil.CHUNK_WIDTH;
boolean requestInRadius = (blockDistanceFromCenter <= maxBlockRadius);
return requestInRadius;
}
}
@@ -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(); }
}
@@ -26,7 +26,6 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import it.unimi.dsi.fastutil.bytes.ByteArrayList; import it.unimi.dsi.fastutil.bytes.ByteArrayList;
import net.jpountz.lz4.LZ4FrameInputStream; import net.jpountz.lz4.LZ4FrameInputStream;
import org.apache.logging.log4j.LogManager;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import org.tukaani.xz.ResettableArrayCache; import org.tukaani.xz.ResettableArrayCache;
import org.tukaani.xz.XZInputStream; import org.tukaani.xz.XZInputStream;
@@ -61,7 +60,7 @@ public class DhDataInputStream extends DataInputStream
{ {
// Z_Std handling compression outside the stream provides a significant performance boost // Z_Std handling compression outside the stream provides a significant performance boost
ByteArrayInputStream byteArrayInputStream; ByteArrayInputStream byteArrayInputStream;
if (compressionMode == EDhApiDataCompressionMode.Z_STD) if (compressionMode == EDhApiDataCompressionMode.Z_STD_BLOCK)
{ {
byteArrayInputStream = new ByteArrayInputStream(Zstd.decompress(byteArray)); byteArrayInputStream = new ByteArrayInputStream(Zstd.decompress(byteArray));
} }
@@ -87,7 +86,7 @@ public class DhDataInputStream extends DataInputStream
return stream; return stream;
case LZ4: case LZ4:
return new LZ4FrameInputStream(stream); return new LZ4FrameInputStream(stream);
case Z_STD: case Z_STD_BLOCK:
// ZStd compression should be handled before this point // ZStd compression should be handled before this point
// just return the stream // just return the stream
return stream; return stream;
@@ -20,14 +20,12 @@
package com.seibel.distanthorizons.core.util.objects.dataStreams; package com.seibel.distanthorizons.core.util.objects.dataStreams;
import com.github.luben.zstd.Zstd; import com.github.luben.zstd.Zstd;
import com.github.luben.zstd.ZstdOutputStream;
import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode; import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import it.unimi.dsi.fastutil.bytes.ByteArrayList; import it.unimi.dsi.fastutil.bytes.ByteArrayList;
import net.jpountz.lz4.LZ4Factory; import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FrameOutputStream; import net.jpountz.lz4.LZ4FrameOutputStream;
import net.jpountz.xxhash.XXHashFactory; import net.jpountz.xxhash.XXHashFactory;
import org.apache.logging.log4j.LogManager;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import org.tukaani.xz.*; import org.tukaani.xz.*;
@@ -85,7 +83,7 @@ public class DhDataOutputStream extends DataOutputStream
//LZ4Factory.nativeInstance().fastCompressor(), //LZ4Factory.nativeInstance().fastCompressor(),
//XXHashFactory.nativeInstance().hash32(), //XXHashFactory.nativeInstance().hash32(),
LZ4FrameOutputStream.FLG.Bits.BLOCK_INDEPENDENCE); LZ4FrameOutputStream.FLG.Bits.BLOCK_INDEPENDENCE);
case Z_STD: case Z_STD_BLOCK:
// ZStd compression should be handled after the stream is closed // ZStd compression should be handled after the stream is closed
// just return the stream // just return the stream
return stream; return stream;
@@ -127,7 +125,7 @@ public class DhDataOutputStream extends DataOutputStream
this.outputByteArray.clear(); this.outputByteArray.clear();
if (this.compressionMode == EDhApiDataCompressionMode.Z_STD) if (this.compressionMode == EDhApiDataCompressionMode.Z_STD_BLOCK)
{ {
this.outputByteArray.addElements(0, Zstd.compress(this.wrappedByteStream.toByteArray(), 3)); this.outputByteArray.addElements(0, Zstd.compress(this.wrappedByteStream.toByteArray(), 3));
} }
@@ -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); }
@@ -32,33 +32,11 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
/**
* Contains everything related to the Minecraft object.
*
* @author James Seibel
* @version 2022-8-20
*/
public interface IMinecraftClientWrapper extends IBindable public interface IMinecraftClientWrapper extends IBindable
{ {
//================// //======================//
// helper methods // // multiplayer handling //
//================// //======================//
/**
* This should be called at the beginning of every frame to
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
* <p>
* LightMaps and other time sensitive objects fall in this category. <br> <br>
* <p>
* This doesn't affect OpenGL objects in any way.
*/
void clearFrameObjectCache();
//=================//
// method wrappers //
//=================//
float getShade(EDhDirection lodDirection);
boolean hasSinglePlayerServer(); boolean hasSinglePlayerServer();
boolean clientConnectedToDedicatedServer(); boolean clientConnectedToDedicatedServer();
@@ -69,24 +47,26 @@ public interface IMinecraftClientWrapper extends IBindable
String getCurrentServerIp(); String getCurrentServerIp();
String getCurrentServerVersion(); String getCurrentServerVersion();
//=============//
// Simple gets //
//=============// //=================//
// player handling //
//=================//
boolean playerExists(); boolean playerExists();
UUID getPlayerUUID();
String getUsername();
// TODO returning null would be easier to understand but might make things harder to parse in some cases
/** @return (0,0,0) if no player is loaded */ /** @return (0,0,0) if no player is loaded */
DhBlockPos getPlayerBlockPos(); DhBlockPos getPlayerBlockPos();
// TODO returning null would be easier to understand but might make things harder to parse in some cases
/** @return (0,0) if no player is loaded */ /** @return (0,0) if no player is loaded */
DhChunkPos getPlayerChunkPos(); DhChunkPos getPlayerChunkPos();
//================//
// level handling //
//================//
/** /**
* Returns the level the client is currently in. <br> * Returns the level the client is currently in. <br>
* Returns null if the client isn't in a level. * Returns null if the client isn't in a level.
@@ -98,49 +78,37 @@ public interface IMinecraftClientWrapper extends IBindable
*/ */
IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager); IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager);
IProfilerWrapper getProfiler();
/** Returns all worlds available to the server */
ArrayList<ILevelWrapper> getAllServerWorlds(); //===========//
// messaging //
//===========//
void sendChatMessage(String string); void sendChatMessage(String string);
/** Will default to sending a chat message if not supported by the current MC version */
/**
* Will default to sending a chat message if not supported by
* the current MC version (1.19.2 and older).
*/
void sendOverlayMessage(String string); void sendOverlayMessage(String string);
/** Sends the given message to chat with a formatted prefix and color based on the log level. */
default void logToChat(Level logLevel, String message)
{
String prefix = "[" + ModInfo.READABLE_NAME + "] ";
if (logLevel == Level.ERROR)
{
prefix += "\u00A74";
}
else if (logLevel == Level.WARN)
{
prefix += "\u00A76";
}
else if (logLevel == Level.INFO)
{
prefix += "\u00A7f";
}
else if (logLevel == Level.DEBUG)
{
prefix += "\u00A77";
}
else if (logLevel == Level.TRACE)
{
prefix += "\u00A78";
}
else
{
prefix += "\u00A7f";
}
prefix += "\u00A7l\u00A7u";
prefix += logLevel.name();
prefix += ":\u00A7r ";
this.sendChatMessage(prefix + message);
} //==========================//
// vanilla option overrides //
//==========================//
void disableVanillaClouds();
void disableVanillaChunkFadeIn();
//======//
// misc //
//======//
IProfilerWrapper getProfiler();
/** /**
* Crashes Minecraft, displaying the given errorMessage <br> <br> * Crashes Minecraft, displaying the given errorMessage <br> <br>
@@ -150,15 +118,17 @@ public interface IMinecraftClientWrapper extends IBindable
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br> * Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
* Exit Code: -1 <br> * Exit Code: -1 <br>
*/ */
void crashMinecraft(String errorMessage, Throwable exception); //FIXME: Move to IMinecraftSharedWrapper void crashMinecraft(String errorMessage, Throwable exception);
//=============//
// mod support //
//=============//
/** used for Optifine */
Object getOptionsObject(); Object getOptionsObject();
/**
* Executes the given task on Minecraft's render thread.
* @deprecated use {@link GLProxy#runningOnRenderThread()} instead
*/
@Deprecated
void executeOnRenderThread(Runnable runnable);
} }
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
import java.awt.Color; import java.awt.Color;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
@@ -46,8 +47,6 @@ public interface IMinecraftRenderWrapper extends IBindable
Color getFogColor(float partialTicks); Color getFogColor(float partialTicks);
default Color getSpecialFogColor(float partialTicks) { return getFogColor(partialTicks); }
/** Unless you really need to know if the player is blind, use {@link IMinecraftRenderWrapper#isFogStateSpecial()} instead */ /** Unless you really need to know if the player is blind, use {@link IMinecraftRenderWrapper#isFogStateSpecial()} instead */
boolean isFogStateSpecial(); boolean isFogStateSpecial();
@@ -58,9 +57,6 @@ public interface IMinecraftRenderWrapper extends IBindable
/** Measured in chunks */ /** Measured in chunks */
int getRenderDistance(); int getRenderDistance();
int getScreenWidth();
int getScreenHeight();
boolean mcRendersToFrameBuffer(); boolean mcRendersToFrameBuffer();
boolean runningLegacyOpenGL(); boolean runningLegacyOpenGL();
@@ -82,5 +78,8 @@ public interface IMinecraftRenderWrapper extends IBindable
@Nullable @Nullable
ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level); ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level);
float getShade(EDhDirection lodDirection);
} }
@@ -23,7 +23,6 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab
import java.io.File; import java.io.File;
//TODO: Maybe have IMCClientWrapper & IMCDedicatedWrapper extend this interface???
public interface IMinecraftSharedWrapper extends IBindable public interface IMinecraftSharedWrapper extends IBindable
{ {
boolean isDedicatedServer(); boolean isDedicatedServer();
@@ -32,6 +31,6 @@ public interface IMinecraftSharedWrapper extends IBindable
int getPlayerCount(); int getPlayerCount();
void setPreventAutoPause(boolean preventAutoPause);
} }
@@ -79,58 +79,6 @@ public abstract class AbstractOptifineAccessor implements IOptifineAccessor
// interface methods // // interface methods //
//===================// //===================//
//@Override
@Deprecated
public EDhApiFogDrawMode getFogDrawMode()
{
if (this.ofFogField == null)
{
// either optifine isn't installed,
// the variable name was changed, or
// the setup method wasn't called yet.
return EDhApiFogDrawMode.FOG_ENABLED;
}
int returnNum = 0;
try
{
returnNum = (int) this.ofFogField.get(this.mcOptionsObject);
}
catch (IllegalArgumentException | IllegalAccessException e)
{
LOGGER.error("Unable to get project fog draw mode from Optifine, error: ["+e.getMessage()+"].", e);
}
switch (returnNum)
{
default:
case 0: // optifine's "default" option,
// it should never be used, so default to fog Enabled
// normal options
case 1: // fast
case 2: // fancy
return EDhApiFogDrawMode.FOG_ENABLED;
case 3: // off
return EDhApiFogDrawMode.FOG_DISABLED;
}
}
@Override
public double getRenderResolutionMultiplier()
{
/*
* TODO remove comment when done, this is just here as reference
* Returns the percentage multiplier of the screen's current resolution. <br>
* 1.0 = 100% <br>
* 1.5 = 150% <br>
*/
// TODO
return 1.0;
}
public boolean getIsShaderActive() public boolean getIsShaderActive()
{ {
@@ -27,11 +27,4 @@ import java.util.HashSet;
public interface IOptifineAccessor extends IModAccessor public interface IOptifineAccessor extends IModAccessor
{ {
/**
* Returns the percentage multiplier of the screen's current resolution. <br>
* 1.0 = 100% <br>
* 1.5 = 150% <br>
*/
double getRenderResolutionMultiplier();
} }
@@ -385,6 +385,11 @@
"distanthorizons.config.client.advanced.graphics.culling.ignoredRenderCaveBlockCsv.@tooltip": "distanthorizons.config.client.advanced.graphics.culling.ignoredRenderCaveBlockCsv.@tooltip":
"A comma separated list of block resource locations that shouldn't be rendered \nif they are in a 0 sky light underground area. \nNote: air is always included in this list.", "A comma separated list of block resource locations that shouldn't be rendered \nif they are in a 0 sky light underground area. \nNote: air is always included in this list.",
"distanthorizons.config.client.advanced.graphics.overrideVanillaGraphicsSettings":
"Override Vanilla Settings",
"distanthorizons.config.client.advanced.graphics.overrideVanillaGraphicsSettings.@tooltip":
"If true some vanilla graphics settings will be automatically changed \nduring DH setup to provide a better experience. \n\nIE disabling vanilla clouds (which render on top of DH LODs), \nand chunk fading (DH already fades MC chunks).",
"distanthorizons.config.client.advanced.graphics.experimental": "distanthorizons.config.client.advanced.graphics.experimental":
@@ -720,6 +725,8 @@
"If DH detects that pooled objects are being garbage collected this will send a chat warning.", "If DH detects that pooled objects are being garbage collected this will send a chat warning.",
"distanthorizons.config.common.logging.warning.showHighVanillaRenderDistanceWarning": "distanthorizons.config.common.logging.warning.showHighVanillaRenderDistanceWarning":
"Show High Vanilla Render Distance Warning", "Show High Vanilla Render Distance Warning",
"distanthorizons.config.common.logging.warning.showGarbageCollectorWarning":
"Show Garbage Collector Warning",
"distanthorizons.config.common.logging.warning.showReplayWarningOnStartup": "distanthorizons.config.common.logging.warning.showReplayWarningOnStartup":
"Show Replay Warning", "Show Replay Warning",
"distanthorizons.config.common.logging.warning.showUpdateQueueOverloadedChatWarning": "distanthorizons.config.common.logging.warning.showUpdateQueueOverloadedChatWarning":
@@ -980,7 +987,7 @@
"Uncompressed", "Uncompressed",
"distanthorizons.config.enum.EDhApiDataCompressionMode.LZ4": "distanthorizons.config.enum.EDhApiDataCompressionMode.LZ4":
"Fastest/Big - LZ4", "Fastest/Big - LZ4",
"distanthorizons.config.enum.EDhApiDataCompressionMode.Z_STD": "distanthorizons.config.enum.EDhApiDataCompressionMode.Z_STD_BLOCK":
"Fastest/Small - Z_STD - Block", "Fastest/Small - Z_STD - Block",
"distanthorizons.config.enum.EDhApiDataCompressionMode.Z_STD_STREAM": "distanthorizons.config.enum.EDhApiDataCompressionMode.Z_STD_STREAM":
"Fast/Small - Z_STD - Stream", "Fast/Small - Z_STD - Stream",
@@ -27,7 +27,6 @@ import com.seibel.distanthorizons.coreapi.util.StringUtil;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
//import org.apache.commons.compress.compressors.zstandard.ZstdCompressorOutputStream; //import org.apache.commons.compress.compressors.zstandard.ZstdCompressorOutputStream;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test;
import java.io.*; import java.io.*;
@@ -204,7 +203,7 @@ public class CompressionTest
public void Zstd() // middle of the road public void Zstd() // middle of the road
{ {
String compressorName = "Zstd"; String compressorName = "Zstd";
this.testCompressor(compressorName, EDhApiDataCompressionMode.Z_STD); this.testCompressor(compressorName, EDhApiDataCompressionMode.Z_STD_BLOCK);
} }
//@Test //@Test
@@ -321,7 +321,7 @@ public class DataSourceRepoTests
Assert.assertFalse(pooledDto.compressedWorldCompressionModeByteArray.isEmpty()); Assert.assertFalse(pooledDto.compressedWorldCompressionModeByteArray.isEmpty());
try (FullDataSourceV2 dataSource = pooledDto.createUnitTestDataSource(); try (FullDataSourceV2 dataSource = pooledDto.createUnitTestDataSource();
FullDataSourceV2DTO compressedDto = FullDataSourceV2DTO.CreateFromDataSource(dataSource, EDhApiDataCompressionMode.Z_STD)) FullDataSourceV2DTO compressedDto = FullDataSourceV2DTO.CreateFromDataSource(dataSource, EDhApiDataCompressionMode.Z_STD_BLOCK))
{ {
repo.save(compressedDto); repo.save(compressedDto);