diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java index a77444d47..392e2206f 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java @@ -18,12 +18,12 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverri * This is the masthead of the API, almost everything you could want to do * can be achieved from here.
* For example: you can access singletons which handle the config or event binding.

- * + * * Q: Why should I use this class instead of just getting the API singleton I need?
- * + * * A: This way there is a lower chance of your code breaking if we change something on our end. * For example, if we realized there is a much better way of handling dependency injection we would keep the - * interface the same so your code doesn't have to change. Whereas if you were directly referencing + * interface the same so your code doesn't have to change. Whereas if you were directly referencing * the concrete object we replaced, there would be issues. * * @author James Seibel @@ -31,10 +31,10 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverri */ public class DhApi { - /** - * WARNING: + /** + * WARNING: * All objects in this class will be null until after DH initializes for the first time.

- * + * * Bind a custom {@link DhApiAfterDhInitEvent DhApiAfterDhInitEvent} * to {@link DhApi#events ApiCoreInjectors.events} in order to be notified when this class can * be safely used. @@ -44,8 +44,8 @@ public class DhApi /** Used to interact with Distant Horizons' Configs. */ public static IDhApiConfig configs = null; - /** - * Used to interact with Distant Horizons' terrain data. + /** + * Used to interact with Distant Horizons' terrain data. * Designed to be used in conjunction with {@link DhApi.Delayed#worldProxy}. */ public static IDhApiTerrainDataRepo terrainRepo = null; @@ -81,8 +81,8 @@ public class DhApi /** This version should be updated whenever non-breaking fixes are added to the Distant Horizons API. */ public static int getApiPatchVersion() { return ModInfo.API_PATH_VERSION; } - /** - * Returns the mod's semantic version number in the format: Major.Minor.Patch + /** + * Returns the mod's semantic version number in the format: Major.Minor.Patch * with optional extensions "-a" for alpha, "-b" for beta, and -dev for unstable development builds.
* Examples: "1.6.9-a", "1.7.0-a-dev", "2.1.0-b", "3.0.0", "3.1.4-dev" */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/EDhApiDetailLevel.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/EDhApiDetailLevel.java index 329926800..8fcd01335 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/EDhApiDetailLevel.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/EDhApiDetailLevel.java @@ -9,11 +9,11 @@ package com.seibel.distanthorizons.api.enums; * is, with the smallest being 0 (1 block wide).
* The width of a detail level can be calculated by putting the detail level to the power of 2.
* Example for the chunk detail level (4): 2^4 = 16 blocks wide

- * + * * This enum doesn't contain all valid detail levels, only those most likely to be needed. - * Detail levels 1,2,3, ... 255 are all technically valid detail levels - * (although anything beyond {@link EDhApiDetailLevel#REGION} may be difficult deal with). - * + * Detail levels 1,2,3, ... 255 are all technically valid detail levels + * (although anything beyond {@link EDhApiDetailLevel#REGION} may be difficult deal with). + * * @author James Seibel * @version 2022-12-5 */ @@ -23,14 +23,14 @@ public enum EDhApiDetailLevel // when adding items up the API minor version // when removing items up the API major version - /** + /** * detail level: 0
- * width in Blocks: 1 + * width in Blocks: 1 */ BLOCK(0, 1), /** * detail level: 4
- * width in Blocks: 16 + * width in Blocks: 16 */ CHUNK(4, 16), /** diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/DisallowSelectingViaConfigGui.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/DisallowSelectingViaConfigGui.java index 2e095f9f6..4b609801e 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/DisallowSelectingViaConfigGui.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/DisallowSelectingViaConfigGui.java @@ -7,8 +7,8 @@ import java.lang.annotation.RetentionPolicy; * Add this annotation to enum values that * are valid config options, but shouldn't be selectable * when toggling through the options.

- * - * Example: A preset's "custom" option shouldn't be selectable + * + * Example: A preset's "custom" option shouldn't be selectable */ @Retention(RetentionPolicy.RUNTIME) public @interface DisallowSelectingViaConfigGui diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EBufferRebuildTimes.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EBufferRebuildTimes.java index 2995141d3..dc8d71a93 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EBufferRebuildTimes.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EBufferRebuildTimes.java @@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.config; * RARE

* * Determines how fast the buffers should be regenerated - * + * * @author Leonardo Amato * @version 9-25-2021 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGenerationPriority.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGenerationPriority.java index b4ac64283..1bcdb313a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGenerationPriority.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGenerationPriority.java @@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.config; * * Determines which LODs should have priority when generating * outside the normal view distance. - * + * * @author Leonardo Amato * @version 12-1-2021 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGpuUploadMethod.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGpuUploadMethod.java index 9c9f40a5f..92e01c46a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGpuUploadMethod.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGpuUploadMethod.java @@ -34,7 +34,7 @@ public enum EGpuUploadMethod { /** Picks the best option based on the GPU the user has. */ AUTO(false, false), - + // commented out since it isn't currently in use //BUFFER_STORAGE_MAPPING(true, true), @@ -43,14 +43,14 @@ public enum EGpuUploadMethod /** Fast rendering but may stutter when uploading. */ SUB_DATA(false, false), - - /** + + /** * May end up storing buffers in System memory.
* Fast rending if in GPU memory, slow if in system memory,
- * but won't stutter when uploading. + * but won't stutter when uploading. */ BUFFER_MAPPING(true, false), - + /** Fast rendering but may stutter when uploading. */ DATA(false, false); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EHorizontalQuality.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EHorizontalQuality.java index 72c81292a..631f3d260 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EHorizontalQuality.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EHorizontalQuality.java @@ -52,8 +52,8 @@ public enum EHorizontalQuality EHorizontalQuality(double quadraticBase, int distanceUnitInBlocks) { - this.quadraticBase = quadraticBase; + this.quadraticBase = quadraticBase; this.distanceUnitInBlocks = distanceUnitInBlocks; } - + } \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELightGenerationMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELightGenerationMode.java index 914d8b265..491b25676 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELightGenerationMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELightGenerationMode.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.api.enums.config; /** diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELoggerMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELoggerMode.java index 299aa5a61..c5a331ce6 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELoggerMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/ELoggerMode.java @@ -16,30 +16,32 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.api.enums.config; + import org.apache.logging.log4j.Level; public enum ELoggerMode { - DISABLED(Level.OFF, Level.OFF), - LOG_ALL_TO_FILE(Level.ALL, Level.OFF), - LOG_ERROR_TO_CHAT(Level.ALL, Level.ERROR), - LOG_WARNING_TO_CHAT(Level.ALL, Level.WARN), - LOG_INFO_TO_CHAT(Level.ALL, Level.INFO), - LOG_DEBUG_TO_CHAT(Level.ALL, Level.DEBUG), - LOG_ALL_TO_CHAT(Level.ALL, Level.ALL), - LOG_ERROR_TO_CHAT_AND_FILE(Level.ERROR, Level.ERROR), - LOG_WARNING_TO_CHAT_AND_FILE(Level.WARN, Level.WARN), - LOG_INFO_TO_CHAT_AND_FILE(Level.INFO, Level.INFO), - LOG_DEBUG_TO_CHAT_AND_FILE(Level.DEBUG, Level.DEBUG), - LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.WARN), - LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.ERROR), - ; - public final Level levelForFile; - public final Level levelForChat; - ELoggerMode(Level levelForFile, Level levelForChat) { - this.levelForFile = levelForFile; - this.levelForChat = levelForChat; - } + DISABLED(Level.OFF, Level.OFF), + LOG_ALL_TO_FILE(Level.ALL, Level.OFF), + LOG_ERROR_TO_CHAT(Level.ALL, Level.ERROR), + LOG_WARNING_TO_CHAT(Level.ALL, Level.WARN), + LOG_INFO_TO_CHAT(Level.ALL, Level.INFO), + LOG_DEBUG_TO_CHAT(Level.ALL, Level.DEBUG), + LOG_ALL_TO_CHAT(Level.ALL, Level.ALL), + LOG_ERROR_TO_CHAT_AND_FILE(Level.ERROR, Level.ERROR), + LOG_WARNING_TO_CHAT_AND_FILE(Level.WARN, Level.WARN), + LOG_INFO_TO_CHAT_AND_FILE(Level.INFO, Level.INFO), + LOG_DEBUG_TO_CHAT_AND_FILE(Level.DEBUG, Level.DEBUG), + LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.WARN), + LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.ERROR), + ; + public final Level levelForFile; + public final Level levelForChat; + ELoggerMode(Level levelForFile, Level levelForChat) + { + this.levelForFile = levelForFile; + this.levelForChat = levelForChat; + } } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EMaxHorizontalResolution.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EMaxHorizontalResolution.java index b36c00187..6da20b471 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EMaxHorizontalResolution.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EMaxHorizontalResolution.java @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil; * FOUR_BLOCKS
* HALF_CHUNK
* CHUNK
- * + * * @author James Seibel * @author Leonardo Amato * @version 2023-6-14 diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EServerFolderNameMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EServerFolderNameMode.java index 6d14b928e..33c95714d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EServerFolderNameMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EServerFolderNameMode.java @@ -27,7 +27,7 @@ package com.seibel.distanthorizons.api.enums.config; * NAME_IP_PORT_MC_VERSION,

* * Determines how the multiplayer folders should be named. - * + * * @author James Seibel * @version 2022-7-1 */ @@ -41,7 +41,7 @@ public enum EServerFolderNameMode /** Only use the server name */ NAME_ONLY, - /** + /** * {SERVER_NAME} IP {IP}
* Example: Minecraft Server IP 192.168.1.40 */ @@ -53,10 +53,10 @@ public enum EServerFolderNameMode */ NAME_IP_PORT, - /** + /** * {SERVER_NAME} IP {IP}
* Example: Minecraft Server IP 192.168.1.40:25565 GameVersion 1.16.5

- * + * * Not normally recommended, since the game version can change if the * server installs paper or some other jar.
* This is just here to provide backwards compatibility. diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVanillaOverdraw.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVanillaOverdraw.java index d8b7ced6a..683a76cb5 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVanillaOverdraw.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVanillaOverdraw.java @@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.config; * * This represents how far the LODs should overlap with * the vanilla Minecraft terrain. - * + * * @author James Seibel * @version 2022-6-30 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVerticalQuality.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVerticalQuality.java index c5655370f..7b92feb82 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVerticalQuality.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EVerticalQuality.java @@ -33,11 +33,11 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil; */ public enum EVerticalQuality { - HEIGHT_MAP(new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }), - LOW(new int[] { 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 }), - MEDIUM(new int[] { 6, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1 }), - HIGH(new int[] { 8, 6, 4, 2, 2, 2, 2, 1, 1, 1, 1 }), - EXTREME(new int[] { 16, 8, 4, 2, 2, 2, 2, 1, 1, 1, 1 }); + HEIGHT_MAP(new int[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}), + LOW(new int[]{4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1}), + MEDIUM(new int[]{6, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1}), + HIGH(new int[]{8, 6, 4, 2, 2, 2, 2, 1, 1, 1, 1}), + EXTREME(new int[]{16, 8, 4, 2, 2, 2, 2, 1, 1, 1, 1}); /** represents how many LODs can be rendered in a single vertical slice */ public final int[] maxVerticalData; @@ -48,11 +48,11 @@ public enum EVerticalQuality - public int calculateMaxVerticalData(byte dataDetail) + public int calculateMaxVerticalData(byte dataDetail) { // for detail levels lower than what the enum defines, use the lowest quality item int index = MathUtil.clamp(0, dataDetail, this.maxVerticalData.length - 1); return this.maxVerticalData[index]; - } + } } \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EQualityPreset.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EQualityPreset.java index c34d8e4d4..76ed6ca5c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EQualityPreset.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EQualityPreset.java @@ -23,7 +23,7 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui /** * CUSTOM,

- * + * * MINIMUM,
* LOW,
* MEDIUM,
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EThreadPreset.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EThreadPreset.java index 87e9f09ab..ab85d17c9 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EThreadPreset.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/quickOptions/EThreadPreset.java @@ -23,7 +23,7 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui /** * CUSTOM,

- * + * * MINIMAL_IMPACT,
* LOW_IMPACT,
* BALANCED,
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java index c10d5aeb1..b66cc3c10 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDebugRendering.java @@ -53,27 +53,37 @@ public enum EDebugRendering SHOW_RENDER_SOURCE_FLAG; - public static EDebugRendering next(EDebugRendering type) + public static EDebugRendering next(EDebugRendering type) { - switch (type) + switch (type) { - case OFF: return SHOW_DETAIL; - case SHOW_DETAIL: return SHOW_GENMODE; - case SHOW_GENMODE: return SHOW_OVERLAPPING_QUADS; - case SHOW_OVERLAPPING_QUADS: return SHOW_RENDER_SOURCE_FLAG; - default: return OFF; + case OFF: + return SHOW_DETAIL; + case SHOW_DETAIL: + return SHOW_GENMODE; + case SHOW_GENMODE: + return SHOW_OVERLAPPING_QUADS; + case SHOW_OVERLAPPING_QUADS: + return SHOW_RENDER_SOURCE_FLAG; + default: + return OFF; } } - - public static EDebugRendering previous(EDebugRendering type) + + public static EDebugRendering previous(EDebugRendering type) { - switch (type) + switch (type) { - case OFF: return SHOW_RENDER_SOURCE_FLAG; - case SHOW_RENDER_SOURCE_FLAG: return SHOW_OVERLAPPING_QUADS; - case SHOW_OVERLAPPING_QUADS: return SHOW_GENMODE; - case SHOW_GENMODE: return SHOW_DETAIL; - default: return OFF; + case OFF: + return SHOW_RENDER_SOURCE_FLAG; + case SHOW_RENDER_SOURCE_FLAG: + return SHOW_OVERLAPPING_QUADS; + case SHOW_OVERLAPPING_QUADS: + return SHOW_GENMODE; + case SHOW_GENMODE: + return SHOW_DETAIL; + default: + return OFF; } } } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogColorMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogColorMode.java index 226be2934..0c9fa7ab2 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogColorMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogColorMode.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.api.enums.rendering; /** * USE_DEFAULT_FOG_COLOR,
* USE_SKY_COLOR,
- * + * * @author James Seibel * @version 2022-6-9 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDistance.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDistance.java index 42764a3b0..0656c38c3 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDistance.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDistance.java @@ -21,7 +21,7 @@ package com.seibel.distanthorizons.api.enums.rendering; /** * NEAR, FAR, or NEAR_AND_FAR. - * + * * @author James Seibel * @version 2022-6-2 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDrawMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDrawMode.java index 7c57affb0..6dec26c37 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDrawMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EFogDrawMode.java @@ -23,7 +23,7 @@ package com.seibel.distanthorizons.api.enums.rendering; * USE_OPTIFINE_FOG_SETTING,
* FOG_ENABLED,
* FOG_DISABLED
- * + * * @author James Seibel * @version 2022-6-2 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EHeightFogMixMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EHeightFogMixMode.java index af7100d7c..86df7c176 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EHeightFogMixMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EHeightFogMixMode.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.api.enums.rendering; /** @@ -36,14 +36,14 @@ package com.seibel.distanthorizons.api.enums.rendering; */ public enum EHeightFogMixMode { - BASIC, - IGNORE_HEIGHT, - ADDITION, - MAX, - MULTIPLY, - INVERSE_MULTIPLY, - LIMITED_ADDITION, - MULTIPLY_ADDITION, - INVERSE_MULTIPLY_ADDITION, - AVERAGE, + BASIC, + IGNORE_HEIGHT, + ADDITION, + MAX, + MULTIPLY, + INVERSE_MULTIPLY, + LIMITED_ADDITION, + MULTIPLY_ADDITION, + INVERSE_MULTIPLY_ADDITION, + AVERAGE, } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ERendererMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ERendererMode.java index e5f83edf1..97412e103 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ERendererMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ERendererMode.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.api.enums.rendering; /** @@ -28,36 +28,42 @@ package com.seibel.distanthorizons.api.enums.rendering; */ public enum ERendererMode { - // Reminder: - // when adding items up the API minor version - // when removing items up the API major version - - - DEFAULT, - DEBUG, - DISABLED; - - - /** Used by the config GUI to cycle through the available rendering options */ - public static ERendererMode next(ERendererMode type) - { - switch (type) - { - case DEFAULT: return DEBUG; - case DEBUG: return DISABLED; - default: return DEFAULT; - } - } - - /** Used by the config GUI to cycle through the available rendering options */ - public static ERendererMode previous(ERendererMode type) - { - switch (type) - { - case DEFAULT: return DISABLED; - case DEBUG: return DEFAULT; - default: return DEBUG; - } - } - + // Reminder: + // when adding items up the API minor version + // when removing items up the API major version + + + DEFAULT, + DEBUG, + DISABLED; + + + /** Used by the config GUI to cycle through the available rendering options */ + public static ERendererMode next(ERendererMode type) + { + switch (type) + { + case DEFAULT: + return DEBUG; + case DEBUG: + return DISABLED; + default: + return DEFAULT; + } + } + + /** Used by the config GUI to cycle through the available rendering options */ + public static ERendererMode previous(ERendererMode type) + { + switch (type) + { + case DEFAULT: + return DISABLED; + case DEBUG: + return DEFAULT; + default: + return DEBUG; + } + } + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ETransparency.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ETransparency.java index 56bbe9eb2..6df20f7e0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ETransparency.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/ETransparency.java @@ -34,10 +34,10 @@ public enum ETransparency DISABLED(false, false), FAKE(true, true), COMPLETE(true, false); - + public final boolean transparencyEnabled; public final boolean fakeTransparencyEnabled; - + ETransparency(boolean transparencyEnabled, boolean fakeTransparencyEnabled) { this.transparencyEnabled = transparencyEnabled; diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/worldGeneration/EDhApiDistantGeneratorMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/worldGeneration/EDhApiDistantGeneratorMode.java index e46f7e957..bd784589d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/worldGeneration/EDhApiDistantGeneratorMode.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/worldGeneration/EDhApiDistantGeneratorMode.java @@ -28,7 +28,7 @@ package com.seibel.distanthorizons.api.enums.worldGeneration; * FULL

* * In order of fastest to slowest. - * + * * @author James Seibel * @author Leonardo Amato * @version 2022-12-10 diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/IDhApiUnsafeWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/IDhApiUnsafeWrapper.java index 0104a0f6d..dbc3b15f2 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/IDhApiUnsafeWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/IDhApiUnsafeWrapper.java @@ -3,7 +3,7 @@ package com.seibel.distanthorizons.api.interfaces; /** * Implemented by wrappers so developers can * access the underlying Minecraft object(s). - * + * * @author James Seibel * @version 2023-6-17 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBiomeWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBiomeWrapper.java index 56e058107..eaba0a22c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBiomeWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBiomeWrapper.java @@ -23,11 +23,12 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; /** * A Minecraft version independent way of handling Biomes. - * + * * @author James Seibel * @version 3-5-2022 */ public interface IDhApiBiomeWrapper extends IDhApiUnsafeWrapper { String getName(); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java index 51b05df34..41800c69c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java @@ -4,13 +4,13 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; /** * A Minecraft version independent way of handling Blocks. - * + * * @author James Seibel * @version 2023-6-11 */ public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper { - boolean isAir(); + boolean isAir(); boolean isSolid(); boolean isLiquid(); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java index bb1e8330b..b46370159 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java @@ -6,7 +6,7 @@ import com.seibel.distanthorizons.api.interfaces.config.client.*; /** * This interfaces holds all config groups * the API has access to for easy access. - * + * * @author James Seibel * @version 2023-6-14 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigGroup.java index 0dae82a8c..007afeb1c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigGroup.java @@ -5,7 +5,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab /** * This interface is just used to organize API config groups so * they can be more easily handled together. - * + * * @author James Seibel * @version 9-15-2022 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java index 1fe304503..e20ba66d4 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java @@ -4,7 +4,6 @@ package com.seibel.distanthorizons.api.interfaces.config; * An interface for Distant Horizon's Config. * * @param The data type of this config. - * * @author James Seibel * @version 2022-9-15 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/both/IDhApiWorldGenerationConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/both/IDhApiWorldGenerationConfig.java index 5e7be4033..b584961ff 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/both/IDhApiWorldGenerationConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/both/IDhApiWorldGenerationConfig.java @@ -44,7 +44,7 @@ public interface IDhApiWorldGenerationConfig extends IDhApiConfigGroup /** Defines to what level LOD chunks will be generated. */ IDhApiConfigValue distantGeneratorMode(); - /** + /** * Defines what lighting engine will be used when * Distant Horizons generates chunks. */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java index 4a6f31a4c..37db89542 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java @@ -144,9 +144,9 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup /** If enabled vanilla chunk rendering is disabled and only fake chunks are rendered. */ IDhApiConfigValue lodOnlyMode(); - /** - * Setting this to a non-zero number will modify vanilla Minecraft's LOD Bias, - * increasing how quickly its textures fade away. + /** + * Setting this to a non-zero number will modify vanilla Minecraft's LOD Bias, + * increasing how quickly its textures fade away. */ IDhApiConfigValue lodBias(); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiMultiThreadingConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiMultiThreadingConfig.java index bcc506593..cadfe3be9 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiMultiThreadingConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiMultiThreadingConfig.java @@ -46,9 +46,9 @@ public interface IDhApiMultiThreadingConfig extends IDhApiConfigGroup /** Defines how many file handler threads are used. */ IDhApiConfigValue fileHandlerThreads(); - /** + /** * Defines how many Full to Render data converter threads are used.

- * + * * Full data - Distant Horizons data based on BlockState and Biome IDs
* Render data - color data used when Distant Horizons is rendering */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java index c387a9745..b2735b455 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java @@ -9,7 +9,7 @@ import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint; /** * Used to interface with Distant Horizons' terrain data. - * + * * @author James Seibel * @version 2023-6-22 */ @@ -25,9 +25,9 @@ public interface IDhApiTerrainDataRepo /** Returns every datapoint in the column located at the given block X and Z position top to bottom. */ DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ); - /** + /** * Returns every datapoint in the given chunk's X and Z position.

- * + * * The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex]
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the chunk's position.
* The column data is ordered from top to bottom. Note: each column may have a different number of values.
@@ -46,21 +46,22 @@ public interface IDhApiTerrainDataRepo /** * Returns every datapoint in the column located at the given detail level and X/Z position.
* This can be used to return terrain data for non-standard sizes (IE 2x2 blocks or 2x2 chunks). - * + * * @param detailLevel a positive byte defining the detail level of the returned data.
- * Every increase doubles the width of the returned area.
- * Example values: 0 = block, 1 = 2x2 blocks, 2 = 4x4 blocks, ... 4 = chunk (16x16 blocks), ... 9 = region (512x512 blocks)
- * See {@link EDhApiDetailLevel} for more information. + * Every increase doubles the width of the returned area.
+ * Example values: 0 = block, 1 = 2x2 blocks, 2 = 4x4 blocks, ... 4 = chunk (16x16 blocks), ... 9 = region (512x512 blocks)
+ * See {@link EDhApiDetailLevel} for more information. */ DhApiResult getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ); /** * Returns the datapoint and position of the LOD * at the end of the given ray.

- * + * * Will return "success" with a null datapoint if the ray reaches the max length without finding any data. */ - DhApiResult raycast(IDhApiLevelWrapper levelWrapper, + DhApiResult raycast( + IDhApiLevelWrapper levelWrapper, double rayOriginX, double rayOriginY, double rayOriginZ, float rayDirectionX, float rayDirectionY, float rayDirectionZ, int maxRayBlockLength); @@ -73,19 +74,18 @@ public interface IDhApiTerrainDataRepo /** * Sets the LOD data for the given chunk at the chunk's position.

- * + * * Notes:
* - Only works if the given {@link IDhApiLevelWrapper} points to a loaded level.
* - If the player travels to this chunk, or the chunk is updated in some other way; your data will be replaced - * by whatever the current chunk is.
+ * by whatever the current chunk is.
* - This method may not update the LOD data immediately. Any other chunks have - * been queued to update, they will be handled first. + * been queued to update, they will be handled first. * * @param levelWrapper the level wrapper that the chunk should be saved to. * @param chunkObjectArray see {@link IDhApiWorldGenerator#generateChunks} for what objects are expected. - * - * @throws ClassCastException if chunkObjectArray doesn't contain the right objects. - * The exception will contain the expected object(s). + * @throws ClassCastException if chunkObjectArray doesn't contain the right objects. + * The exception will contain the expected object(s). */ public DhApiResult overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException; diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java index 3ef35e6db..ff2e32dbd 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java @@ -34,8 +34,8 @@ public interface IDhApiEventInjector extends IDependencyInjector /** * Unlinks the given event handler, preventing the handler from being called in the future. * - * @throws IllegalArgumentException if the implementation object doesn't implement the interface * @return true if the handler was unbound, false if the handler wasn't bound. + * @throws IllegalArgumentException if the implementation object doesn't implement the interface */ // Note to self: Don't try adding a generic type to IDhApiEvent, the constructor won't accept it boolean unbind(Class dependencyInterface, Class dependencyClassToRemove) throws IllegalArgumentException; @@ -46,8 +46,8 @@ public interface IDhApiEventInjector extends IDependencyInjector * * @param abstractEvent event type * @param eventParameterObject event parameter - * @return if any of bound event handlers returned that this event should be canceled. * @param the parameter type taken by the event handlers. + * @return if any of bound event handlers returned that this event should be canceled. */ > boolean fireAllEvents(Class abstractEvent, T eventParameterObject); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java index 2beb5ae3a..cbb274e75 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java @@ -46,9 +46,9 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh // TODO what does this mean? int genChunkWidth = BitShiftUtil.powerOfTwo(granularity - 4); - for (int chunkX = chunkPosMinX; chunkX < chunkPosMinX+genChunkWidth; chunkX++) + for (int chunkX = chunkPosMinX; chunkX < chunkPosMinX + genChunkWidth; chunkX++) { - for (int chunkZ = chunkPosMinZ; chunkZ< chunkPosMinZ+genChunkWidth; chunkZ++) + for (int chunkZ = chunkPosMinZ; chunkZ < chunkPosMinZ + genChunkWidth; chunkZ++) { Object[] rawMcObjectArray = this.generateChunk(chunkX, chunkZ, generatorMode); resultConsumer.accept(rawMcObjectArray); @@ -60,10 +60,10 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh /** * This method is called to generate terrain over a given area * from a thread defined by Distant Horizons.

- * - * See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks} + * + * See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks} * for the list of Object's this method should return along with additional documentation. - * + * * @see IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator#generateChunks */ public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java index e0cd3515b..badb0749f 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java @@ -30,10 +30,10 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable * Minimum detail level is 0 (1 block)
* Default detail level is 0
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.

- * + * * TODO: System currently only supports 1x1 block per data. - * - * @see EDhApiDetailLevel + * + * @see EDhApiDetailLevel */ default byte getSmallestDataDetailLevel() { return EDhApiDetailLevel.BLOCK.detailLevel; } /** @@ -41,32 +41,32 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable * Minimum detail level is 0 (1 block)
* Default detail level is 0
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}. - * - * @see EDhApiDetailLevel + * + * @see EDhApiDetailLevel */ default byte getLargestDataDetailLevel() { return EDhApiDetailLevel.BLOCK.detailLevel; } /** * When creating generation requests the system will attempt to group nearby tasks together.

* What is the minimum size a single generation call can batch together?
- * + * * Minimum detail level is 4 (the size of a MC chunk)
* Default detail level is 4
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}. - * - * @see EDhApiDetailLevel + * + * @see EDhApiDetailLevel */ default byte getMinGenerationGranularity() { return EDhApiDetailLevel.CHUNK.detailLevel; } /** * When creating generation requests the system will attempt to group nearby tasks together.

* What is the maximum size a single generation call can batch together?
- * + * * Minimum detail level is 4 (the size of a MC chunk)
* Default detail level is 6 (4x4 chunks)
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}. - * - * @see EDhApiDetailLevel + * + * @see EDhApiDetailLevel */ default byte getMaxGenerationGranularity() { return (byte) (EDhApiDetailLevel.CHUNK.detailLevel + 2); } @@ -82,19 +82,20 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable /** * This method is called by Distant Horizons to generate terrain over a given area.

- * - * After a chunk has been generated it (and any necessary supporting objects as listed below) should be passed into the + * + * After a chunk has been generated it (and any necessary supporting objects as listed below) should be passed into the * resultConsumer's {@link Consumer#accept} method. If the Consumer is given the wrong data * type(s) it will disable the world generator and log an error with a list of objects it was expecting.
* Note: these objects are minecraft version dependent and will change without notice! * Please run your generator in game at least once to confirm the objects you are returning are correct.

- * + * * Consumer expected inputs for each minecraft version (in order):
* 1.18: [net.minecraft.world.level.chunk.ChunkAccess] and [net.minecraft.world.level.LevelReader]
* 1.19: [net.minecraft.world.level.chunk.ChunkAccess] and [net.minecraft.world.level.LevelReader]
* 1.20: [net.minecraft.world.level.chunk.ChunkAccess] and [net.minecraft.world.level.LevelReader]
*/ - CompletableFuture generateChunks(int chunkPosMinX, int chunkPosMinZ, + CompletableFuture generateChunks( + int chunkPosMinX, int chunkPosMinZ, byte granularity, byte targetDataDetail, EDhApiDistantGeneratorMode generatorMode, ExecutorService worldGeneratorThreadPool, Consumer resultConsumer); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java index cd3d70703..3a0ec7c04 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderProxy.java @@ -23,24 +23,24 @@ import com.seibel.distanthorizons.api.objects.DhApiResult; /** * Used to interact with Distant Horizons' rendering system. - * + * * @author James Seibel * @version 2023-2-8 */ public interface IDhApiRenderProxy { - /** + /** * Forces any cached render data to be deleted and regenerated. * This is generally called whenever resource packs are changed or specific * rendering settings are changed in Distant Horizon's config.

- * + * * If this is called on a dedicated server it won't do anything and will return {@link DhApiResult#success} = false

- * + * * Background:
* Distant Horizons has two different file formats: Full data and Render data.
* - Full data files store the block, biome, etc. information and is the result of loading or generating new chunks.
* - Render data files store LOD colors and are created using the Full data and currently loaded resource packs.
- * This is the data cleared by this method. + * This is the data cleared by this method. */ DhApiResult clearRenderDataCache(); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java index a45918c24..cf5f1afcf 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java @@ -25,7 +25,7 @@ import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; /** * Can be either a Server or Client level.
* A level is equivalent to a dimension in vanilla Minecraft. - * + * * @author James Seibel * @version 2022-7-14 */ @@ -42,7 +42,7 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper /** Returns the max block height of the level(?) */ int getHeight(); - /** + /** * Returns the lowest possible block position for the level.
* For MC versions before 1.18 this will return 0. */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiWorldProxy.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiWorldProxy.java index 5cb4d36bc..81b42d04c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiWorldProxy.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiWorldProxy.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.api.interfaces.world; /** * Used to interact with Distant Horizons' current world.
* A world is equivalent to a single server connection or a singleplayer world. - * + * * @author James Seibel * @version 2022-11-20 */ @@ -32,10 +32,10 @@ public interface IDhApiWorldProxy boolean worldLoaded(); - /** + /** * In singleplayer this will return the level the player is currently in.
* In multiplayer this will return null. - * + * * @throws IllegalStateException if no world is loaded */ IDhApiLevelWrapper getSinglePlayerLevel() throws IllegalStateException; @@ -43,18 +43,18 @@ public interface IDhApiWorldProxy /** @throws IllegalStateException if no world is loaded */ Iterable getAllLoadedLevelWrappers() throws IllegalStateException; - /** + /** * In the case of servers running multiverse there may be multiple levels for the same dimensionType. * - * @throws IllegalStateException if no world is loaded + * @throws IllegalStateException if no world is loaded */ Iterable getAllLoadedLevelsForDimensionType(IDhApiDimensionTypeWrapper dimensionTypeWrapper) throws IllegalStateException; /** * Returns any dimensions that have names containing the given string (case-insensitive).
- * In the case of servers running multiverse there may be multiple levels for the same dimensionType. + * In the case of servers running multiverse there may be multiple levels for the same dimensionType. * - * @throws IllegalStateException if no world is loaded + * @throws IllegalStateException if no world is loaded */ Iterable getAllLoadedLevelsWithDimensionNameLike(String dimensionName) throws IllegalStateException; diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/DhApiEventRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/DhApiEventRegister.java index 7f2dce44f..4a355d30b 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/DhApiEventRegister.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/DhApiEventRegister.java @@ -30,7 +30,7 @@ public class DhApiEventRegister return DhApiResult.createFail(e.getMessage()); } } - + /** * Unregisters the given event handler for this event if one has been registered.
* If no eventHandler of the given class has been registered the result will return diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterDhInitEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterDhInitEvent.java index 3380970d8..7af70d103 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterDhInitEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterDhInitEvent.java @@ -6,7 +6,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp /** * Fired after Distant Horizons finishes running its setup. - * + * * @author James Seibel * @version 2023-6-23 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java index 7d4846a52..08e36222e 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java @@ -8,10 +8,10 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp * Fired after Distant Horizons finishes rendering a frame.
* At this point DH will have also finished cleaning up any modifications it * did to the OpenGL state, so the state should be back to Minecraft's defaults. - * - * @see DhApiRenderParam + * * @author James Seibel * @version 2023-6-23 + * @see DhApiRenderParam */ public abstract class DhApiAfterRenderEvent implements IDhApiEvent { @@ -37,6 +37,7 @@ public abstract class DhApiAfterRenderEvent implements IDhApiEvent * IE this is called before Forge's initClient/initServer or Fabric's init method. - * + * * @author James Seibel * @version 2023-6-23 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java index 9998bd4c0..3872fd1d0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderEvent.java @@ -7,7 +7,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp /** * Called before Distant Horizons starts rendering a frame.
* Canceling the event will prevent DH from rendering that frame. - * + * * @author James Seibel * @version 2023-6-23 */ @@ -35,6 +35,7 @@ public abstract class DhApiBeforeRenderEvent implements IDhApiCancelableEvent * By the time this event has been fired, the chunk modification should have propagated * to DH's full data source, but may not have been updated in the render data source. - * - * @see IDhApiTerrainDataRepo + * * @author James Seibel * @version 2023-6-23 + * @see IDhApiTerrainDataRepo */ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent { @@ -41,15 +41,16 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent * Note: this may be fired before Minecraft has loaded in the player. - * + * * @author James Seibel * @version 2023-6-23 */ @@ -35,6 +35,7 @@ public abstract class DhApiLevelLoadEvent implements IDhApiEvent extends IDhApiEvent /** * Shouldn't be called.

- * + * * The {@link IDhApiCancelableEvent#fireEvent(DhApiCancelableEventParam)} method should be used instead. * This override method is present to prevent API users from having to implement it themselves. - * + * * @deprecated marked as deprecated to warn that this method shouldn't be used.
- * DH Internal Note: Is there a better way to format the {@link IDhApiEvent} classes so we don't need this method? - * It would be better to completely hide this method so it isn't possible to accidentally call. + * DH Internal Note: Is there a better way to format the {@link IDhApiEvent} classes so we don't need this method? + * It would be better to completely hide this method so it isn't possible to accidentally call. */ @Deprecated @Override @@ -31,7 +31,7 @@ public interface IDhApiCancelableEvent extends IDhApiEvent { if (!input.getClass().isAssignableFrom(DhApiCancelableEventParam.class)) { - throw new IllegalArgumentException("Programmer error. ["+IDhApiCancelableEvent.class.getSimpleName()+"] was given a ["+DhApiEventParam.class.getSimpleName()+"] when it should only be given a ["+DhApiCancelableEventParam.class.getSimpleName()+"]."); + throw new IllegalArgumentException("Programmer error. [" + IDhApiCancelableEvent.class.getSimpleName() + "] was given a [" + DhApiEventParam.class.getSimpleName() + "] when it should only be given a [" + DhApiCancelableEventParam.class.getSimpleName() + "]."); } this.fireEvent((DhApiCancelableEventParam) input); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiEvent.java index 5d6d5eeb9..9ab1b9f2b 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiEvent.java @@ -5,9 +5,8 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab /** * The interface used by all DH Api events. - * + * * @param This is the datatype that will be passed into the event handler's method. - * * @author James Seibel * @version 2023-6-23 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiOneTimeEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiOneTimeEvent.java index 627c6e4ef..b866387ff 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiOneTimeEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiOneTimeEvent.java @@ -3,7 +3,7 @@ package com.seibel.distanthorizons.api.methods.events.interfaces; /** * If a {@link IDhApiEvent} implements this interface then the event will only ever be fired once.
* An example of this would be initial setup methods, DH won't run its initial setup more than once.

- * + * * If a handler is bound to a one time event after the event has been fired, the handler will immediately fire. */ public interface IDhApiOneTimeEvent extends IDhApiEvent diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhServerMessageReceived.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhServerMessageReceived.java index 6919c392a..88f49f425 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhServerMessageReceived.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhServerMessageReceived.java @@ -9,6 +9,7 @@ public interface IDhServerMessageReceived extends IDhApiEvent { /** * Triggered when a plugin message is received from the server. + * * @param channel The name of the channel this was received on. * @param message The message sent from the server. */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/package-info.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/package-info.java index cb8e0173d..788f78df1 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/package-info.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/package-info.java @@ -1,4 +1,5 @@ /** * Holds objects and methods for listening to events fired by Distant Horizons'. */ + package com.seibel.distanthorizons.api.methods.events; diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/override/DhApiWorldGeneratorOverrideRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/override/DhApiWorldGeneratorOverrideRegister.java index 87f34bc61..5ad90f69b 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/override/DhApiWorldGeneratorOverrideRegister.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/override/DhApiWorldGeneratorOverrideRegister.java @@ -16,7 +16,7 @@ public class DhApiWorldGeneratorOverrideRegister implements IDhApiWorldGenerator { public static DhApiWorldGeneratorOverrideRegister INSTANCE = new DhApiWorldGeneratorOverrideRegister(); - private DhApiWorldGeneratorOverrideRegister() { } + private DhApiWorldGeneratorOverrideRegister() { } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/override/package-info.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/override/package-info.java index 0c95e66a6..34e6e6c67 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/override/package-info.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/override/package-info.java @@ -1,4 +1,5 @@ /** * The override api package holds objects and methods for overriding Distant Horizons' backend systems, so they can be replaced or improved. */ + package com.seibel.distanthorizons.api.methods.override; diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/DhApiResult.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/DhApiResult.java index b86dc9c90..39afd289c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/DhApiResult.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/DhApiResult.java @@ -2,9 +2,8 @@ package com.seibel.distanthorizons.api.objects; /** * Allows for more descriptive non-critical failure states. - * - * @param The payload type this result contains, can be Void if the result is just used to notify success/failure. - * + * + * @param The payload type this result contains, can be Void if the result is just used to notify success/failure. * @author James Seibel * @version 2022-11-24 */ @@ -19,9 +18,9 @@ public class DhApiResult */ public final String message; - /** + /** * Whatever object the API Method generated/returned.
- * Will be null/Void if this result is just used to notify success/failure. + * Will be null/Void if this result is just used to notify success/failure. */ public final T payload; @@ -33,7 +32,7 @@ public class DhApiResult { this.success = success; // don't allow null messages, in the case of a null message return the empty string to prevent potential null pointers - this.message = (message == null) ? "" : message; + this.message = (message == null) ? "" : message; this.payload = payload; } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java index 3974d00fc..5c15b92fb 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java @@ -14,7 +14,6 @@ import com.seibel.distanthorizons.coreapi.util.converters.DefaultConverter; * * @param The datatype you, an API dev will use. * @param The datatype Distant Horizons uses in the background; implementing developers can ignore this. - * * @author James Seibel * @version 2022-6-30 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiRaycastResult.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiRaycastResult.java index 43b21a35c..65a58116a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiRaycastResult.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiRaycastResult.java @@ -6,15 +6,15 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3i; /** * Holds a single datapoint of terrain data * and the block position from the raycast. - * + * * @author James Seibel * @version 2022-11-19 */ public class DhApiRaycastResult { - /** + /** * LOD position of this raycast.

- * + * * Note: * This will NOT be the exact block position if the LOD the ray * hits is more than one block tall. In that case this will diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java index 69b72e1ca..0f5f40e33 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java @@ -5,7 +5,7 @@ import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; /** * Holds a single datapoint of terrain data. - * + * * @author James Seibel * @version 2022-11-13 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3i.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3i.java index f8f001e03..79a3afdb6 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3i.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3i.java @@ -20,9 +20,9 @@ package com.seibel.distanthorizons.api.objects.math; /** - * Often used to store block positions or any other + * Often used to store block positions or any other * position in 3D space. - * + * * @author James Seibel * @version 2022-11-19 */ diff --git a/api/src/main/java/com/seibel/distanthorizons/api/package-info.java b/api/src/main/java/com/seibel/distanthorizons/api/package-info.java index a9bc1098d..180dff03d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/package-info.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/package-info.java @@ -1,7 +1,8 @@ /** * Start Here
* {@link com.seibel.distanthorizons.api.DhApi} has almost every method you would want.

- * + * * This package contains every method and object that is safe to use within the API. */ + package com.seibel.distanthorizons.api; diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java index cca942e6d..36325d085 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java @@ -46,7 +46,7 @@ public class ApiEventInjector extends DependencyInjector implements private ApiEventInjector() { super(IDhApiEvent.class, true); } - + @SuppressWarnings("unchecked") @Override public void bind(Class abstractEvent, IDhApiEvent eventImplementation) throws IllegalStateException, IllegalArgumentException @@ -76,7 +76,7 @@ public class ApiEventInjector extends DependencyInjector implements { // make sure the given dependency implements the necessary interfaces boolean implementsInterface = this.checkIfClassImplements(eventClassToRemove, abstractEvent) || - this.checkIfClassExtends(eventClassToRemove, abstractEvent); + this.checkIfClassExtends(eventClassToRemove, abstractEvent); boolean implementsBindable = this.checkIfClassImplements(eventClassToRemove, this.bindableInterface); // display any errors @@ -95,7 +95,7 @@ public class ApiEventInjector extends DependencyInjector implements { ArrayList dependencyList = this.dependencies.get(abstractEvent); int indexToRemove = -1; - for(int i = 0; i < dependencyList.size(); i++) + for (int i = 0; i < dependencyList.size(); i++) { IBindable dependency = dependencyList.get(i); if (dependency.getClass().equals(eventClassToRemove)) @@ -120,7 +120,7 @@ public class ApiEventInjector extends DependencyInjector implements { // if this is a one time event, record that it was called if (IDhApiOneTimeEvent.class.isAssignableFrom(abstractEventClass) && - !this.firedOneTimeEventParamsByEventInterface.containsKey(abstractEventClass)) + !this.firedOneTimeEventParamsByEventInterface.containsKey(abstractEventClass)) { this.firedOneTimeEventParamsByEventInterface.put(abstractEventClass, eventInput); } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/DependencyInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/DependencyInjector.java index ac3bf2beb..a8686111a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/DependencyInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/DependencyInjector.java @@ -70,7 +70,7 @@ public class DependencyInjector implements IDepe // make sure the given dependency implements the necessary interfaces boolean implementsInterface = this.checkIfClassImplements(dependencyImplementation.getClass(), dependencyInterface) || - this.checkIfClassExtends(dependencyImplementation.getClass(), dependencyInterface); + this.checkIfClassExtends(dependencyImplementation.getClass(), dependencyInterface); boolean implementsBindable = this.checkIfClassImplements(dependencyImplementation.getClass(), this.bindableInterface); // display any errors diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java index 80ac93158..1947e75e1 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverrideInjector.java @@ -35,7 +35,7 @@ import java.util.HashMap; public class OverrideInjector implements IOverrideInjector { public static final OverrideInjector INSTANCE = new OverrideInjector(); - + private final HashMap, OverridePriorityListContainer> overrideContainerByInterface = new HashMap<>(); @@ -61,7 +61,7 @@ public class OverrideInjector implements IOverrideInjector @Override - public void bind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation) throws IllegalStateException, IllegalArgumentException + public void bind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation) throws IllegalStateException, IllegalArgumentException { // make sure a override container exists OverridePriorityListContainer overrideContainer = this.overrideContainerByInterface.get(dependencyInterface); diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java index 1f2714a99..cc31021df 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/OverridePriorityListContainer.java @@ -7,8 +7,8 @@ import java.util.ArrayList; /** * Contains a list of overrides and their priorities. - * - * @author James Seibel + * + * @author James Seibel * @version 2022-9-5 */ public class OverridePriorityListContainer implements IBindable @@ -98,7 +98,7 @@ public class OverridePriorityListContainer implements IBindable // utils // /** sort the list so the highest priority item is first in the list */ - private void sortList() { this.overridePairList.sort((x,y) -> Integer.compare(y.priority, x.priority)); } + private void sortList() { this.overridePairList.sort((x, y) -> Integer.compare(y.priority, x.priority)); } @@ -112,5 +112,7 @@ public class OverridePriorityListContainer implements IBindable this.override = newOverride; this.priority = newPriority; } + } + } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/WorldGeneratorInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/WorldGeneratorInjector.java index 6fdec4d94..da0751996 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/WorldGeneratorInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/WorldGeneratorInjector.java @@ -29,6 +29,7 @@ import java.util.HashMap; /** * This class takes care of dependency injection for world generators.
* This is done so other mods can override our world generator(s) to improve or replace them. + * * @author James Seibel * @version 2022-12-10 */ @@ -65,10 +66,9 @@ public class WorldGeneratorInjector /** * Binds a world generator to the given level.
* See {@link DependencyInjector#bind(Class, IBindable) bind(Class, IBindable)} for full documentation. - * + * * @throws NullPointerException if any parameter is null * @throws IllegalArgumentException if a non-Distant Horizons world generator with the priority CORE is passed in - * * @see DependencyInjector#bind(Class, IBindable) */ public void bind(IDhApiLevelWrapper levelForWorldGenerator, IDhApiWorldGenerator worldGeneratorImplementation) throws NullPointerException, IllegalArgumentException @@ -98,8 +98,9 @@ public class WorldGeneratorInjector /** * Returns the bound world generator with the highest priority.
* Returns null if no world generators have been bound for this specific level.

- * + * * See {@link OverrideInjector#get(Class) get(Class)} for full documentation. + * * @see OverrideInjector#get(Class) */ public IDhApiWorldGenerator get(IDhApiLevelWrapper levelForWorldGenerator) throws ClassCastException diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java index 74a336a10..ff0eb7d14 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java @@ -19,8 +19,8 @@ package com.seibel.distanthorizons.coreapi; -/** - * This file is similar to mcmod.info +/** + * This file is similar to mcmod.info * and contains most meta-information related to Distant Horizons. */ public final class ModInfo @@ -37,7 +37,7 @@ public final class ModInfo public static final String VERSION = "2.0.0-a-dev"; /** Returns true if the current build is an unstable developer build, false otherwise. */ public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev"); - + /** This version should only be updated when breaking changes are introduced to the DH API */ public static final int API_MAJOR_VERSION = 1; /** This version should be updated whenever new methods are added to the DH API */ @@ -45,7 +45,7 @@ public final class ModInfo /** This version should be updated whenever non-breaking fixes are added to the DH API */ public static final int API_PATH_VERSION = 0; - public static final String NETWORKING_RESOURCE_NAMESPACE = "distant_horizons"; + public static final String NETWORKING_RESOURCE_NAMESPACE = "distant_horizons"; public static final String MULTIVERSE_PLUGIN_NAMESPACE = "world_control"; diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java index a74e2ac4a..fb137f3bc 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java @@ -10,50 +10,50 @@ package com.seibel.distanthorizons.coreapi.interfaces.config; public interface IConfigEntry { - /** Gets the default value of the option */ - T getDefaultValue(); + /** Gets the default value of the option */ + T getDefaultValue(); - void setApiValue(T newApiValue); - T getApiValue(); + void setApiValue(T newApiValue); + T getApiValue(); /** Returns true if this config can be set via the API. */ boolean getAllowApiOverride(); - void set(T newValue); - T get(); - T getTrueValue(); + void set(T newValue); + T get(); + T getTrueValue(); - /** Sets the value without saving */ - void setWithoutSaving(T newValue); + /** Sets the value without saving */ + void setWithoutSaving(T newValue); - /** Gets the min value */ - T getMin(); - /** Sets the min value */ - void setMin(T newMin); - /** Gets the max value */ - T getMax(); - /** Sets the max value */ - void setMax(T newMax); - /** Sets the min and max in 1 setter */ - void setMinMax(T newMin, T newMax); + /** Gets the min value */ + T getMin(); + /** Sets the min value */ + void setMin(T newMin); + /** Gets the max value */ + T getMax(); + /** Sets the max value */ + void setMax(T newMax); + /** Sets the min and max in 1 setter */ + void setMinMax(T newMin, T newMax); - /** Gets the comment */ - String getComment(); - /** Sets the comment */ - void setComment(String newComment); + /** Gets the comment */ + String getComment(); + /** Sets the comment */ + void setComment(String newComment); - /** - * Checks if the option is valid - * - * 0 == valid - * 1 == number too high - * -1 == number too low - */ - byte isValid(); - /** Checks if a value is valid */ - byte isValid(T value); + /** + * Checks if the option is valid + * + * 0 == valid + * 1 == number too high + * -1 == number too low + */ + byte isValid(); + /** Checks if a value is valid */ + byte isValid(T value); - /** Is the value of this equal to another */ - boolean equals(IConfigEntry obj); + /** Is the value of this equal to another */ + boolean equals(IConfigEntry obj); } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IBindable.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IBindable.java index b383513df..80b70c14c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IBindable.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IBindable.java @@ -16,12 +16,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection; /** * Necessary for all singletons that can be dependency injected. - * + * * @author James Seibel * @version 2022-7-16 */ @@ -29,12 +29,12 @@ public interface IBindable { /** * Finish initializing this object.

- * + * * Generally this should just be used for getting other objects through - * dependency injection and is specifically designed to allow + * dependency injection and is specifically designed to allow * for circular references.

- * - * If no circular dependencies are required this method + * + * If no circular dependencies are required this method * doesn't have to be implemented. */ default void finishDelayedSetup() { } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java index ee543fe8e..266c43e66 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java @@ -30,19 +30,18 @@ public interface IDependencyInjector * * @see #get(Class, boolean) */ - @SuppressWarnings("unchecked") - T get(Class interfaceClass) throws ClassCastException; + @SuppressWarnings("unchecked") T get(Class interfaceClass) throws ClassCastException; /** * Returns all dependencies of type T that have been bound.
* Returns an empty list if no dependencies have been bound. * * @param class of the dependency - * (inferred from the objectClass parameter) + * (inferred from the objectClass parameter) * @param interfaceClass Interface of the dependency * @return the dependency of type T * @throws ClassCastException If the dependency isn't able to be cast to type T. - * (this shouldn't normally happen, unless the bound object changed somehow) + * (this shouldn't normally happen, unless the bound object changed somehow) */ ArrayList getAll(Class interfaceClass) throws ClassCastException; @@ -53,15 +52,14 @@ public interface IDependencyInjector * If the handler allows duplicate bindings, this will return the first bound dependency. * * @param class of the dependency - * (inferred from the interfaceClass parameter) + * (inferred from the interfaceClass parameter) * @param interfaceClass Interface of the dependency * @param allowIncompleteDependencies If true this method will also return dependencies that haven't completed their delayed setup. * @return the dependency of type T * @throws ClassCastException If the dependency isn't able to be cast to type T. - * (this shouldn't normally happen, unless the bound object changed somehow) + * (this shouldn't normally happen, unless the bound object changed somehow) */ - @SuppressWarnings("unchecked") - T get(Class interfaceClass, boolean allowIncompleteDependencies) throws ClassCastException; + @SuppressWarnings("unchecked") T get(Class interfaceClass, boolean allowIncompleteDependencies) throws ClassCastException; @@ -72,4 +70,5 @@ public interface IDependencyInjector /** Runs delayed setup for any dependencies that require it. */ void runDelayedSetup(); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java index 3d1581edd..15f9dcbc4 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java @@ -27,7 +27,7 @@ public interface IOverrideInjector * @throws IllegalStateException if another override with the given priority already has been bound. * @see IDependencyInjector#bind(Class, IBindable) */ - void bind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation) throws IllegalStateException, IllegalArgumentException; + void bind(Class dependencyInterface, IDhApiOverrideable dependencyImplementation) throws IllegalStateException, IllegalArgumentException; /** * Returns the bound dependency with the highest priority.
diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/package-info.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/package-info.java index 4f122f9b5..6b5dea26d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/package-info.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/package-info.java @@ -1,11 +1,12 @@ /** * Only For Internal Use
* Everything in here for DH internally use.

- * + * * You can use objects and methods from here if you want, (I'm a javaDoc, not the cops) * but using anything from this package is unsupported and may change at any time.

- * + * * When in doubt, if a method starts with "DhApi" it is safe to use, and we will * do our best to avoid breaking changes. */ + package com.seibel.distanthorizons.coreapi; diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java index 410dfb013..cd900a2d7 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java @@ -3,20 +3,20 @@ package com.seibel.distanthorizons.coreapi.util; /** * A list of helper methods to make code easier to read.
* Specifically written because bit shifts short circuit James' brain. - * + * * @author James Seibel * @version 2022-11-6 */ public class BitShiftUtil { - /** + /** * Equivalent to:
* {@literal 1 << value0, }
* 2^value,
* Math.pow(2, value)

- * + * * Note: Math.pow() isn't identical for large values where bits would be lost in the shift, however for medium to small values they function the same.

- * + * * Can also be used to replace bit shifts in the format:
* {@literal multiplier << value; }
* multiplier * powerOfTwo(value); @@ -30,7 +30,7 @@ public class BitShiftUtil * Equivalent to:
* value >> 1,
* value / 2

- * + * * Note: value / 2 isn't identical for negative values */ public static int half(int value) { return value >> 1; } @@ -42,7 +42,7 @@ public class BitShiftUtil * Equivalent to:
* value >> power,
* value / 2^power

- * + * * Note: value / 2^power isn't identical for negative values */ public static int divideByPowerOfTwo(int value, int power) { return value >> power; } @@ -55,7 +55,7 @@ public class BitShiftUtil * {@literal value << 1, }
* value^2,
* Math.pow(value, 2)

- * + * * Note: Math.pow() isn't identical for large values where bits would be lost in the shift, however for medium to small values they function the same. */ public static int square(int value) { return value << 1; } @@ -68,7 +68,7 @@ public class BitShiftUtil * {@literal value << power, }
* value^power,
* Math.pow(value, power)

- * + * * Note: Math.pow() isn't identical for large values where bits would be lost in the shift, however for medium to small values they function the same. */ public static int pow(int value, int power) { return value << power; } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/MathUtil.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/MathUtil.java index 1dc713305..a2c1ba9c5 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/MathUtil.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/MathUtil.java @@ -49,7 +49,7 @@ public class MathUtil public static int log2(int numb) { // properties of logs allow us to use the base Log_e() method - return (int)(Math.log(numb) / Math.log(2)); + return (int) (Math.log(numb) / Math.log(2)); } } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/StringUtil.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/StringUtil.java index 9a3a8f195..76ab1beff 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/StringUtil.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/StringUtil.java @@ -36,7 +36,9 @@ public class StringUtil { int pos = str.indexOf(substr); while (--n > 0 && pos != -1) + { pos = str.indexOf(substr, pos + 1); + } return pos; } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/converters/DefaultConverter.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/converters/DefaultConverter.java index 2f66a13a5..4179e068e 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/converters/DefaultConverter.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/converters/DefaultConverter.java @@ -23,4 +23,5 @@ public class DefaultConverter implements IConverter { return coreObject; } + } \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java index 1ba8ff361..6523ddf62 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Mat4f.java @@ -24,7 +24,7 @@ import java.nio.FloatBuffer; /** * An (almost) exact copy of Minecraft's 1.16.5 * implementation of a 4x4 float matrix. - * + * * @author James Seibel * @version 11-11-2021 */ @@ -394,8 +394,8 @@ public class Mat4f } */ - /** - * TODO: what kind of translation is this? + /** + * TODO: what kind of translation is this? * and how is this different from "multiplyTranslationMatrix"? * Answer: This is faster and direct (but only if this is pure translation matrix without rotate) */ @@ -409,7 +409,7 @@ public class Mat4f /** originally "translate" from Minecraft's MatrixStack */ public void multiplyTranslationMatrix(double x, double y, double z) { - multiply(createTranslateMatrix((float)x, (float)y, (float)z)); + multiply(createTranslateMatrix((float) x, (float) y, (float) z)); } public Mat4f copy() @@ -450,30 +450,31 @@ public class Mat4f /** Returns the values of this matrix in row major order (AKA rows then columns) */ public float[] getValuesAsArray() { - return new float[] { - this.m00, - this.m01, - this.m02, - this.m03, - - this.m10, - this.m11, - this.m12, - this.m13, - - this.m20, - this.m21, - this.m22, - this.m23, - - this.m30, - this.m31, - this.m32, - this.m33, + return new float[]{ + this.m00, + this.m01, + this.m02, + this.m03, + + this.m10, + this.m11, + this.m12, + this.m13, + + this.m20, + this.m21, + this.m22, + this.m23, + + this.m30, + this.m31, + this.m32, + this.m33, }; } - - public Vec3f asNonNormalizedLookForwardVector() { + + public Vec3f asNonNormalizedLookForwardVector() + { return new Vec3f(this.m02, this.m12, this.m22); } @@ -505,7 +506,7 @@ public class Mat4f { this(buffer.array()); } - + public void set(Mat4f mat) { this.m00 = mat.m00; @@ -563,7 +564,7 @@ public class Mat4f this.m13 = y; this.m23 = z; } - + /** * Changes the values that store the clipping planes. * Formula for calculating matrix values is the same that OpenGL uses when making matrices. @@ -571,7 +572,7 @@ public class Mat4f * @param nearClip New near clipping plane value. * @param farClip New far clipping plane value. */ - public void setClipPlanes(float nearClip,float farClip) + public void setClipPlanes(float nearClip, float farClip) { //convert to matrix values, formula copied from a textbook / openGL specification. float matNearClip = -((farClip + nearClip) / (farClip - nearClip)); diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java index 28dd5d8de..ab83283d1 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java @@ -22,10 +22,10 @@ package com.seibel.distanthorizons.coreapi.util.math; import com.seibel.distanthorizons.coreapi.util.MathUtil; /** - * This is closer to MC's implementation of a + * This is closer to MC's implementation of a * 3 element float vector than a 3 element double * vector. Hopefully that shouldn't cause any issues. - * + * * @author James Seibel * @version 11-18-2021 */ @@ -254,4 +254,5 @@ public class Vec3d this.y = values[1]; this.z = values[2]; } + } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java index 1aa168579..1ec4988e5 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil; /** * A (almost) exact copy of Minecraft's 1.16.5 * implementation of a 3 element float vector. - * + * * @author James Seibel * @version 11-11-2021 */ @@ -259,4 +259,5 @@ public class Vec3f this.y = values[1]; this.z = values[2]; } + } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java index 6df27340b..4aa624b0e 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java @@ -25,7 +25,7 @@ import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; /** * A (almost) exact copy of Minecraft's 1.16.5 * implementation of a 3 element integer vector. - * + * * @author James Seibel * @version 2022-11-19 */ @@ -134,8 +134,8 @@ public class Vec3i extends DhApiVec3i // extends the API object so it can be ret public Vec3i cross(Vec3i otherVec) { return new Vec3i( - (this.y * otherVec.z) - (this.z * otherVec.y), - (this.z * otherVec.x) - (this.x * otherVec.z), + (this.y * otherVec.z) - (this.z * otherVec.y), + (this.z * otherVec.x) - (this.x * otherVec.z), (this.x * otherVec.y) - (this.y * otherVec.x)); } diff --git a/api/src/test/java/testItems/events/abstractObjects/AbstractDhApiCancelableOneTimeTestEvent.java b/api/src/test/java/testItems/events/abstractObjects/AbstractDhApiCancelableOneTimeTestEvent.java index 1b69f07af..09c7d0d25 100644 --- a/api/src/test/java/testItems/events/abstractObjects/AbstractDhApiCancelableOneTimeTestEvent.java +++ b/api/src/test/java/testItems/events/abstractObjects/AbstractDhApiCancelableOneTimeTestEvent.java @@ -25,7 +25,7 @@ public abstract class AbstractDhApiCancelableOneTimeTestEvent implements IDhApiC //=========================// @Override - public final void fireEvent(DhApiCancelableEventParam input) + public final void fireEvent(DhApiCancelableEventParam input) { this.onTestEvent(input); if (input.value) diff --git a/api/src/test/java/tests/EventInjectorTest.java b/api/src/test/java/tests/EventInjectorTest.java index 70ad89118..67fb480cb 100644 --- a/api/src/test/java/tests/EventInjectorTest.java +++ b/api/src/test/java/tests/EventInjectorTest.java @@ -133,7 +133,7 @@ public class EventInjectorTest oneTimeEventList = TEST_EVENT_HANDLER.getAll(AbstractDhApiCancelableOneTimeTestEvent.class); for (int i = 0; i < oneTimeEventList.size(); i++) { - Assert.assertEquals("Event not fired for object ["+i+"].", true, oneTimeEventList.get(i).getTestValue()); + Assert.assertEquals("Event not fired for object [" + i + "].", true, oneTimeEventList.get(i).getTestValue()); } diff --git a/api/src/test/java/tests/ExampleTest.java b/api/src/test/java/tests/ExampleTest.java index de45feab0..150f77422 100644 --- a/api/src/test/java/tests/ExampleTest.java +++ b/api/src/test/java/tests/ExampleTest.java @@ -24,7 +24,7 @@ import org.junit.Test; /** * This is just a quick demo to confirm the testing system is set up correctly. - * + * * @author James Seibel * @version 2022-9-5 */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/IReflectionHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/IReflectionHandler.java index f20788af3..9755811e4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/IReflectionHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/IReflectionHandler.java @@ -23,7 +23,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab /** * A singleton used to get variables from methods - * where they are private or potentially absent. + * where they are private or potentially absent. * Specifically the fog setting used by Optifine or the * presence/absence of other mods. *

@@ -32,7 +32,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab * passing in interfaces), and it may be needed in the future if * we find that reflection handlers need to be different for * different MC versions. - * + * * @author James Seibel * @version 2022-11-24 */ @@ -40,7 +40,7 @@ public interface IReflectionHandler extends IBindable { /** @return if Sodium (or a sodium like) mod is present. */ boolean sodiumPresent(); - + boolean optifinePresent(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java index cb4e4512d..f26291865 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java @@ -17,9 +17,9 @@ import org.apache.logging.log4j.Logger; /** Handles first time Core setup. */ public class Initializer { - private static final Logger LOGGER = LogManager.getLogger(ModInfo.NAME+"-"+Initializer.class.getSimpleName()); + private static final Logger LOGGER = LogManager.getLogger(ModInfo.NAME + "-" + Initializer.class.getSimpleName()); - public static void init() + public static void init() { // confirm that all referenced libraries are available to use try @@ -33,15 +33,15 @@ public class Initializer } catch (NoClassDefFoundError e) { - LOGGER.fatal("Critical programmer error: One or more libraries aren't present. Error: ["+e.getMessage()+"]."); + LOGGER.fatal("Critical programmer error: One or more libraries aren't present. Error: [" + e.getMessage() + "]."); throw e; } - CompleteFullDataSourceLoader unused2 = new CompleteFullDataSourceLoader(); // Auto register into the loader system - HighDetailIncompleteFullDataSourceLoader unused3 = new HighDetailIncompleteFullDataSourceLoader(); // Auto register - LowDetailIncompleteFullDataSourceLoader unused4 = new LowDetailIncompleteFullDataSourceLoader(); // Auto register + CompleteFullDataSourceLoader unused2 = new CompleteFullDataSourceLoader(); // Auto register into the loader system + HighDetailIncompleteFullDataSourceLoader unused3 = new HighDetailIncompleteFullDataSourceLoader(); // Auto register + LowDetailIncompleteFullDataSourceLoader unused4 = new LowDetailIncompleteFullDataSourceLoader(); // Auto register // link Core's config to the API DhApi.Delayed.configs = DhApiConfig.INSTANCE; @@ -49,5 +49,6 @@ public class Initializer DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE; DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE; - } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/ReflectionHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/ReflectionHandler.java index e8e385b28..2690144b7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/ReflectionHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/ReflectionHandler.java @@ -26,12 +26,12 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOpt import org.apache.logging.log4j.Logger; /** - * A singleton used to determine if a class is present or - * access variables from methods where they are private + * A singleton used to determine if a class is present or + * access variables from methods where they are private * or potentially absent.

- * + * * For example: presence/absence of Optifine. - * + * * @author James Seibel * @version 2022-11-24 */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java index 3713ac7e1..46c9bc022 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java @@ -10,21 +10,21 @@ public class DhApiConfig implements IDhApiConfig { public static final DhApiConfig INSTANCE = new DhApiConfig(); - private DhApiConfig() { } + private DhApiConfig() { } @Override public IDhApiGraphicsConfig graphics() { return DhApiGraphicsConfig.INSTANCE; } - @Override + @Override public IDhApiWorldGenerationConfig worldGenerator() { return DhApiWorldGenerationConfig.INSTANCE; } @Override public IDhApiMultiplayerConfig multiplayer() { return DhApiMultiplayerConfig.INSTANCE; } @Override public IDhApiMultiThreadingConfig multiThreading() { return DhApiMultiThreadingConfig.INSTANCE; } - @Override + @Override public IDhApiGpuBuffersConfig gpuBuffers() { return DhApiGpuBuffersConfig.INSTANCE; } - @Override + @Override public IDhApiDebuggingConfig debugging() { return DhApiDebuggingConfig.INSTANCE; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java index 867d6484c..c07bb82cf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java @@ -106,7 +106,7 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig //===========================// // advanced graphic settings // //===========================// - + // @Override // public IDhApiConfigValue getDisableDirectionalCulling() // { return new DhApiConfigValue(AdvancedGraphics.disableDirectionalCulling); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/common/DhApiWorldGenerationConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/common/DhApiWorldGenerationConfig.java index b69711a46..ef0f93dd3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/common/DhApiWorldGenerationConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/common/DhApiWorldGenerationConfig.java @@ -36,7 +36,7 @@ import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGenerat */ public class DhApiWorldGenerationConfig implements IDhApiWorldGenerationConfig { - public static DhApiWorldGenerationConfig INSTANCE = new DhApiWorldGenerationConfig(); + public static DhApiWorldGenerationConfig INSTANCE = new DhApiWorldGenerationConfig(); private DhApiWorldGenerationConfig() { } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index bc27d82bd..1968658ee 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -55,7 +55,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo - private DhApiTerrainDataRepo() + private DhApiTerrainDataRepo() { } @@ -67,12 +67,12 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo //================// @Override - public DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) + public DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) { return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY); } @Override - public DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) + public DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) { return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null); } @@ -112,14 +112,14 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo } } - /** + /** * Returns all the block columns represented by the given {@link DhLodPos}.
* IE, A position with the detail level:
* 0 (block): will return a 1x1 matrix of data. (don't do this, we have a specific method for that.)
* 1 (2 blocks): will return a 2x2 matrix of data.
* 4 (chunk): will return a 16x16 matrix of data.

- * - * will stop and return the in progress data if any errors are encountered. + * + * will stop and return the in progress data if any errors are encountered. */ private static DhApiResult getTerrainDataOverAreaForPositionDetailLevel(IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos) { @@ -151,10 +151,10 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo return dataColumnsReturned != 0 ? DhApiResult.createSuccess("[" + dataColumnsReturned + "] columns returned.", returnArray) : DhApiResult.createSuccess("No data found.", returnArray); } - /** + /** * If nullableBlockYPos is null: returns every datapoint in the column defined by the DhLodPos.
* If nullableBlockYPos is NOT null: returns a single datapoint in the column defined by the DhLodPos which contains the block Y position.

- * + * * If the ApiResult is successful there will be an array of data.
* The returned array will be empty if no data could be retrieved. */ @@ -170,7 +170,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo { // custom level wrappers aren't supported, // the API user must get a level wrapper from our code somewhere - return DhApiResult.createFail("Unsupported ["+IDhApiLevelWrapper.class.getSimpleName()+"] implementation, only the core class ["+ IDhLevel.class.getSimpleName()+"] is a valid parameter."); + return DhApiResult.createFail("Unsupported [" + IDhApiLevelWrapper.class.getSimpleName() + "] implementation, only the core class [" + IDhLevel.class.getSimpleName() + "] is a valid parameter."); } ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper; @@ -256,7 +256,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo catch (InterruptedException | ExecutionException e) { // shouldn't normally happen, but just in case - LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: ["+e.getMessage()+"]", e); + LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: [" + e.getMessage() + "]", e); return DhApiResult.createFail("Unexpected exception: [" + e.getMessage() + "]."); } } @@ -270,7 +270,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo int height = FullDataPointUtil.getHeight(dataPoint); int topY = bottomY + height; - return new DhApiTerrainDataPoint(detailLevel, + return new DhApiTerrainDataPoint(detailLevel, FullDataPointUtil.getLight(dataPoint), topY, bottomY, blockState, biomeWrapper); } @@ -282,7 +282,8 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo //====================// @Override - public DhApiResult raycast(IDhApiLevelWrapper levelWrapper, + public DhApiResult raycast( + IDhApiLevelWrapper levelWrapper, double rayOriginX, double rayOriginY, double rayOriginZ, float rayDirectionX, float rayDirectionY, float rayDirectionZ, int maxRayBlockLength) @@ -340,7 +341,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo { // does this LOD contain the given Y position? Vec3i dataPointPos = new Vec3i(columnPos.x, dataPoint.bottomYBlockPos, columnPos.z); - if (exactPos.y >= dataPoint.bottomYBlockPos && exactPos.y <= dataPoint.topYBlockPos) + if (exactPos.y >= dataPoint.bottomYBlockPos && exactPos.y <= dataPoint.topYBlockPos) { if (closetFoundDataPoint == null) { @@ -423,7 +424,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo { if (!(levelWrapper instanceof ILevelWrapper)) { - return DhApiResult.createFail("Level wrapper needs to be an instance of ["+IDhApiLevelWrapper.class.getSimpleName()+"]."); + return DhApiResult.createFail("Level wrapper needs to be an instance of [" + IDhApiLevelWrapper.class.getSimpleName() + "]."); } AbstractDhWorld dhWorld = SharedApi.getAbstractDhWorld(); if (dhWorld == null) @@ -452,8 +453,8 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo // debug methods // //===============// - /** - * This method is here for debugging the repo and isn't intended for normal use. + /** + * This method is here for debugging the repo and isn't intended for normal use. * The method need to be async because pausing the main thread with a breakpoint and hot swapping will crash the program */ public static void asyncDebugMethod(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) @@ -476,7 +477,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo if (rayCast.payload != null && !rayCast.payload.pos.equals(currentDebugVec3i)) { currentDebugVec3i = rayCast.payload.pos; - + // get a string for the block String blockString = "[NULL BLOCK]"; // shouldn't normally happen unless there is an issue with getting the terrain at the given position if (rayCast.payload.dataPoint.blockStateWrapper != null) @@ -487,10 +488,10 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo } else { - blockString = "[AIR]"; + blockString = "[AIR]"; } } - + LOGGER.info("raycast: " + currentDebugVec3i + "\t block: " + blockString); } else if (rayCast.payload == null && currentDebugVec3i != null) @@ -504,7 +505,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo } catch (Exception e) { - LOGGER.error("Test method Error: ["+e.getMessage()+"]", e); + LOGGER.error("Test method Error: [" + e.getMessage() + "]", e); } finally { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index a081f4c19..6b8d683eb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -106,7 +106,7 @@ public class ClientApi // world events // //==============// - /** + /** * May be fired slightly before or after the associated * {@link ClientApi#clientLevelLoadEvent(IClientLevelWrapper)} event * depending on how the host mod loader functions. @@ -123,7 +123,7 @@ public class ClientApi SharedApi.setDhWorld(new DhClientWorld()); - LOGGER.info("Loading ["+this.waitingClientLevels.size()+"] waiting client level wrappers."); + LOGGER.info("Loading [" + this.waitingClientLevels.size() + "] waiting client level wrappers."); for (IClientLevelWrapper level : this.waitingClientLevels) { this.clientLevelLoadEvent(level); @@ -132,7 +132,7 @@ public class ClientApi this.waitingClientLevels.clear(); } } - + public void onClientOnlyDisconnected() { if (MC.clientConnectedToDedicatedServer()) @@ -141,7 +141,7 @@ public class ClientApi if (world != null) { LOGGER.info("Client on ClientOnly mode disconnecting."); - + world.close(); SharedApi.setDhWorld(null); } @@ -166,7 +166,7 @@ public class ClientApi public void clientLevelUnloadEvent(IClientLevelWrapper level) { - LOGGER.info("Unloading client level ["+level+"]."); + LOGGER.info("Unloading client level [" + level + "]."); AbstractDhWorld world = SharedApi.getAbstractDhWorld(); if (world != null) @@ -191,7 +191,7 @@ public class ClientApi } - LOGGER.info("Loading "+(isServerCommunication ? "Multiverse" : "")+" client level [" + level + "]."); + LOGGER.info("Loading " + (isServerCommunication ? "Multiverse" : "") + " client level [" + level + "]."); AbstractDhWorld world = SharedApi.getAbstractDhWorld(); if (world != null) @@ -220,7 +220,7 @@ public class ClientApi keysToRemove.add(levelChunkPair); } } - LOGGER.info("Loaded ["+keysToRemove.size()+"] waiting chunk wrappers."); + LOGGER.info("Loaded [" + keysToRemove.size() + "] waiting chunk wrappers."); for (Pair keyToRemove : keysToRemove) { @@ -263,8 +263,8 @@ public class ClientApi { for (int zOffset = -1; zOffset <= 1; zOffset++) { - DhChunkPos neighbourPos = new DhChunkPos(chunk.getChunkPos().x+xOffset, chunk.getChunkPos().z+zOffset); - IChunkWrapper neighbourChunk = dhLevel.getLevelWrapper().tryGetChunk(neighbourPos); + DhChunkPos neighbourPos = new DhChunkPos(chunk.getChunkPos().x + xOffset, chunk.getChunkPos().z + zOffset); + IChunkWrapper neighbourChunk = dhLevel.getLevelWrapper().tryGetChunk(neighbourPos); if (neighbourChunk != null) { dhLevel.updateChunkAsync(neighbourChunk); @@ -282,20 +282,20 @@ public class ClientApi public void rendererShutdownEvent() { LOGGER.info("Renderer shutting down."); - + IProfilerWrapper profiler = MC.getProfiler(); profiler.push("DH-RendererShutdown"); - + profiler.pop(); } public void rendererStartupEvent() { LOGGER.info("Renderer starting up."); - + IProfilerWrapper profiler = MC.getProfiler(); profiler.push("DH-RendererStartup"); - + // make sure the GLProxy is created before the LodBufferBuilder needs it GLProxy.getInstance(); profiler.pop(); @@ -305,7 +305,7 @@ public class ClientApi { IProfilerWrapper profiler = MC.getProfiler(); profiler.push("DH-ClientTick"); - + boolean doFlush = System.nanoTime() - this.lastFlushNanoTime >= SPAM_LOGGER_FLUSH_NS; if (doFlush) { @@ -314,7 +314,7 @@ public class ClientApi } ConfigBasedLogger.updateAll(); ConfigBasedSpamLogger.updateAll(doFlush); - + IDhClientWorld clientWorld = SharedApi.getIDhClientWorld(); if (clientWorld != null) { @@ -328,7 +328,7 @@ public class ClientApi //============// // networking // //============// - + // /** @param byteBuf is Netty's {@link ByteBuffer} wrapper. */ // public void serverMessageReceived(ByteBuf byteBuf) // { @@ -463,8 +463,8 @@ public class ClientApi MC.sendChatMessage("Here be dragons!"); this.configOverrideReminderPrinted = true; } - - + + IProfilerWrapper profiler = MC.getProfiler(); profiler.pop(); // get out of "terrain" profiler.push("DH-RenderLevel"); @@ -474,20 +474,20 @@ public class ClientApi { return; } - - + + //FIXME: Improve class hierarchy of DhWorld, IClientWorld, IServerWorld to fix all this hard casting // (also in RenderUtil) IDhClientWorld dhClientWorld = SharedApi.getIDhClientWorld(); IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper); - + if (prefLoggerEnabled) { level.dumpRamUsage(); } - - - + + + try { @@ -495,9 +495,9 @@ public class ClientApi { DhApiRenderParam renderEventParam = new DhApiRenderParam(mcProjectionMatrix, mcModelViewMatrix, - RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks), - RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), partialTicks); - + RenderUtil.createLodProjectionMatrix(mcProjectionMatrix, partialTicks), + RenderUtil.createLodModelViewMatrix(mcModelViewMatrix), partialTicks); + boolean renderingCanceled = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderEvent.class, new DhApiBeforeRenderEvent.EventParam(renderEventParam)); if (!this.rendererDisabledBecauseOfExceptions && !renderingCanceled) { @@ -517,7 +517,7 @@ public class ClientApi { this.rendererDisabledBecauseOfExceptions = true; LOGGER.error("Renderer thrown an uncaught exception: ", e); - + MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons" + " renderer has encountered an exception!"); MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues."); @@ -534,13 +534,13 @@ public class ClientApi profiler.push("terrain"); // go back into "terrain" } } - - - + + + //=================// // DEBUG USE // //=================// - + /** Trigger once on key press, with CLIENT PLAYER. */ public void keyPressedEvent(int glfwKey) { @@ -549,8 +549,8 @@ public class ClientApi // keybindings are disabled return; } - - + + if (glfwKey == GLFW.GLFW_KEY_F8) { Config.Client.Advanced.Debugging.debugRendering.set(EDebugRendering.next(Config.Client.Advanced.Debugging.debugRendering.get())); @@ -567,6 +567,6 @@ public class ClientApi MC.sendChatMessage("P: Debug Pref Logger is " + (prefLoggerEnabled ? "enabled" : "disabled")); } } - - + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java index f8584c925..3d517cebe 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java @@ -79,23 +79,23 @@ public class ServerApi catch (Exception e) { // try catch is necessary to prevent crashing the internal server when an exception is thrown - LOGGER.error("ServerTickEvent error: "+e.getMessage(), e); + LOGGER.error("ServerTickEvent error: " + e.getMessage(), e); } } public void serverLevelTickEvent(IServerLevelWrapper level) { //TODO } - + public void serverLoadEvent(boolean isDedicatedEnvironment) { - LOGGER.debug("Server World loading with (dedicated?:"+isDedicatedEnvironment+")"); + LOGGER.debug("Server World loading with (dedicated?:" + isDedicatedEnvironment + ")"); SharedApi.setDhWorld(isDedicatedEnvironment ? new DhServerWorld() : new DhClientServerWorld()); } public void serverUnloadEvent() { - LOGGER.debug("Server World "+SharedApi.getAbstractDhWorld()+" unloading"); + LOGGER.debug("Server World " + SharedApi.getAbstractDhWorld() + " unloading"); SharedApi.getAbstractDhWorld().close(); SharedApi.setDhWorld(null); @@ -103,7 +103,7 @@ public class ServerApi public void serverLevelLoadEvent(IServerLevelWrapper level) { - LOGGER.debug("Server Level "+level+" loading"); + LOGGER.debug("Server Level " + level + " loading"); AbstractDhWorld serverWorld = SharedApi.getAbstractDhWorld(); if (serverWorld != null) @@ -114,7 +114,7 @@ public class ServerApi } public void serverLevelUnloadEvent(IServerLevelWrapper level) { - LOGGER.debug("Server Level "+level+" unloading"); + LOGGER.debug("Server Level " + level + " unloading"); AbstractDhWorld serverWorld = SharedApi.getAbstractDhWorld(); if (serverWorld != null) @@ -123,11 +123,11 @@ public class ServerApi ApiEventInjector.INSTANCE.fireAllEvents(DhApiLevelUnloadEvent.class, new DhApiLevelUnloadEvent.EventParam(level)); } } - + @Deprecated // TODO not implemented, remove public void serverSaveEvent() { - LOGGER.debug("Server world "+SharedApi.getAbstractDhWorld()+" saving"); + LOGGER.debug("Server world " + SharedApi.getAbstractDhWorld() + " saving"); AbstractDhWorld serverWorld = SharedApi.getAbstractDhWorld(); if (serverWorld != null) @@ -135,7 +135,7 @@ public class ServerApi serverWorld.saveAndFlush(); } } - + public void serverChunkLoadEvent(IChunkWrapper chunk, ILevelWrapper level) { // the world should always be non-null, this != null is just in case the world was removed accidentally diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index e00111b6d..5544c8811 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -11,21 +11,21 @@ import com.seibel.distanthorizons.core.world.*; /** Contains code and variables used by both {@link ClientApi} and {@link ServerApi} */ public class SharedApi { - private static AbstractDhWorld currentWorld; - + private static AbstractDhWorld currentWorld; - public static void init() { Initializer.init(); } + + public static void init() { Initializer.init(); } public static EWorldEnvironment getEnvironment() { return (currentWorld == null) ? null : currentWorld.environment; } - public static void setDhWorld(AbstractDhWorld newWorld) + public static void setDhWorld(AbstractDhWorld newWorld) { - currentWorld = newWorld; + currentWorld = newWorld; // starting and stopping the DataRenderTransformer is necessary to prevent attempting to // access the MC level at inappropriate times, which can cause exceptions diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/AppliedConfigState.java b/core/src/main/java/com/seibel/distanthorizons/core/config/AppliedConfigState.java index 658b374e8..8c8a6be15 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/AppliedConfigState.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/AppliedConfigState.java @@ -5,31 +5,31 @@ import com.seibel.distanthorizons.core.config.types.ConfigEntry; // TODO: Make this intergrate with the config system public class AppliedConfigState { - final ConfigEntry entry; - T activeValue; + final ConfigEntry entry; + T activeValue; - public AppliedConfigState(ConfigEntry entryToWatch) + public AppliedConfigState(ConfigEntry entryToWatch) { - this.entry = entryToWatch; - this.activeValue = entryToWatch.get(); - } + this.entry = entryToWatch; + this.activeValue = entryToWatch.get(); + } /** Returns true if the value was changed */ - public boolean pollNewValue() + public boolean pollNewValue() { - T newValue = this.entry.get(); - if (newValue.equals(this.activeValue)) + T newValue = this.entry.get(); + if (newValue.equals(this.activeValue)) { - return false; - } + return false; + } this.activeValue = newValue; - return true; - } + return true; + } - public T get() { return this.activeValue; } + public T get() { return this.activeValue; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 380b8a643..bb10fbd22 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -43,12 +43,12 @@ import java.util.*; /** * This handles any configuration the user has access to.

- * + * * Note:
* Only add simpler listeners here (IE listeners that only depend on 1 config entry). * For listeners that depend on 2 or more config entries, add them before the config menu is opened. * Otherwise, you will have issues where only some of the config entries will exist when your listener is created. - * + * * @author coolGi * @version 2023-7-16 */ @@ -57,11 +57,11 @@ public class Config { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static ConfigCategory client = new ConfigCategory.Builder().set(Client.class).build(); + public static ConfigCategory client = new ConfigCategory.Builder().set(Client.class).build(); - public static class Client - { + public static class Client + { public static ConfigEntry quickEnableRendering = new ConfigEntry.Builder() .set(true) .comment("" @@ -105,7 +105,7 @@ public class Config public static ConfigEntry optionsButton = new ConfigEntry.Builder() .set(true) .comment("" + - "Should Distant Horizon's config button appear in the options screen next to fov slider?") + "Should Distant Horizon's config button appear in the options screen next to fov slider?") .build(); @@ -219,7 +219,7 @@ public class Config + "\n" + "True: a red flower will tint the grass below it red. \n" + "False: skipped blocks will not change color of surface below them. " - +"") + + "") .setPerformance(EConfigEntryPerformance.NONE) .addListener(RenderCacheConfigEventHandler.INSTANCE) .build(); @@ -310,7 +310,7 @@ public class Config .build(); public static ConfigEntry farFogMin = new ConfigEntry.Builder() - .setMinDefaultMax(-5.0,0.0, FOG_RANGE_MAX) + .setMinDefaultMax(-5.0, 0.0, FOG_RANGE_MAX) .comment("" + "What is the minimum fog thickness? \n" + "\n" @@ -338,7 +338,7 @@ public class Config .build(); public static ConfigEntry farFogDensity = new ConfigEntry.Builder() - .setMinDefaultMax(0.01,2.5, 50.0) + .setMinDefaultMax(0.01, 2.5, 50.0) .comment("" + "Used in conjunction with the Fog Falloff.") .build(); @@ -367,7 +367,7 @@ public class Config + EHeightFogMixMode.INVERSE_MULTIPLY_ADDITION + ": farFog + 1 - (1-heightFog) * (1-farFog) \n" + EHeightFogMixMode.AVERAGE + ": farFog*0.5 + heightFog*0.5 \n" + "\n" - + "Note: height fog settings are ignored if '"+EHeightFogMixMode.BASIC+"' or '"+EHeightFogMixMode.IGNORE_HEIGHT+"' are selected.") + + "Note: height fog settings are ignored if '" + EHeightFogMixMode.BASIC + "' or '" + EHeightFogMixMode.IGNORE_HEIGHT + "' are selected.") .build(); public static ConfigEntry heightFogMode = new ConfigEntry.Builder() @@ -440,7 +440,9 @@ public class Config .build(); } + } + } public static class NoiseTextureSettings @@ -449,7 +451,7 @@ public class Config .set(true) .comment("" + "Should a noise texture be applied to LODs? \n" - +"\n" + + "\n" + "This is done to simulate textures and make the LODs appear more detailed. \n" + "") .build(); @@ -472,6 +474,7 @@ public class Config + "Defines how far should the noise texture render before it fades away. (in blocks) \n" + "Set to 0 to disable noise from fading away") .build(); + } public static class AdvancedGraphics @@ -512,7 +515,7 @@ public class Config + "reducing overdraw. \n" + "\n" + "Only functional on Fabric.\n" - + "Works best with an overdraw prevention setting of "+EOverdrawPrevention.MEDIUM+" or higher \n" + + "Works best with an overdraw prevention setting of " + EOverdrawPrevention.MEDIUM + " or higher \n" + " and cave culling is disabled. \n" + "") .setPerformance(EConfigEntryPerformance.NONE) @@ -553,13 +556,13 @@ public class Config .build(); public static ConfigEntry caveCullingHeight = new ConfigEntry.Builder() - .setMinDefaultMax(-4096,40,4096) - .comment("" + .setMinDefaultMax(-4096, 40, 4096) + .comment("" + "At what Y value should cave culling start?") .build(); public static ConfigEntry earthCurveRatio = new ConfigEntry.Builder() - .setMinDefaultMax(0,0,5000) + .setMinDefaultMax(0, 0, 5000) .comment("" + "This is the earth size ratio when applying the curvature shader effect. \n" + "Note: Enabling this feature may cause rendering bugs. \n" @@ -643,14 +646,14 @@ public class Config + "WARNING: This may cause world generator bugs or instability when paired with certain world generator mods. \n" + "- Fast \n" + "") - /* - // FULL isn't currently implemented - + "\n" - + EDhApiDistantGeneratorMode.FULL + " \n" - + "Ask the local server to generate/load each chunk. \n" - + "This is the most compatible, but will cause server/simulation lag. \n" - + "- Slow (15-50 ms, with spikes up to 200 ms) \n" - */ + /* + // FULL isn't currently implemented + + "\n" + + EDhApiDistantGeneratorMode.FULL + " \n" + + "Ask the local server to generate/load each chunk. \n" + + "This is the most compatible, but will cause server/simulation lag. \n" + + "- Slow (15-50 ms, with spikes up to 200 ms) \n" + */ .build(); public static ConfigEntry worldGenLightingEngine = new ConfigEntry.Builder() @@ -667,7 +670,7 @@ public class Config .build(); public static ConfigEntry worldGenerationTimeoutLengthInSeconds = new ConfigEntry.Builder() - .setMinDefaultMax(5, 60, 60*10/*10 minutes*/) + .setMinDefaultMax(5, 60, 60 * 10/*10 minutes*/ ) .comment("" + "How long should a world generator thread run for before timing out? \n" + "Note: If you are experiencing timeout errors it is better to lower your CPU usage first \n" @@ -695,7 +698,7 @@ public class Config + " fake chunks. \n" + "\n" + EGenerationPriority.BALANCED + " \n" - + "A mix between "+ EGenerationPriority.NEAR_FIRST+"and"+ EGenerationPriority.FAR_FIRST+". \n" + + "A mix between " + EGenerationPriority.NEAR_FIRST + "and" + EGenerationPriority.FAR_FIRST + ". \n" + "First prioritise completing nearby highest detail chunks, \n" + " then focus on filling in the low detail areas away from the player. \n" + "\n" @@ -933,6 +936,7 @@ public class Config + "How frequently should vertex buffers (geometry) be rebuilt and sent to the GPU? \n" + "Higher settings may cause stuttering, but will prevent holes in the world") .build(); + } public static class AutoUpdater @@ -945,10 +949,11 @@ public class Config public static ConfigEntry enableSilentUpdates = new ConfigEntry.Builder() .set(false) - .comment("" + .comment("" + "Should Distant Horizons silently, automatically download and install new versions? " + "") .build(); + } public static class Logging @@ -1017,6 +1022,7 @@ public class Config + "If enabled, the mod will log information about network operations. \n" + "This can be useful for debugging.") .build(); + } public static class Debugging @@ -1068,7 +1074,7 @@ public class Config + " This setting is only for fun and debugging. \n" + " Mod compatibility is not guaranteed.") .build(); - + public static ConfigEntry debugWireframeRendering = new ConfigEntry.Builder() .set(false) .comment("" @@ -1078,21 +1084,21 @@ public class Config + " Additionally, only stuff that's loaded after you enable this \n" + " will render their debug wireframes.") .build(); - + public static ConfigEntry enableWhiteWorld = new ConfigEntry.Builder() .set(false) .comment("" + "Stops vertex colors from being passed. \n" + "Useful for debugging shaders") .build(); - + // Note: This will reset on game restart, and should have a warning on the tooltip public static ConfigEntry allowUnsafeValues = new ConfigEntry.Builder() .set(false) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .addListener(UnsafeValuesConfigListener.INSTANCE) .build(); - + // can be set to public inorder to show in the config file and UI public static ConfigCategory exampleConfigScreen = new ConfigCategory.Builder() @@ -1130,7 +1136,7 @@ public class Config public static ConfigEntry longTest = new ConfigEntry.Builder() .set(42069L) .build(); - + public static ConfigEntry floatTest = new ConfigEntry.Builder() .set(0.42069f) .build(); @@ -1142,15 +1148,15 @@ public class Config public static ConfigEntry> listTest = new ConfigEntry.Builder>() .set(new ArrayList(Arrays.asList("option 1", "option 2", "option 3"))) .build(); - + public static ConfigEntry> mapTest = new ConfigEntry.Builder>() .set(new HashMap()) .build(); - + public static ConfigUIButton uiButtonTest = new ConfigUIButton(() -> { System.setProperty("java.awt.headless", "false"); // Required to make it work - JOptionPane.showMessageDialog(null, "Button pressed!", "UITester dialog", JOptionPane.INFORMATION_MESSAGE); - }); + JOptionPane.showMessageDialog(null, "Button pressed!", "UITester dialog", JOptionPane.INFORMATION_MESSAGE); + }); public static ConfigCategory categoryTest = new ConfigCategory.Builder().set(CategoryTest.class).build(); @@ -1163,7 +1169,9 @@ public class Config { // The name of this can be anything as it will be overwritten by the name of the linked object public static ConfigLinkedEntry linkableTest = new ConfigLinkedEntry(ExampleConfigScreen.linkableTest); + } + } } @@ -1184,7 +1192,7 @@ public class Config } - } + } @@ -1193,10 +1201,10 @@ public class Config /** * Runs any config setup that needs all (or most) config entries be initialized (not null), * but doesn't necessarily require they have the right values yet.

- * + * * Specially: - * Updates any config values that are UI only - * and adds any listeners that depend on multiple config values. + * Updates any config values that are UI only + * and adds any listeners that depend on multiple config values. */ public static void completeDelayedSetup() { @@ -1208,11 +1216,11 @@ public class Config { ThreadPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); RenderQualityPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); - QuickRenderToggleConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); + QuickRenderToggleConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); } catch (Exception e) { - LOGGER.error("Unexpected exception when setting up complicated config listeners. Error: ["+e.getMessage()+"].", e); + LOGGER.error("Unexpected exception when setting up complicated config listeners. Error: [" + e.getMessage() + "].", e); } } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java b/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java index 7b0ddd4e3..0df37a368 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java @@ -20,181 +20,205 @@ import java.util.*; * @author Ran */ // Init the config after singletons have been blinded -public class ConfigBase +public class ConfigBase { - /** Our own config instance, don't modify */ - public static ConfigBase INSTANCE; - public ConfigFileHandling configFileINSTANCE; - - public static final Logger LOGGER = LogManager.getLogger(ConfigBase.class.getSimpleName()); - public final String modID; - public final String modName; - public final int configVersion; + /** Our own config instance, don't modify */ + public static ConfigBase INSTANCE; + public ConfigFileHandling configFileINSTANCE; + + public static final Logger LOGGER = LogManager.getLogger(ConfigBase.class.getSimpleName()); + public final String modID; + public final String modName; + public final int configVersion; + + /** + * What the config works with + * + * Enum + * Boolean + * Byte + * Integer + * Double + * Short + * Long + * Float + * String + * + * // Below, "T" should be a value from above + * List + * ArrayList + * Map + * HashMap + */ + public static final List> acceptableInputs = new ArrayList>() + {{ + add(Boolean.class); + add(Byte.class); + add(Integer.class); + add(Double.class); + add(Short.class); + add(Long.class); + add(Float.class); + add(String.class); + + // TODO[CONFIG]: Check the type of these is valid + add(List.class); + add(ArrayList.class); + add(Map.class); + add(HashMap.class); + }}; + + /** Disables the minimum and maximum of any variable */ + public boolean disableMinMax = false; // Very fun to use, but should always be disabled by default + public final List> entries = new ArrayList<>(); + + + public ConfigBase(String modID, String modName, Class config, int configVersion) + { + LOGGER.info("Initialising config for " + modName); + this.modID = modID; + this.modName = modName; + this.configVersion = configVersion; + + initNestedClass(config, ""); // Init root category + + // File handling (load from file) + this.configFileINSTANCE = new ConfigFileHandling(this); + this.configFileINSTANCE.loadFromFile(); + LOGGER.info("Config for " + modName + " initialised"); + } + + private void initNestedClass(Class config, String category) + { + // Put all the entries in entries + + for (Field field : config.getFields()) + { + if (AbstractConfigType.class.isAssignableFrom(field.getType())) + { + try + { + entries.add((AbstractConfigType) field.get(field.getType())); + } + catch (IllegalAccessException exception) + { + exception.printStackTrace(); + } + + AbstractConfigType entry = entries.get(entries.size() - 1); + entry.category = category; + entry.name = field.getName(); + entry.configBase = this; + + if (ConfigEntry.class.isAssignableFrom(field.getType())) + { // If item is type ConfigEntry + if (!isAcceptableType(entry.getType())) + { + LOGGER.error("Invalid variable type at [" + (category.isEmpty() ? "" : category + ".") + field.getName() + "]."); + LOGGER.error("Type [" + entry.getType() + "] is not one of these types [" + acceptableInputs.toString() + "]"); + entries.remove(entries.size() - 1); // Delete the entry if it is invalid so the game can still run + } + } + + if (ConfigCategory.class.isAssignableFrom(field.getType())) + { // If it's a category then init the stuff inside it and put it in the category list + assert entry instanceof ConfigCategory; + if (((ConfigCategory) entry).getDestination() == null) + ((ConfigCategory) entry).destination = entry.getNameWCategory(); + if (entry.get() != null) + { + initNestedClass(((ConfigCategory) entry).get(), ((ConfigCategory) entry).getDestination()); + } + } + } + } + } + + private static boolean isAcceptableType(Class Clazz) + { + if (Clazz.isEnum()) + return true; + return acceptableInputs.contains(Clazz); + } + + + + + /** + * Used for checking that all the lang files for the config exist + * + * @param onlyShowNew If disabled then it would basically remake the config lang + * @param checkEnums Checks if all the lang for the enum's exist + */ + // This is just to re-format the lang or check if there is something in the lang that is missing + public String generateLang(boolean onlyShowNew, boolean checkEnums) + { + ILangWrapper langWrapper = SingletonInjector.INSTANCE.get(ILangWrapper.class); + List> enumList = new ArrayList<>(); + + String generatedLang = ""; + + String starter = " \""; + String separator = "\":\n \""; + String ending = "\",\n"; + + for (AbstractConfigType entry : this.entries) + { + String entryPrefix = "lod.config." + entry.getNameWCategory(); + + if (checkEnums && entry.getType().isEnum() && !enumList.contains(entry.getType())) + { // Put it in an enum list to work with at the end + enumList.add((Class) entry.getType()); + } + if (!onlyShowNew || langWrapper.langExists(entryPrefix)) + { + if (!ConfigLinkedEntry.class.isAssignableFrom(entry.getClass())) + { // If it is a linked item, dont generate the base lang + generatedLang += starter + + entryPrefix + + separator + + langWrapper.getLang(entryPrefix) + + ending + ; + } + // Adds tooltips + if (langWrapper.langExists(entryPrefix + ".@tooltip")) + { + generatedLang += starter + + entryPrefix + ".@tooltip" + + separator + + langWrapper.getLang(entryPrefix + ".@tooltip") + .replaceAll("\n", "\\\\n") + .replaceAll("\"", "\\\\\"") + + ending + ; + } + } + } + if (!enumList.isEmpty()) + { + generatedLang += "\n"; // Separate the main lang with the enum's + + for (Class anEnum : enumList) + { + for (Object enumStr : new ArrayList<>(EnumSet.allOf(anEnum))) + { + String enumPrefix = "lod.config.enum." + anEnum.getSimpleName() + "." + enumStr.toString(); + + if (!onlyShowNew || langWrapper.langExists(enumPrefix)) + { + generatedLang += starter + + enumPrefix + + separator + + langWrapper.getLang(enumPrefix) + + ending + ; + } + } + } + } + + return generatedLang; + } - /** - What the config works with - - Enum - Boolean - Byte - Integer - Double - Short - Long - Float - String - - // Below, "T" should be a value from above - List - ArrayList - Map - HashMap - */ - public static final List> acceptableInputs = new ArrayList>() {{ - add(Boolean.class); - add(Byte.class); - add(Integer.class); - add(Double.class); - add(Short.class); - add(Long.class); - add(Float.class); - add(String.class); - - // TODO[CONFIG]: Check the type of these is valid - add(List.class); - add(ArrayList.class); - add(Map.class); - add(HashMap.class); - }}; - - /** Disables the minimum and maximum of any variable */ - public boolean disableMinMax = false; // Very fun to use, but should always be disabled by default - public final List> entries = new ArrayList<>(); - - - public ConfigBase(String modID, String modName, Class config, int configVersion) { - LOGGER.info("Initialising config for " + modName); - this.modID = modID; - this.modName = modName; - this.configVersion = configVersion; - - initNestedClass(config, ""); // Init root category - - // File handling (load from file) - this.configFileINSTANCE = new ConfigFileHandling(this); - this.configFileINSTANCE.loadFromFile(); - LOGGER.info("Config for " + modName + " initialised"); - } - - private void initNestedClass(Class config, String category) { - // Put all the entries in entries - - for (Field field : config.getFields()) { - if (AbstractConfigType.class.isAssignableFrom(field.getType())) { - try { - entries.add((AbstractConfigType) field.get(field.getType())); - } catch (IllegalAccessException exception) { - exception.printStackTrace(); - } - - AbstractConfigType entry = entries.get(entries.size() - 1); - entry.category = category; - entry.name = field.getName(); - entry.configBase = this; - - if (ConfigEntry.class.isAssignableFrom(field.getType())) { // If item is type ConfigEntry - if (!isAcceptableType(entry.getType())) { - LOGGER.error("Invalid variable type at [" + (category.isEmpty() ? "" : category + ".") + field.getName() + "]."); - LOGGER.error("Type [" + entry.getType() + "] is not one of these types [" + acceptableInputs.toString() + "]"); - entries.remove(entries.size() -1); // Delete the entry if it is invalid so the game can still run - } - } - - if (ConfigCategory.class.isAssignableFrom(field.getType())) { // If it's a category then init the stuff inside it and put it in the category list - assert entry instanceof ConfigCategory; - if (((ConfigCategory) entry).getDestination() == null) - ((ConfigCategory) entry).destination = entry.getNameWCategory(); - if (entry.get() != null) { - initNestedClass(((ConfigCategory) entry).get(), ((ConfigCategory) entry).getDestination()); - } - } - } - } - } - - private static boolean isAcceptableType(Class Clazz) { - if (Clazz.isEnum()) - return true; - return acceptableInputs.contains(Clazz); - } - - - - - /** - * Used for checking that all the lang files for the config exist - * - * @param onlyShowNew If disabled then it would basically remake the config lang - * @param checkEnums Checks if all the lang for the enum's exist - */ - // This is just to re-format the lang or check if there is something in the lang that is missing - public String generateLang(boolean onlyShowNew, boolean checkEnums) { - ILangWrapper langWrapper = SingletonInjector.INSTANCE.get(ILangWrapper.class); - List> enumList = new ArrayList<>(); - - String generatedLang = ""; - - String starter = " \""; - String separator = "\":\n \""; - String ending = "\",\n"; - - for (AbstractConfigType entry: this.entries) { - String entryPrefix = "lod.config."+entry.getNameWCategory(); - - if (checkEnums && entry.getType().isEnum() && !enumList.contains(entry.getType())) { // Put it in an enum list to work with at the end - enumList.add((Class) entry.getType()); - } - if (!onlyShowNew || langWrapper.langExists(entryPrefix)) { - if (!ConfigLinkedEntry.class.isAssignableFrom(entry.getClass())) { // If it is a linked item, dont generate the base lang - generatedLang += starter - + entryPrefix - + separator - + langWrapper.getLang(entryPrefix) - + ending - ; - } - // Adds tooltips - if (langWrapper.langExists(entryPrefix+".@tooltip")) { - generatedLang += starter - + entryPrefix+".@tooltip" - + separator - + langWrapper.getLang(entryPrefix+".@tooltip") - .replaceAll("\n", "\\\\n") - .replaceAll("\"", "\\\\\"") - + ending - ; - } - } - } - if (!enumList.isEmpty()) { - generatedLang += "\n"; // Separate the main lang with the enum's - - for (Class anEnum: enumList) { - for (Object enumStr: new ArrayList<>(EnumSet.allOf(anEnum))) { - String enumPrefix = "lod.config.enum."+anEnum.getSimpleName()+"."+enumStr.toString(); - - if (!onlyShowNew || langWrapper.langExists(enumPrefix)) { - generatedLang += starter - + enumPrefix - + separator - + langWrapper.getLang(enumPrefix) - + ending - ; - } - } - } - } - - return generatedLang; - } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java index 1731da4d0..b53e59f89 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java @@ -10,59 +10,67 @@ import java.util.Map; * @version 2023-7-16 */ // TODO: Should this be moved out of here into somewhere like the util section -public class NumberUtil { - // Is there no better way of doing this? - public static Map minValues = new HashMap() {{ - put(Byte.class, Byte.MIN_VALUE); - put(Short.class, Short.MIN_VALUE); - put(Integer.class, Integer.MIN_VALUE); - put(Long.class, Long.MIN_VALUE); - put(Double.class, Double.MIN_VALUE); - put(Float.class, Float.MIN_VALUE); - }}; - public static Map maxValues = new HashMap() {{ - put(Byte.class, Byte.MAX_VALUE); - put(Short.class, Short.MAX_VALUE); - put(Integer.class, Integer.MAX_VALUE); - put(Long.class, Long.MAX_VALUE); - put(Double.class, Double.MAX_VALUE); - put(Float.class, Float.MAX_VALUE); - }}; - - public static Number getMinimum(Class c) { - return minValues.get(c); - } - public static Number getMaximum(Class c) { - return maxValues.get(c); - } - - /** Does a greater than (>) operator on any number */ - public static boolean greaterThan(Number a, Number b) { - if (a.getClass() != b.getClass()) - return false; - Class typeClass = a.getClass(); - - if (typeClass == Byte.class) return a.byteValue() > b.byteValue(); - if (typeClass == Short.class) return a.shortValue() > b.shortValue(); - if (typeClass == Integer.class) return a.intValue() > b.intValue(); - if (typeClass == Long.class) return a.longValue() > b.longValue(); - if (typeClass == Double.class) return a.doubleValue() > b.doubleValue(); - if (typeClass == Float.class) return a.floatValue() > b.floatValue(); - return false; - } - - /** Does a less than (<) operator on any number */ - public static boolean lessThan(Number a, Number b) { - if (a.getClass() != b.getClass()) - return false; - Class typeClass = a.getClass(); - - if (typeClass == Byte.class) return a.byteValue() < b.byteValue(); - if (typeClass == Short.class) return a.shortValue() < b.shortValue(); - if (typeClass == Integer.class) return a.intValue() < b.intValue(); - if (typeClass == Long.class) return a.longValue() < b.longValue(); - if (typeClass == Double.class) return a.doubleValue() < b.doubleValue(); - if (typeClass == Float.class) return a.floatValue() < b.floatValue(); - return false; - } +public class NumberUtil +{ + // Is there no better way of doing this? + public static Map minValues = new HashMap() + {{ + put(Byte.class, Byte.MIN_VALUE); + put(Short.class, Short.MIN_VALUE); + put(Integer.class, Integer.MIN_VALUE); + put(Long.class, Long.MIN_VALUE); + put(Double.class, Double.MIN_VALUE); + put(Float.class, Float.MIN_VALUE); + }}; + public static Map maxValues = new HashMap() + {{ + put(Byte.class, Byte.MAX_VALUE); + put(Short.class, Short.MAX_VALUE); + put(Integer.class, Integer.MAX_VALUE); + put(Long.class, Long.MAX_VALUE); + put(Double.class, Double.MAX_VALUE); + put(Float.class, Float.MAX_VALUE); + }}; + + public static Number getMinimum(Class c) + { + return minValues.get(c); + } + public static Number getMaximum(Class c) + { + return maxValues.get(c); + } + + /** Does a greater than (>) operator on any number */ + public static boolean greaterThan(Number a, Number b) + { + if (a.getClass() != b.getClass()) + return false; + Class typeClass = a.getClass(); + + if (typeClass == Byte.class) return a.byteValue() > b.byteValue(); + if (typeClass == Short.class) return a.shortValue() > b.shortValue(); + if (typeClass == Integer.class) return a.intValue() > b.intValue(); + if (typeClass == Long.class) return a.longValue() > b.longValue(); + if (typeClass == Double.class) return a.doubleValue() > b.doubleValue(); + if (typeClass == Float.class) return a.floatValue() > b.floatValue(); + return false; + } + + /** Does a less than (<) operator on any number */ + public static boolean lessThan(Number a, Number b) + { + if (a.getClass() != b.getClass()) + return false; + Class typeClass = a.getClass(); + + if (typeClass == Byte.class) return a.byteValue() < b.byteValue(); + if (typeClass == Short.class) return a.shortValue() < b.shortValue(); + if (typeClass == Integer.class) return a.intValue() < b.intValue(); + if (typeClass == Long.class) return a.longValue() < b.longValue(); + if (typeClass == Double.class) return a.doubleValue() < b.doubleValue(); + if (typeClass == Float.class) return a.floatValue() < b.floatValue(); + return false; + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/QuickRenderToggleConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/QuickRenderToggleConfigEventHandler.java index 5f5a5a12a..d3b8811c5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/QuickRenderToggleConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/QuickRenderToggleConfigEventHandler.java @@ -14,15 +14,15 @@ public class QuickRenderToggleConfigEventHandler /** private since we only ever need one handler at a time */ - private QuickRenderToggleConfigEventHandler() + private QuickRenderToggleConfigEventHandler() { this.quickRenderChangeListener = new ConfigChangeListener<>(Config.Client.quickEnableRendering, (val) -> { Config.Client.Advanced.Debugging.rendererMode.set(Config.Client.quickEnableRendering.get() ? ERendererMode.DEFAULT : ERendererMode.DISABLED); }); this.rendererModeChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Debugging.rendererMode, (val) -> { Config.Client.quickEnableRendering.set(Config.Client.Advanced.Debugging.rendererMode.get() != ERendererMode.DISABLED); }); } /** - * Set the UI only config based on what is set in the file.
- * This should only be called once. + * Set the UI only config based on what is set in the file.
+ * This should only be called once. */ public void setUiOnlyConfigValues() { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java index 8bbca7f0c..4f69ce2ed 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java @@ -13,7 +13,7 @@ import java.util.TimerTask; /** * Listens to the config and will automatically * clear the current render cache if certain settings are changed.

- * + * * Note: if additional settings should clear the render cache, add those to this listener, don't create a new listener */ public class RenderCacheConfigEventHandler implements IConfigListener @@ -31,11 +31,11 @@ public class RenderCacheConfigEventHandler implements IConfigListener /** private since we only ever need one handler at a time */ - private RenderCacheConfigEventHandler() { } + private RenderCacheConfigEventHandler() { } - @Override + @Override public void onConfigValueSet() { // confirm a setting was actually changed diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ResetConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ResetConfigEventHandler.java index 7c05ed28f..a2fd1a48e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ResetConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ResetConfigEventHandler.java @@ -11,7 +11,7 @@ public class ResetConfigEventHandler /** private since we only ever need one handler at a time */ - private ResetConfigEventHandler() + private ResetConfigEventHandler() { this.configChangeListener = new ConfigChangeListener<>(Config.Client.ResetConfirmation.resetAllSettings, (resetSettings) -> { doStuff(resetSettings); }); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java index 4c0eca3bc..af7f1f19c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java @@ -3,17 +3,21 @@ package com.seibel.distanthorizons.core.config.eventHandlers; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.listeners.IConfigListener; -public class UnsafeValuesConfigListener implements IConfigListener { - public static UnsafeValuesConfigListener INSTANCE = new UnsafeValuesConfigListener(); - - @Override - public void onConfigValueSet() { - Config.Client.Advanced.Debugging.allowUnsafeValues.configBase.disableMinMax = - Config.Client.Advanced.Debugging.allowUnsafeValues.get(); - } - - @Override - public void onUiModify() { - - } +public class UnsafeValuesConfigListener implements IConfigListener +{ + public static UnsafeValuesConfigListener INSTANCE = new UnsafeValuesConfigListener(); + + @Override + public void onConfigValueSet() + { + Config.Client.Advanced.Debugging.allowUnsafeValues.configBase.disableMinMax = + Config.Client.Advanced.Debugging.allowUnsafeValues.get(); + } + + @Override + public void onUiModify() + { + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/AbstractPresetConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/AbstractPresetConfigEventHandler.java index 9c21d6233..36b103c49 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/AbstractPresetConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/AbstractPresetConfigEventHandler.java @@ -22,9 +22,9 @@ public abstract class AbstractPresetConfigEventHandler - * This should only be called once. + /** + * Set the UI only config based on what is set in the file.
+ * This should only be called once. */ public void setUiOnlyConfigValues() { @@ -37,7 +37,7 @@ public abstract class AbstractPresetConfigEventHandler 1) { // we shouldn't have multiple options, but just in case - LOGGER.warn("Multiple potential preset options ["+StringUtil.join(", ", possiblePrestList)+"], defaulting to the first one."); + LOGGER.warn("Multiple potential preset options [" + StringUtil.join(", ", possiblePrestList) + "], defaulting to the first one."); } if (possiblePrestList.size() == 0) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/RenderQualityPresetConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/RenderQualityPresetConfigEventHandler.java index c830fd611..5ae270f1d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/RenderQualityPresetConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/RenderQualityPresetConfigEventHandler.java @@ -21,51 +21,51 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE private static final Logger LOGGER = LogManager.getLogger(); - private final ConfigEntryWithPresetOptions drawResolution = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.maxHorizontalResolution, - new HashMap() - {{ - this.put(EQualityPreset.MINIMUM, EMaxHorizontalResolution.TWO_BLOCKS); - this.put(EQualityPreset.LOW, EMaxHorizontalResolution.BLOCK); - this.put(EQualityPreset.MEDIUM, EMaxHorizontalResolution.BLOCK); - this.put(EQualityPreset.HIGH, EMaxHorizontalResolution.BLOCK); - this.put(EQualityPreset.EXTREME, EMaxHorizontalResolution.BLOCK); - }}); + private final ConfigEntryWithPresetOptions drawResolution = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.maxHorizontalResolution, + new HashMap() + {{ + this.put(EQualityPreset.MINIMUM, EMaxHorizontalResolution.TWO_BLOCKS); + this.put(EQualityPreset.LOW, EMaxHorizontalResolution.BLOCK); + this.put(EQualityPreset.MEDIUM, EMaxHorizontalResolution.BLOCK); + this.put(EQualityPreset.HIGH, EMaxHorizontalResolution.BLOCK); + this.put(EQualityPreset.EXTREME, EMaxHorizontalResolution.BLOCK); + }}); private final ConfigEntryWithPresetOptions verticalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.verticalQuality, - new HashMap() - {{ - this.put(EQualityPreset.MINIMUM, EVerticalQuality.HEIGHT_MAP); - this.put(EQualityPreset.LOW, EVerticalQuality.LOW); - this.put(EQualityPreset.MEDIUM, EVerticalQuality.MEDIUM); - this.put(EQualityPreset.HIGH, EVerticalQuality.HIGH); - this.put(EQualityPreset.EXTREME, EVerticalQuality.EXTREME); - }}); + new HashMap() + {{ + this.put(EQualityPreset.MINIMUM, EVerticalQuality.HEIGHT_MAP); + this.put(EQualityPreset.LOW, EVerticalQuality.LOW); + this.put(EQualityPreset.MEDIUM, EVerticalQuality.MEDIUM); + this.put(EQualityPreset.HIGH, EVerticalQuality.HIGH); + this.put(EQualityPreset.EXTREME, EVerticalQuality.EXTREME); + }}); private final ConfigEntryWithPresetOptions horizontalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality, - new HashMap() - {{ - this.put(EQualityPreset.MINIMUM, EHorizontalQuality.LOWEST); - this.put(EQualityPreset.LOW, EHorizontalQuality.LOW); - this.put(EQualityPreset.MEDIUM, EHorizontalQuality.MEDIUM); - this.put(EQualityPreset.HIGH, EHorizontalQuality.HIGH); - this.put(EQualityPreset.EXTREME, EHorizontalQuality.EXTREME); - }}); - private final ConfigEntryWithPresetOptions transparency = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.transparency, - new HashMap() - {{ - this.put(EQualityPreset.MINIMUM, ETransparency.DISABLED); - this.put(EQualityPreset.LOW, ETransparency.DISABLED); // should be fake if/when fake is fixed - this.put(EQualityPreset.MEDIUM, ETransparency.COMPLETE); - this.put(EQualityPreset.HIGH, ETransparency.COMPLETE); - this.put(EQualityPreset.EXTREME, ETransparency.COMPLETE); - }}); - private final ConfigEntryWithPresetOptions ssao = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.ssao, - new HashMap() - {{ - this.put(EQualityPreset.MINIMUM, false); - this.put(EQualityPreset.LOW, false); - this.put(EQualityPreset.MEDIUM, true); - this.put(EQualityPreset.HIGH, true); - this.put(EQualityPreset.EXTREME, true); - }}); + new HashMap() + {{ + this.put(EQualityPreset.MINIMUM, EHorizontalQuality.LOWEST); + this.put(EQualityPreset.LOW, EHorizontalQuality.LOW); + this.put(EQualityPreset.MEDIUM, EHorizontalQuality.MEDIUM); + this.put(EQualityPreset.HIGH, EHorizontalQuality.HIGH); + this.put(EQualityPreset.EXTREME, EHorizontalQuality.EXTREME); + }}); + private final ConfigEntryWithPresetOptions transparency = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.transparency, + new HashMap() + {{ + this.put(EQualityPreset.MINIMUM, ETransparency.DISABLED); + this.put(EQualityPreset.LOW, ETransparency.DISABLED); // should be fake if/when fake is fixed + this.put(EQualityPreset.MEDIUM, ETransparency.COMPLETE); + this.put(EQualityPreset.HIGH, ETransparency.COMPLETE); + this.put(EQualityPreset.EXTREME, ETransparency.COMPLETE); + }}); + private final ConfigEntryWithPresetOptions ssao = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.ssao, + new HashMap() + {{ + this.put(EQualityPreset.MINIMUM, false); + this.put(EQualityPreset.LOW, false); + this.put(EQualityPreset.MEDIUM, true); + this.put(EQualityPreset.HIGH, true); + this.put(EQualityPreset.EXTREME, true); + }}); @@ -74,7 +74,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE //==============// /** private since we only ever need one handler at a time */ - private RenderQualityPresetConfigEventHandler() + private RenderQualityPresetConfigEventHandler() { // add each config used by this preset this.configList.add(this.drawResolution); @@ -100,9 +100,9 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE @Override protected IConfigEntry getPresetConfigEntry() { return Config.Client.qualityPresetSetting; } - @Override + @Override protected List getPresetEnumList() { return Arrays.asList(EQualityPreset.values()); } - @Override + @Override protected EQualityPreset getCustomPresetEnum() { return EQualityPreset.CUSTOM; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/ThreadPresetConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/ThreadPresetConfigEventHandler.java index 1a3f5e295..61b777b6e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/ThreadPresetConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/ThreadPresetConfigEventHandler.java @@ -22,114 +22,114 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan - public static int getWorldGenDefaultThreadCount() { return getThreadCountByPercent(0.2); } - private final ConfigEntryWithPresetOptions worldGenThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 1); - this.put(EThreadPreset.LOW_IMPACT, getWorldGenDefaultThreadCount()); - this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.4)); - this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.6)); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); - }}); + public static int getWorldGenDefaultThreadCount() { return getThreadCountByPercent(0.2); } + private final ConfigEntryWithPresetOptions worldGenThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads, + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 1); + this.put(EThreadPreset.LOW_IMPACT, getWorldGenDefaultThreadCount()); + this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.4)); + this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.6)); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); + }}); public static double getWorldGenDefaultRunTimeRatio() { return LOW_THREAD_COUNT_CPU ? 0.5 : 1; } private final ConfigEntryWithPresetOptions worldGenRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, LOW_THREAD_COUNT_CPU ? 0.1 : 0.25); - this.put(EThreadPreset.LOW_IMPACT, getWorldGenDefaultRunTimeRatio()); - this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.5 : 1.0); - this.put(EThreadPreset.AGGRESSIVE, LOW_THREAD_COUNT_CPU ? 0.75 : 1.0); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); - }}); + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, LOW_THREAD_COUNT_CPU ? 0.1 : 0.25); + this.put(EThreadPreset.LOW_IMPACT, getWorldGenDefaultRunTimeRatio()); + this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.5 : 1.0); + this.put(EThreadPreset.AGGRESSIVE, LOW_THREAD_COUNT_CPU ? 0.75 : 1.0); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); + }}); public static int getBufferBuilderDefaultThreadCount() { return getThreadCountByPercent(0.1); } - private final ConfigEntryWithPresetOptions bufferBuilderThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfBufferBuilderThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 1); - this.put(EThreadPreset.LOW_IMPACT, getBufferBuilderDefaultThreadCount()); - this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); - this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4)); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); - }}); + private final ConfigEntryWithPresetOptions bufferBuilderThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfBufferBuilderThreads, + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 1); + this.put(EThreadPreset.LOW_IMPACT, getBufferBuilderDefaultThreadCount()); + this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); + this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4)); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); + }}); public static double getBufferBuilderDefaultRunTimeRatio() { return LOW_THREAD_COUNT_CPU ? 0.5 : 0.75; } private final ConfigEntryWithPresetOptions bufferBuilderRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForBufferBuilderThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 0.25); - this.put(EThreadPreset.LOW_IMPACT, getBufferBuilderDefaultRunTimeRatio()); - this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.75 : 1.0); - this.put(EThreadPreset.AGGRESSIVE, 1.0); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); - }}); + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 0.25); + this.put(EThreadPreset.LOW_IMPACT, getBufferBuilderDefaultRunTimeRatio()); + this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.75 : 1.0); + this.put(EThreadPreset.AGGRESSIVE, 1.0); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); + }}); public static int getFileHandlerDefaultThreadCount() { return getThreadCountByPercent(0.1); } - private final ConfigEntryWithPresetOptions fileHandlerThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfFileHandlerThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 1); - this.put(EThreadPreset.LOW_IMPACT, getFileHandlerDefaultThreadCount()); - this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); - this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2)); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); - }}); + private final ConfigEntryWithPresetOptions fileHandlerThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfFileHandlerThreads, + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 1); + this.put(EThreadPreset.LOW_IMPACT, getFileHandlerDefaultThreadCount()); + this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); + this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2)); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); + }}); public static double getFileHandlerDefaultRunTimeRatio() { return 0.5; } private final ConfigEntryWithPresetOptions fileHandlerRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForFileHandlerThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 0.25); - this.put(EThreadPreset.LOW_IMPACT, getFileHandlerDefaultRunTimeRatio()); - this.put(EThreadPreset.BALANCED, 0.75); - this.put(EThreadPreset.AGGRESSIVE, 1.0); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); - }}); + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 0.25); + this.put(EThreadPreset.LOW_IMPACT, getFileHandlerDefaultRunTimeRatio()); + this.put(EThreadPreset.BALANCED, 0.75); + this.put(EThreadPreset.AGGRESSIVE, 1.0); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); + }}); public static int getDataTransformerDefaultThreadCount() { return getThreadCountByPercent(0.1); } - private final ConfigEntryWithPresetOptions dataTransformerThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfDataTransformerThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 1); - this.put(EThreadPreset.LOW_IMPACT, getDataTransformerDefaultThreadCount()); - this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); - this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2)); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); - }}); + private final ConfigEntryWithPresetOptions dataTransformerThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfDataTransformerThreads, + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 1); + this.put(EThreadPreset.LOW_IMPACT, getDataTransformerDefaultThreadCount()); + this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); + this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2)); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); + }}); public static double getDataTransformerDefaultRunTimeRatio() { return LOW_THREAD_COUNT_CPU ? 0.5 : 1; } private final ConfigEntryWithPresetOptions dataTransformerRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForDataTransformerThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 0.25); - this.put(EThreadPreset.LOW_IMPACT, getDataTransformerDefaultRunTimeRatio()); - this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.75 : 1); - this.put(EThreadPreset.AGGRESSIVE, 1.0); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); - }}); + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 0.25); + this.put(EThreadPreset.LOW_IMPACT, getDataTransformerDefaultRunTimeRatio()); + this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.75 : 1); + this.put(EThreadPreset.AGGRESSIVE, 1.0); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); + }}); public static int getChunkLodConverterDefaultThreadCount() { return getThreadCountByPercent(0.1); } - private final ConfigEntryWithPresetOptions chunkLodConverterThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfChunkLodConverterThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, 1); - this.put(EThreadPreset.LOW_IMPACT, getChunkLodConverterDefaultThreadCount()); - this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); - this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4)); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); - }}); + private final ConfigEntryWithPresetOptions chunkLodConverterThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfChunkLodConverterThreads, + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, 1); + this.put(EThreadPreset.LOW_IMPACT, getChunkLodConverterDefaultThreadCount()); + this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.2)); + this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4)); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); + }}); public static double getChunkLodConverterDefaultRunTimeRatio() { return LOW_THREAD_COUNT_CPU ? 0.5 : 0.75; } private final ConfigEntryWithPresetOptions chunkLodConverterRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForChunkLodConverterThreads, - new HashMap() - {{ - this.put(EThreadPreset.MINIMAL_IMPACT, LOW_THREAD_COUNT_CPU ? 0.1 : 0.25); - this.put(EThreadPreset.LOW_IMPACT, getDataTransformerDefaultRunTimeRatio()); - this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.75 : 1); - this.put(EThreadPreset.AGGRESSIVE, 1.0); - //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); - }}); + new HashMap() + {{ + this.put(EThreadPreset.MINIMAL_IMPACT, LOW_THREAD_COUNT_CPU ? 0.1 : 0.25); + this.put(EThreadPreset.LOW_IMPACT, getDataTransformerDefaultRunTimeRatio()); + this.put(EThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.75 : 1); + this.put(EThreadPreset.AGGRESSIVE, 1.0); + //this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); + }}); @@ -138,7 +138,7 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan //==============// /** private since we only ever need one handler at a time */ - private ThreadPresetConfigEventHandler() + private ThreadPresetConfigEventHandler() { // add each config used by this preset this.configList.add(this.worldGenThreadCount); @@ -204,9 +204,9 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan @Override protected IConfigEntry getPresetConfigEntry() { return Config.Client.threadPresetSetting; } - @Override + @Override protected List getPresetEnumList() { return Arrays.asList(EThreadPreset.values()); } - @Override + @Override protected EThreadPreset getCustomPresetEnum() { return EThreadPreset.CUSTOM; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java index e8ef1fef5..b37a9af5d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java @@ -19,197 +19,243 @@ import java.nio.file.Path; * @author coolGi * @version 2023-7-16 */ -public class ConfigFileHandling { +public class ConfigFileHandling +{ private static final Logger LOGGER = ConfigBase.LOGGER; - - public final ConfigBase configBase; + + public final ConfigBase configBase; public final Path ConfigPath; - - public ConfigFileHandling(ConfigBase configBase) { - this.configBase = configBase; - ConfigPath = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class) - .getInstallationDirectory().toPath().resolve("config").resolve(this.configBase.modName+".toml"); - } - - /** Saves the entire config to the file */ - public void saveToFile() { - CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).build(); - if (!Files.exists(ConfigPath)) // Try to check if the config exists - try { - Files.createFile(ConfigPath); - } catch (IOException ex) { - ex.printStackTrace(); - } - - loadConfig(config); - - for (AbstractConfigType entry : this.configBase.entries) { - if (ConfigEntry.class.isAssignableFrom(entry.getClass())) { - createComment((ConfigEntry) entry, config); - saveEntry((ConfigEntry) entry, config); - } - } - - - try { - config.save(); - } catch (Exception e) { - // If it fails to save, crash game - SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Failed to save config at ["+ ConfigPath.toString() +"]", e); - } - config.close(); - } - /** - * Loads the entire config from the file - * @apiNote This overwrites any value currently stored in the config - */ - public void loadFromFile() { - CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).build(); - // Attempt to load the file and if it fails then save config to file - try { - if (Files.exists(ConfigPath)) - config.load(); - else { - saveToFile(); - return; - } - } catch (Exception e) { - e.printStackTrace(); - saveToFile(); - return; - } - - // Load all the entries - for (AbstractConfigType entry : this.configBase.entries) { - if (ConfigEntry.class.isAssignableFrom(entry.getClass())) { - createComment((ConfigEntry) entry, config); - loadEntry((ConfigEntry) entry, config); - } - } - - - try { - config.save(); - } catch (Exception e) { - // If it fails to save, crash game - SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Failed to save config at ["+ ConfigPath.toString() +"]", e); - } - config.close(); - } - - - - - // Save an entry when only given the entry - public void saveEntry(ConfigEntry entry) { - CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).build(); - loadConfig(config); - saveEntry(entry, config); - config.save(); - config.close(); - } - // Save an entry - @SuppressWarnings("unchecked") - public void saveEntry(ConfigEntry entry, CommentedFileConfig workConfig) { - if (!entry.getAppearance().showInFile) return; - if (entry.getTrueValue() == null) - throw new IllegalArgumentException("Entry ["+ entry.getNameWCategory() +"] is null, this may be a problem with ["+ configBase.modName +"]. Please contact the authors"); - - Class originalClass = ConfigTypeConverters.isClassConvertable(entry.getType()); - if (originalClass != null) { - workConfig.set(entry.getNameWCategory(), ConfigTypeConverters.convertToString(originalClass, entry.getTrueValue())); - return; - } - workConfig.set(entry.getNameWCategory(), entry.getTrueValue()); - } - - // Loads an entry when only given the entry - public void loadEntry(ConfigEntry entry) { - CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).autosave().build(); - loadConfig(config); - loadEntry(entry, config); - config.close(); - - } - // Loads an entry - @SuppressWarnings("unchecked") // Suppress due to its always safe - public void loadEntry(ConfigEntry entry, CommentedFileConfig workConfig) { - if (!entry.getAppearance().showInFile) return; - - if (workConfig.contains(entry.getNameWCategory())) { - try { - if (entry.getType().isEnum()) { - entry.setWithoutSaving((T) ( workConfig.getEnum(entry.getNameWCategory(), (Class) entry.getType()))); - return; - } - Class originalClass = ConfigTypeConverters.isClassConvertable(entry.getType()); - if (originalClass != null) { - entry.setWithoutSaving((T) ConfigTypeConverters.convertFromString(originalClass, workConfig.get(entry.getNameWCategory()))); - return; - } - - if (entry.getType() == workConfig.get(entry.getNameWCategory()).getClass()) { // If the types are the same - entry.setWithoutSaving((T) workConfig.get(entry.getNameWCategory())); - entry.clampWithinRange(); - return; - } - - LOGGER.warn("Entry ["+ entry.getNameWCategory() +"] is invalid. Expected " + entry.getType() + " but got " + workConfig.get(entry.getNameWCategory()).getClass() + ". Using default value."); - saveEntry(entry, workConfig); - } catch (Exception e) { + + public ConfigFileHandling(ConfigBase configBase) + { + this.configBase = configBase; + ConfigPath = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class) + .getInstallationDirectory().toPath().resolve("config").resolve(this.configBase.modName + ".toml"); + } + + /** Saves the entire config to the file */ + public void saveToFile() + { + CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).build(); + if (!Files.exists(ConfigPath)) // Try to check if the config exists + try + { + Files.createFile(ConfigPath); + } + catch (IOException ex) + { + ex.printStackTrace(); + } + + loadConfig(config); + + for (AbstractConfigType entry : this.configBase.entries) + { + if (ConfigEntry.class.isAssignableFrom(entry.getClass())) + { + createComment((ConfigEntry) entry, config); + saveEntry((ConfigEntry) entry, config); + } + } + + + try + { + config.save(); + } + catch (Exception e) + { + // If it fails to save, crash game + SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Failed to save config at [" + ConfigPath.toString() + "]", e); + } + config.close(); + } + /** + * Loads the entire config from the file + * + * @apiNote This overwrites any value currently stored in the config + */ + public void loadFromFile() + { + CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).build(); + // Attempt to load the file and if it fails then save config to file + try + { + if (Files.exists(ConfigPath)) + config.load(); + else + { + saveToFile(); + return; + } + } + catch (Exception e) + { + e.printStackTrace(); + saveToFile(); + return; + } + + // Load all the entries + for (AbstractConfigType entry : this.configBase.entries) + { + if (ConfigEntry.class.isAssignableFrom(entry.getClass())) + { + createComment((ConfigEntry) entry, config); + loadEntry((ConfigEntry) entry, config); + } + } + + + try + { + config.save(); + } + catch (Exception e) + { + // If it fails to save, crash game + SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Failed to save config at [" + ConfigPath.toString() + "]", e); + } + config.close(); + } + + + + + // Save an entry when only given the entry + public void saveEntry(ConfigEntry entry) + { + CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).build(); + loadConfig(config); + saveEntry(entry, config); + config.save(); + config.close(); + } + // Save an entry + @SuppressWarnings("unchecked") + public void saveEntry(ConfigEntry entry, CommentedFileConfig workConfig) + { + if (!entry.getAppearance().showInFile) return; + if (entry.getTrueValue() == null) + throw new IllegalArgumentException("Entry [" + entry.getNameWCategory() + "] is null, this may be a problem with [" + configBase.modName + "]. Please contact the authors"); + + Class originalClass = ConfigTypeConverters.isClassConvertable(entry.getType()); + if (originalClass != null) + { + workConfig.set(entry.getNameWCategory(), ConfigTypeConverters.convertToString(originalClass, entry.getTrueValue())); + return; + } + workConfig.set(entry.getNameWCategory(), entry.getTrueValue()); + } + + // Loads an entry when only given the entry + public void loadEntry(ConfigEntry entry) + { + CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).autosave().build(); + loadConfig(config); + loadEntry(entry, config); + config.close(); + + } + // Loads an entry + @SuppressWarnings("unchecked") // Suppress due to its always safe + public void loadEntry(ConfigEntry entry, CommentedFileConfig workConfig) + { + if (!entry.getAppearance().showInFile) return; + + if (workConfig.contains(entry.getNameWCategory())) + { + try + { + if (entry.getType().isEnum()) + { + entry.setWithoutSaving((T) (workConfig.getEnum(entry.getNameWCategory(), (Class) entry.getType()))); + return; + } + Class originalClass = ConfigTypeConverters.isClassConvertable(entry.getType()); + if (originalClass != null) + { + entry.setWithoutSaving((T) ConfigTypeConverters.convertFromString(originalClass, workConfig.get(entry.getNameWCategory()))); + return; + } + + if (entry.getType() == workConfig.get(entry.getNameWCategory()).getClass()) + { // If the types are the same + entry.setWithoutSaving((T) workConfig.get(entry.getNameWCategory())); + entry.clampWithinRange(); + return; + } + + LOGGER.warn("Entry [" + entry.getNameWCategory() + "] is invalid. Expected " + entry.getType() + " but got " + workConfig.get(entry.getNameWCategory()).getClass() + ". Using default value."); + saveEntry(entry, workConfig); + } + catch (Exception e) + { // e.printStackTrace(); - LOGGER.warn("Entry ["+entry.getNameWCategory()+"] had an invalid value when loading the config. Using default value."); - saveEntry(entry, workConfig); - } - } else { - saveEntry(entry, workConfig); - } - } - - // Creates the comment for an entry when only given the entry - public void createComment(ConfigEntry entry) { - CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).autosave().build(); - loadConfig(config); - createComment(entry, config); - config.close(); - } - // Creates a comment for an entry - public void createComment(ConfigEntry entry, CommentedFileConfig workConfig) { - if (!entry.getAppearance().showInFile) - return; - if (entry.getComment() != null) { - workConfig.setComment(entry.getNameWCategory(), " " + entry.getComment().replaceAll("\n", "\n ") + "\n "); - } - } - - - - - /** Does config.load(); but with error checking */ - public void loadConfig(CommentedFileConfig config) { - try { - config.load(); - } catch (Exception e) { - System.out.println("Loading file failed because of this expectation:\n"+e); - try { // Now try remaking the file and loading it - if (!ConfigPath.getParent().toFile().exists()) - Files.createDirectory(ConfigPath.getParent()); - else - Files.deleteIfExists(ConfigPath); - Files.createFile(ConfigPath); - config.load(); - } catch (IOException ex) { - System.out.println("Creating file failed"); - ex.printStackTrace(); - SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Loading file and resetting config file failed at path ["+ConfigPath+"]. Please check the file is ok and you have the permissions", ex); - } - } - } - - - // ========== API (server) STUFF ========== // - /** ALWAYS CLEAR WHEN NOT ON SERVER!!!! */ - // We are not using this stuff, so comment it out for now (if we ever do need it then we can uncomment it) + LOGGER.warn("Entry [" + entry.getNameWCategory() + "] had an invalid value when loading the config. Using default value."); + saveEntry(entry, workConfig); + } + } + else + { + saveEntry(entry, workConfig); + } + } + + // Creates the comment for an entry when only given the entry + public void createComment(ConfigEntry entry) + { + CommentedFileConfig config = CommentedFileConfig.builder(ConfigPath.toFile()).autosave().build(); + loadConfig(config); + createComment(entry, config); + config.close(); + } + // Creates a comment for an entry + public void createComment(ConfigEntry entry, CommentedFileConfig workConfig) + { + if (!entry.getAppearance().showInFile) + return; + if (entry.getComment() != null) + { + workConfig.setComment(entry.getNameWCategory(), " " + entry.getComment().replaceAll("\n", "\n ") + "\n "); + } + } + + + + + /** Does config.load(); but with error checking */ + public void loadConfig(CommentedFileConfig config) + { + try + { + config.load(); + } + catch (Exception e) + { + System.out.println("Loading file failed because of this expectation:\n" + e); + try + { // Now try remaking the file and loading it + if (!ConfigPath.getParent().toFile().exists()) + Files.createDirectory(ConfigPath.getParent()); + else + Files.deleteIfExists(ConfigPath); + Files.createFile(ConfigPath); + config.load(); + } + catch (IOException ex) + { + System.out.println("Creating file failed"); + ex.printStackTrace(); + SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Loading file and resetting config file failed at path [" + ConfigPath + "]. Please check the file is ok and you have the permissions", ex); + } + } + } + + + // ========== API (server) STUFF ========== // + /** ALWAYS CLEAR WHEN NOT ON SERVER!!!! */ + // We are not using this stuff, so comment it out for now (if we ever do need it then we can uncomment it) /* @SuppressWarnings("unchecked") public static void clearApiValues() { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigTypeConverters.java b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigTypeConverters.java index 0ac53df7b..489c9d191 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigTypeConverters.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigTypeConverters.java @@ -13,99 +13,135 @@ import java.util.Map; * * @author coolGi */ -public class ConfigTypeConverters { - // Once you've made a converter add it to here where the first value is the type you want to convert and the 2nd value is the converter - public static final Map, ConverterBase> convertObjects = new HashMap, ConverterBase>() {{ - put(Short.class, new ShortConverter()); - put(Long.class, new LongConverter()); - put(Float.class, new FloatConverter()); - put(Byte.class, new ByteConverter()); - - put(Map.class, new MapConverter()); - }}; - - public static Class isClassConvertable(Class clazz) { - for (int i = 0; i < convertObjects.size(); i++) { - Class selectedClass = (Class) convertObjects.keySet().toArray()[i]; - if (selectedClass.isAssignableFrom(clazz)) - return selectedClass; - } - return null; - } - - public static String convertToString(Class clazz, Object value) { - try { - return convertObjects.get(clazz).convertToString(value); - } catch (Exception e) { - System.out.println("Type [" + clazz.toString() + "] isn't a convertible value in the config file handler"); - return null; - } - } - public static Object convertFromString(Class clazz, String value) { - try { - return convertObjects.get(clazz).convertFromString(value); - } catch (Exception e) { - System.out.println("Type [" + clazz.toString() + "] isn't a convertible value in the config file handler"); - return null; - } - } - - - /** - * The converter should extend this - */ - public static abstract class ConverterBase { - public abstract String convertToString(Object value); - public abstract Object convertFromString(String value); - } - - - - // Some number types are a bit wack with the config parser - // So we just store them as strings - public static class ShortConverter extends ConverterBase { - @Override public String convertToString(Object item) { return ((Short) item).toString(); } - @Override public Short convertFromString(String s) { return Short.valueOf(s); } - } - public static class LongConverter extends ConverterBase { - @Override public String convertToString(Object item) { return ((Long) item).toString(); } - @Override public Long convertFromString(String s) { return Long.valueOf(s); } - } - public static class FloatConverter extends ConverterBase { - @Override public String convertToString(Object item) { return ((Float) item).toString(); } - @Override public Float convertFromString(String s) { return Float.valueOf(s); } - } - public static class ByteConverter extends ConverterBase { - @Override public String convertToString(Object item) { return ((Byte) item).toString(); } - @Override public Byte convertFromString(String s) { return Byte.valueOf(s); } - } - - - - @SuppressWarnings("unchecked") - public static class MapConverter extends ConverterBase { - @Override - public String convertToString(Object item) { - Map mapObject = (Map) item; - Config jsonObject = Config.inMemory(); - - for (int i = 0; i < mapObject.size(); i++) { - jsonObject.add(mapObject.keySet().toArray()[i].toString(), mapObject.get(mapObject.keySet().toArray()[i])); - } - - return JsonFormat.minimalInstance().createWriter().writeToString(jsonObject); - } - - @Override - public Map convertFromString(String s) { - Map map = new HashMap<>(); - - Config jsonObject = Config.inMemory(); - try { - JsonFormat.minimalInstance().createParser().parse(s, jsonObject, ParsingMode.REPLACE); - } catch (Exception e) { e.printStackTrace(); } - - return jsonObject.valueMap(); - } - } +public class ConfigTypeConverters +{ + // Once you've made a converter add it to here where the first value is the type you want to convert and the 2nd value is the converter + public static final Map, ConverterBase> convertObjects = new HashMap, ConverterBase>() + {{ + put(Short.class, new ShortConverter()); + put(Long.class, new LongConverter()); + put(Float.class, new FloatConverter()); + put(Byte.class, new ByteConverter()); + + put(Map.class, new MapConverter()); + }}; + + public static Class isClassConvertable(Class clazz) + { + for (int i = 0; i < convertObjects.size(); i++) + { + Class selectedClass = (Class) convertObjects.keySet().toArray()[i]; + if (selectedClass.isAssignableFrom(clazz)) + return selectedClass; + } + return null; + } + + public static String convertToString(Class clazz, Object value) + { + try + { + return convertObjects.get(clazz).convertToString(value); + } + catch (Exception e) + { + System.out.println("Type [" + clazz.toString() + "] isn't a convertible value in the config file handler"); + return null; + } + } + public static Object convertFromString(Class clazz, String value) + { + try + { + return convertObjects.get(clazz).convertFromString(value); + } + catch (Exception e) + { + System.out.println("Type [" + clazz.toString() + "] isn't a convertible value in the config file handler"); + return null; + } + } + + + /** + * The converter should extend this + */ + public static abstract class ConverterBase + { + public abstract String convertToString(Object value); + public abstract Object convertFromString(String value); + + } + + + + // Some number types are a bit wack with the config parser + // So we just store them as strings + public static class ShortConverter extends ConverterBase + { + @Override public String convertToString(Object item) { return ((Short) item).toString(); } + @Override public Short convertFromString(String s) { return Short.valueOf(s); } + + } + + public static class LongConverter extends ConverterBase + { + @Override public String convertToString(Object item) { return ((Long) item).toString(); } + @Override public Long convertFromString(String s) { return Long.valueOf(s); } + + } + + public static class FloatConverter extends ConverterBase + { + @Override public String convertToString(Object item) { return ((Float) item).toString(); } + @Override public Float convertFromString(String s) { return Float.valueOf(s); } + + } + + public static class ByteConverter extends ConverterBase + { + @Override public String convertToString(Object item) { return ((Byte) item).toString(); } + @Override public Byte convertFromString(String s) { return Byte.valueOf(s); } + + } + + + + @SuppressWarnings("unchecked") + public static class MapConverter extends ConverterBase + { + @Override + public String convertToString(Object item) + { + Map mapObject = (Map) item; + Config jsonObject = Config.inMemory(); + + for (int i = 0; i < mapObject.size(); i++) + { + jsonObject.add(mapObject.keySet().toArray()[i].toString(), mapObject.get(mapObject.keySet().toArray()[i])); + } + + return JsonFormat.minimalInstance().createWriter().writeToString(jsonObject); + } + + @Override + public Map convertFromString(String s) + { + Map map = new HashMap<>(); + + Config jsonObject = Config.inMemory(); + try + { + JsonFormat.minimalInstance().createParser().parse(s, jsonObject, ParsingMode.REPLACE); + } + catch (Exception e) + { + e.printStackTrace(); + } + + return jsonObject.valueMap(); + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/AbstractScreen.java b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/AbstractScreen.java index 687ceef9d..704b2ed4f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/AbstractScreen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/AbstractScreen.java @@ -9,32 +9,35 @@ import java.util.List; * * @author coolGi */ -public abstract class AbstractScreen { - public long minecraftWindow; - public int width; - public int height; - public int scaledWidth; - public int scaledHeight; - public int mouseX = 0; - public int mouseY = 0; - /** Weather it should close when you press the escape key */ - public boolean shouldCloseOnEsc = true; - /** If set to true, the screen would close on the next tick (warning, it closes after tick gets called for a last time) */ - public boolean close = false; - - - /** Called once when the screen is opened */ - public abstract void init(); - /** Called every frame */ - public abstract void render(float delta); - public void tick() {} - - /** Called every time the window gets re-sized */ - public void onResize() {}; - /** What happens when the user closes the screen*/ - public void onClose() {} - - // ---------- Random stuff that might be needed later on ---------- // - /** File dropped into the screen */ - public void onFilesDrop(List files) {} +public abstract class AbstractScreen +{ + public long minecraftWindow; + public int width; + public int height; + public int scaledWidth; + public int scaledHeight; + public int mouseX = 0; + public int mouseY = 0; + /** Weather it should close when you press the escape key */ + public boolean shouldCloseOnEsc = true; + /** If set to true, the screen would close on the next tick (warning, it closes after tick gets called for a last time) */ + public boolean close = false; + + + /** Called once when the screen is opened */ + public abstract void init(); + /** Called every frame */ + public abstract void render(float delta); + public void tick() { } + + /** Called every time the window gets re-sized */ + public void onResize() { } + ; + /** What happens when the user closes the screen */ + public void onClose() { } + + // ---------- Random stuff that might be needed later on ---------- // + /** File dropped into the screen */ + public void onFilesDrop(List files) { } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/ConfigScreen.java b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/ConfigScreen.java index 7cffb7ac4..a43f4891f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/ConfigScreen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/ConfigScreen.java @@ -3,25 +3,29 @@ package com.seibel.distanthorizons.core.config.gui; import javax.swing.*; import java.awt.*; -public class ConfigScreen extends JFrame { - - public ConfigScreen() { - setLayout(new GridBagLayout()); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.weightx = 0.5; - constraints.gridx = 0; - constraints.gridy = 0; - add(new JLabel("Hello World!"), constraints); - } - - - public static void main(String[] args) { - SwingUtilities.invokeLater(() -> { - JFrame frame = new ConfigScreen(); - frame.setSize(300, 200); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setVisible(true); - }); - } +public class ConfigScreen extends JFrame +{ + + public ConfigScreen() + { + setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 0.5; + constraints.gridx = 0; + constraints.gridy = 0; + add(new JLabel("Hello World!"), constraints); + } + + + public static void main(String[] args) + { + SwingUtilities.invokeLater(() -> { + JFrame frame = new ConfigScreen(); + frame.setSize(300, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + }); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/EmbeddedFrameUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/EmbeddedFrameUtil.java index 1cf49ddc7..efa1e189b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/EmbeddedFrameUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/EmbeddedFrameUtil.java @@ -25,120 +25,153 @@ import static org.lwjgl.system.macosx.ObjCRuntime.*; * @author Ran * @author coolGi */ -public final class EmbeddedFrameUtil { - - private static final int JAVA_VERSION; - - private static final JAWT awt; - - static { - Pattern p = Pattern.compile("^(?:1[.])?([1-9][0-9]*)[.-]"); - Matcher m = p.matcher(System.getProperty("java.version")); - - if (!m.find()) { - throw new IllegalStateException("Failed to parse java.version"); - } - - JAVA_VERSION = Integer.parseInt(m.group(1)); - - awt = JAWT.calloc(); - awt.version(JAVA_VERSION < 9 ? JAWT_VERSION_1_4 : JAWT_VERSION_9); - if (!JAWT_GetAWT(awt)) { - throw new RuntimeException("GetAWT failed"); - } - } - - private static String getEmbeddedFrameImpl() { - switch (Platform.get()) { - case LINUX: - return "sun.awt.X11.XEmbeddedFrame"; - case WINDOWS: - return "sun.awt.windows.WEmbeddedFrame"; - case MACOS: - return "sun.lwawt.macosx.CViewEmbeddedFrame"; - default: - throw new IllegalStateException(); - } - } - - private static long getEmbeddedFrameHandle(long window) { - switch (Platform.get()) { - case LINUX: - return glfwGetX11Window(window); - case WINDOWS: - return glfwGetWin32Window(window); - case MACOS: - long objc_msgSend = ObjCRuntime.getLibrary().getFunctionAddress("objc_msgSend"); - return invokePPP(glfwGetCocoaWindow(window), sel_getUid("contentView"), objc_msgSend); - default: - throw new IllegalStateException(); - } - } - - public static Frame embeddedFrameCreate(long window) { - if (JAVA_VERSION < 9) { - try { - @SuppressWarnings("unchecked") - Class EmdeddedFrame = (Class)Class.forName(getEmbeddedFrameImpl()); - Constructor c = EmdeddedFrame.getConstructor(long.class); - - return c.newInstance(getEmbeddedFrameHandle(window)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - return nJAWT_CreateEmbeddedFrame(getEmbeddedFrameHandle(window), awt.CreateEmbeddedFrame()); - } - } - - static void embeddedFrameSynthesizeWindowActivation(Frame embeddedFrame, boolean doActivate) { - if (JAVA_VERSION < 9) { - try { - embeddedFrame - .getClass() - .getMethod("synthesizeWindowActivation", boolean.class) - .invoke(embeddedFrame, doActivate); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - JAWT_SynthesizeWindowActivation(embeddedFrame, doActivate, awt.SynthesizeWindowActivation()); - } - } - - public static void embeddedFrameSetBounds(Frame embeddedFrame, int x, int y, int width, int height) { - if (JAVA_VERSION < 9) { - try { - Method setLocationPrivate = embeddedFrame - .getClass() - .getSuperclass() - .getDeclaredMethod("setBoundsPrivate", int.class, int.class, int.class, int.class); - setLocationPrivate.setAccessible(true); - setLocationPrivate.invoke(embeddedFrame, x, y, width, height); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - JAWT_SetBounds(embeddedFrame, x, y, width, height, awt.SetBounds()); - } - } - - - public static void hideFrame(@NotNull Frame embeddedFrame) { - embeddedFrame.setVisible(false); - embeddedFrameSynthesizeWindowActivation(embeddedFrame, false); - } - - public static void showFrame(@NotNull Frame embeddedFrame) { - embeddedFrameSynthesizeWindowActivation(embeddedFrame, true); - embeddedFrame.setVisible(true); - } - public static void placeAtCenter(Frame embeddedFrame, int windowWidth, int windowHeight, int frameWidth, int frameHeight, float scale) { - float scaleFactor = (100.0F - scale) / 100.0F; - float newWidth = frameWidth * scaleFactor; - float newHeight = frameHeight * scaleFactor; - float newX = (windowWidth - newWidth) / 2F; - float newY = (windowHeight - newHeight) / 2F; - embeddedFrameSetBounds(embeddedFrame, Math.round(newX), Math.round(newY), Math.round(newWidth), Math.round(newHeight)); - } +public final class EmbeddedFrameUtil +{ + + private static final int JAVA_VERSION; + + private static final JAWT awt; + + static + { + Pattern p = Pattern.compile("^(?:1[.])?([1-9][0-9]*)[.-]"); + Matcher m = p.matcher(System.getProperty("java.version")); + + if (!m.find()) + { + throw new IllegalStateException("Failed to parse java.version"); + } + + JAVA_VERSION = Integer.parseInt(m.group(1)); + + awt = JAWT.calloc(); + awt.version(JAVA_VERSION < 9 ? JAWT_VERSION_1_4 : JAWT_VERSION_9); + if (!JAWT_GetAWT(awt)) + { + throw new RuntimeException("GetAWT failed"); + } + } + + private static String getEmbeddedFrameImpl() + { + switch (Platform.get()) + { + case LINUX: + return "sun.awt.X11.XEmbeddedFrame"; + case WINDOWS: + return "sun.awt.windows.WEmbeddedFrame"; + case MACOS: + return "sun.lwawt.macosx.CViewEmbeddedFrame"; + default: + throw new IllegalStateException(); + } + } + + private static long getEmbeddedFrameHandle(long window) + { + switch (Platform.get()) + { + case LINUX: + return glfwGetX11Window(window); + case WINDOWS: + return glfwGetWin32Window(window); + case MACOS: + long objc_msgSend = ObjCRuntime.getLibrary().getFunctionAddress("objc_msgSend"); + return invokePPP(glfwGetCocoaWindow(window), sel_getUid("contentView"), objc_msgSend); + default: + throw new IllegalStateException(); + } + } + + public static Frame embeddedFrameCreate(long window) + { + if (JAVA_VERSION < 9) + { + try + { + @SuppressWarnings("unchecked") + Class EmdeddedFrame = (Class) Class.forName(getEmbeddedFrameImpl()); + Constructor c = EmdeddedFrame.getConstructor(long.class); + + return c.newInstance(getEmbeddedFrameHandle(window)); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + else + { + return nJAWT_CreateEmbeddedFrame(getEmbeddedFrameHandle(window), awt.CreateEmbeddedFrame()); + } + } + + static void embeddedFrameSynthesizeWindowActivation(Frame embeddedFrame, boolean doActivate) + { + if (JAVA_VERSION < 9) + { + try + { + embeddedFrame + .getClass() + .getMethod("synthesizeWindowActivation", boolean.class) + .invoke(embeddedFrame, doActivate); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + else + { + JAWT_SynthesizeWindowActivation(embeddedFrame, doActivate, awt.SynthesizeWindowActivation()); + } + } + + public static void embeddedFrameSetBounds(Frame embeddedFrame, int x, int y, int width, int height) + { + if (JAVA_VERSION < 9) + { + try + { + Method setLocationPrivate = embeddedFrame + .getClass() + .getSuperclass() + .getDeclaredMethod("setBoundsPrivate", int.class, int.class, int.class, int.class); + setLocationPrivate.setAccessible(true); + setLocationPrivate.invoke(embeddedFrame, x, y, width, height); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + else + { + JAWT_SetBounds(embeddedFrame, x, y, width, height, awt.SetBounds()); + } + } + + + public static void hideFrame(@NotNull Frame embeddedFrame) + { + embeddedFrame.setVisible(false); + embeddedFrameSynthesizeWindowActivation(embeddedFrame, false); + } + + public static void showFrame(@NotNull Frame embeddedFrame) + { + embeddedFrameSynthesizeWindowActivation(embeddedFrame, true); + embeddedFrame.setVisible(true); + } + public static void placeAtCenter(Frame embeddedFrame, int windowWidth, int windowHeight, int frameWidth, int frameHeight, float scale) + { + float scaleFactor = (100.0F - scale) / 100.0F; + float newWidth = frameWidth * scaleFactor; + float newHeight = frameHeight * scaleFactor; + float newX = (windowWidth - newWidth) / 2F; + float newY = (windowHeight - newHeight) / 2F; + embeddedFrameSetBounds(embeddedFrame, Math.round(newX), Math.round(newY), Math.round(newWidth), Math.round(newHeight)); + } + } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/JavaScreenHandlerScreen.java b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/JavaScreenHandlerScreen.java index 418995e78..2985ffb6d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/JavaScreenHandlerScreen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/JavaScreenHandlerScreen.java @@ -8,61 +8,74 @@ import java.awt.*; /** * */ -public class JavaScreenHandlerScreen extends AbstractScreen { - public static Frame frame; - public static boolean firstRun = true; - public final Component jComponent; - - static { - // Required to run this - System.setProperty("java.awt.headless", "false"); - } - - public JavaScreenHandlerScreen(@NotNull Component component) { - this.jComponent = component; - } - - @Override - public void init() { - if (firstRun) - frame = EmbeddedFrameUtil.embeddedFrameCreate(this.minecraftWindow); // Don't call this multiple times - - frame.add(jComponent); - - if (firstRun) { - EmbeddedFrameUtil.embeddedFrameSetBounds(frame, 0, 0, this.width, this.height); - firstRun = false; - } else - EmbeddedFrameUtil.showFrame(frame); - } - - /** A testing/debug screen */ - public static class ExampleScreen extends JComponent { - public ExampleScreen() { - setLayout(new GridBagLayout()); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.weightx = 0.5; - constraints.gridx = 0; - constraints.gridy = 0; - add(new JLabel("Hello World!"), constraints); - } - } - - - @Override - public void render(float delta) { - // TODO: Make screen only update on this being called - } - - @Override - public void onResize() { - EmbeddedFrameUtil.embeddedFrameSetBounds(frame, 0, 0, this.width, this.height); - } - - @Override - public void onClose() { - frame.remove(jComponent); - EmbeddedFrameUtil.hideFrame(frame); - } +public class JavaScreenHandlerScreen extends AbstractScreen +{ + public static Frame frame; + public static boolean firstRun = true; + public final Component jComponent; + + static + { + // Required to run this + System.setProperty("java.awt.headless", "false"); + } + + public JavaScreenHandlerScreen(@NotNull Component component) + { + this.jComponent = component; + } + + @Override + public void init() + { + if (firstRun) + frame = EmbeddedFrameUtil.embeddedFrameCreate(this.minecraftWindow); // Don't call this multiple times + + frame.add(jComponent); + + if (firstRun) + { + EmbeddedFrameUtil.embeddedFrameSetBounds(frame, 0, 0, this.width, this.height); + firstRun = false; + } + else + EmbeddedFrameUtil.showFrame(frame); + } + + /** A testing/debug screen */ + public static class ExampleScreen extends JComponent + { + public ExampleScreen() + { + setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 0.5; + constraints.gridx = 0; + constraints.gridy = 0; + add(new JLabel("Hello World!"), constraints); + } + + } + + + @Override + public void render(float delta) + { + // TODO: Make screen only update on this being called + } + + @Override + public void onResize() + { + EmbeddedFrameUtil.embeddedFrameSetBounds(frame, 0, 0, this.width, this.height); + } + + @Override + public void onClose() + { + frame.remove(jComponent); + EmbeddedFrameUtil.hideFrame(frame); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java index 8c38429f7..5035a4726 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java @@ -14,89 +14,99 @@ import java.nio.ByteOrder; /** * @author coolGi */ -public class OpenGLConfigScreen extends AbstractScreen { - ShaderProgram basicShader; - GLVertexBuffer sameContextBuffer; - GLVertexBuffer sharedContextBuffer; - VertexAttribute va; - - @Override - public void init() { - System.out.println("init"); - - va = VertexAttribute.create(); - va.bind(); - // Pos - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - // Color - va.setVertexAttribute(0, 1, VertexAttribute.VertexPointer.addVec4Pointer(false)); - va.completeAndCheck(Float.BYTES * 6); - basicShader = new ShaderProgram("shaders/test/vert.vert", "shaders/test/frag.frag", - "fragColor", new String[]{"vPosition", "color"}); - createBuffer(); - } - - // Render a square with uv color - private static final float[] vertices = { - // PosX,Y, ColorR,G,B,A - -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.4f, -0.4f, 1.0f, 0.0f, 0.0f, 1.0f, - 0.3f, 0.3f, 1.0f, 1.0f, 0.0f, 0.0f, - -0.2f, 0.2f, 0.0f, 1.0f, 1.0f, 1.0f - }; - - private static GLVertexBuffer createTextingBuffer() { - ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES); - // Fill buffer with the vertices. - buffer = buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(vertices); - buffer.rewind(); - GLVertexBuffer vbo = new GLVertexBuffer(false); - vbo.bind(); - vbo.uploadBuffer(buffer, 4, EGpuUploadMethod.DATA, vertices.length * Float.BYTES); - return vbo; - } - - private void createBuffer() { - GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); - GLProxy.ensureAllGLJobCompleted(); - sameContextBuffer = createTextingBuffer(); - } - - @Override - public void render(float delta) { - System.out.println("Updated config screen with the delta of " + delta); - - GLState state = new GLState(); +public class OpenGLConfigScreen extends AbstractScreen +{ + ShaderProgram basicShader; + GLVertexBuffer sameContextBuffer; + GLVertexBuffer sharedContextBuffer; + VertexAttribute va; + + @Override + public void init() + { + System.out.println("init"); + + va = VertexAttribute.create(); + va.bind(); + // Pos + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + // Color + va.setVertexAttribute(0, 1, VertexAttribute.VertexPointer.addVec4Pointer(false)); + va.completeAndCheck(Float.BYTES * 6); + basicShader = new ShaderProgram("shaders/test/vert.vert", "shaders/test/frag.frag", + "fragColor", new String[]{"vPosition", "color"}); + createBuffer(); + } + + // Render a square with uv color + private static final float[] vertices = { + // PosX,Y, ColorR,G,B,A + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, + 0.4f, -0.4f, 1.0f, 0.0f, 0.0f, 1.0f, + 0.3f, 0.3f, 1.0f, 1.0f, 0.0f, 0.0f, + -0.2f, 0.2f, 0.0f, 1.0f, 1.0f, 1.0f + }; + + private static GLVertexBuffer createTextingBuffer() + { + ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES); + // Fill buffer with the vertices. + buffer = buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(vertices); + buffer.rewind(); + GLVertexBuffer vbo = new GLVertexBuffer(false); + vbo.bind(); + vbo.uploadBuffer(buffer, 4, EGpuUploadMethod.DATA, vertices.length * Float.BYTES); + return vbo; + } + + private void createBuffer() + { + GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); + GLProxy.ensureAllGLJobCompleted(); + sameContextBuffer = createTextingBuffer(); + } + + @Override + public void render(float delta) + { + System.out.println("Updated config screen with the delta of " + delta); + + GLState state = new GLState(); // GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - GL32.glViewport(0,0, width, height); - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); - GL32.glDisable(GL32.GL_CULL_FACE); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_STENCIL_TEST); - GL32.glDisable(GL32.GL_BLEND); - //GL32.glDisable(GL32.GL_SCISSOR_TEST); - - basicShader.bind(); - va.bind(); - - // Switch between the two buffers per second - if (System.currentTimeMillis() % 2000 < 1000) { - sameContextBuffer.bind(); - va.bindBufferToAllBindingPoint(sameContextBuffer.getId()); - } else { - sameContextBuffer.bind(); - va.bindBufferToAllBindingPoint(sharedContextBuffer.getId()); - } - // Render the square - GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4); - GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); - - state.restore(); - } - - @Override - public void tick() { - System.out.println("Ticked"); - } + GL32.glViewport(0, 0, width, height); + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); + GL32.glDisable(GL32.GL_CULL_FACE); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_STENCIL_TEST); + GL32.glDisable(GL32.GL_BLEND); + //GL32.glDisable(GL32.GL_SCISSOR_TEST); + + basicShader.bind(); + va.bind(); + + // Switch between the two buffers per second + if (System.currentTimeMillis() % 2000 < 1000) + { + sameContextBuffer.bind(); + va.bindBufferToAllBindingPoint(sameContextBuffer.getId()); + } + else + { + sameContextBuffer.bind(); + va.bindBufferToAllBindingPoint(sharedContextBuffer.getId()); + } + // Render the square + GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4); + GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); + + state.restore(); + } + + @Override + public void tick() + { + System.out.println("Ticked"); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/ConfigChangeListener.java b/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/ConfigChangeListener.java index 25ee5ce67..048b343f7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/ConfigChangeListener.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/ConfigChangeListener.java @@ -9,7 +9,7 @@ import java.util.function.Consumer; * A basic {@link IConfigListener} that will fire a {@link Consumer} * when the value changes from the value the config started with * when this object was created. - * + * * @param the config value type */ public class ConfigChangeListener implements IConfigListener, Closeable @@ -47,9 +47,9 @@ public class ConfigChangeListener implements IConfigListener, Closeable - /** + /** * Removes the config event listener.
- * Must be fired to prevent memory leaks. + * Must be fired to prevent memory leaks. */ @Override public void close() { this.configEntry.removeListener(this); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java b/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java index f7f2f6a08..20749748c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java @@ -5,7 +5,7 @@ public interface IConfigListener /** Called whenever the value is set (including in core DH code) */ void onConfigValueSet(); - /** + /** * TODO not implemented * Called whenever the value is changed through the UI (only when the done button is pressed) */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/AbstractConfigType.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/AbstractConfigType.java index 3d71f227c..218d4bcc4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/AbstractConfigType.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/AbstractConfigType.java @@ -8,68 +8,83 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance * * @author coolGi */ -public abstract class AbstractConfigType { // The S is the class that is extending this - public String category = ""; // This should only be set once in the init - public String name; // This should only be set once in the init - protected T value; - public ConfigBase configBase; - - public Object guiValue; // This is a storage variable something like the gui can use - - protected EConfigEntryAppearance appearance; - - protected AbstractConfigType(EConfigEntryAppearance appearance, T value) { - this.appearance = appearance; - this.value = value; - } - - - /** Gets the value */ - public T get() { - return this.value; - } - /** Sets the value */ - public void set(T newValue) { - this.value = newValue; - } - - public EConfigEntryAppearance getAppearance() { - return appearance; - } - public void setAppearance(EConfigEntryAppearance newAppearance) { - this.appearance = newAppearance; - } - - - public String getCategory() { - return this.category; - } - public String getName() { - return this.name; - } - public String getNameWCategory() { - return (this.category.isEmpty() ? "" : this.category + ".") + this.name; - } - - - // Gets the class of T - public Class getType() { - return value.getClass(); - } - - protected static abstract class Builder { - protected EConfigEntryAppearance tmpAppearance = EConfigEntryAppearance.ALL; - protected T tmpValue; - - - // Put this into your own builder - public S setAppearance(EConfigEntryAppearance newAppearance) { - this.tmpAppearance = newAppearance; - return (S) this; - } - public S set(T newValue) { - this.tmpValue = newValue; - return (S) this; - } - } +public abstract class AbstractConfigType +{ // The S is the class that is extending this + public String category = ""; // This should only be set once in the init + public String name; // This should only be set once in the init + protected T value; + public ConfigBase configBase; + + public Object guiValue; // This is a storage variable something like the gui can use + + protected EConfigEntryAppearance appearance; + + protected AbstractConfigType(EConfigEntryAppearance appearance, T value) + { + this.appearance = appearance; + this.value = value; + } + + + /** Gets the value */ + public T get() + { + return this.value; + } + /** Sets the value */ + public void set(T newValue) + { + this.value = newValue; + } + + public EConfigEntryAppearance getAppearance() + { + return appearance; + } + public void setAppearance(EConfigEntryAppearance newAppearance) + { + this.appearance = newAppearance; + } + + + public String getCategory() + { + return this.category; + } + public String getName() + { + return this.name; + } + public String getNameWCategory() + { + return (this.category.isEmpty() ? "" : this.category + ".") + this.name; + } + + + // Gets the class of T + public Class getType() + { + return value.getClass(); + } + + protected static abstract class Builder + { + protected EConfigEntryAppearance tmpAppearance = EConfigEntryAppearance.ALL; + protected T tmpValue; + + + // Put this into your own builder + public S setAppearance(EConfigEntryAppearance newAppearance) + { + this.tmpAppearance = newAppearance; + return (S) this; + } + public S set(T newValue) + { + this.tmpValue = newValue; + return (S) this; + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigCategory.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigCategory.java index 5197590f8..07d5dea9a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigCategory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigCategory.java @@ -8,41 +8,51 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance * * @author coolGi */ -public class ConfigCategory extends AbstractConfigType { - /** This should not be set by anything other than the config system itself */ - public String destination; // Where the category goes to - - private ConfigCategory(EConfigEntryAppearance appearance, Class value, String destination) { - super(appearance, value); - this.destination = destination; - } - - public String getDestination() { - return this.destination; - } - - @Override - @Deprecated - /** Use get() instead for category */ - public Class getType() { - return value; - } - - public static class Builder extends AbstractConfigType.Builder { - private String tmpDestination = null; - - public Builder setDestination(String newDestination) { - this.tmpDestination = newDestination; - return this; - } - - public Builder setAppearance(EConfigEntryAppearance newAppearance) { - this.tmpAppearance = newAppearance; - return this; - } - - public ConfigCategory build() { - return new ConfigCategory(tmpAppearance, tmpValue, tmpDestination); - } - } +public class ConfigCategory extends AbstractConfigType +{ + /** This should not be set by anything other than the config system itself */ + public String destination; // Where the category goes to + + private ConfigCategory(EConfigEntryAppearance appearance, Class value, String destination) + { + super(appearance, value); + this.destination = destination; + } + + public String getDestination() + { + return this.destination; + } + + @Override + @Deprecated + /** Use get() instead for category */ + public Class getType() + { + return value; + } + + public static class Builder extends AbstractConfigType.Builder + { + private String tmpDestination = null; + + public Builder setDestination(String newDestination) + { + this.tmpDestination = newDestination; + return this; + } + + public Builder setAppearance(EConfigEntryAppearance newAppearance) + { + this.tmpAppearance = newAppearance; + return this; + } + + public ConfigCategory build() + { + return new ConfigCategory(tmpAppearance, tmpValue, tmpDestination); + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java index 218aacbd3..f768ffb13 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java @@ -19,258 +19,265 @@ import java.util.Arrays; */ public class ConfigEntry extends AbstractConfigType> implements IConfigEntry { - private final T defaultValue; - private String comment; - private T min; - private T max; - private final ArrayList listenerList; - - // API control // - /** - * If true this config can be controlled by the API
- * and any get() method calls will return the apiValue if it is set. - */ - public final boolean allowApiOverride; - private T apiValue; - - private final EConfigEntryPerformance performance; - - - /** Creates the entry */ - private ConfigEntry(EConfigEntryAppearance appearance, T value, String comment, T min, T max, boolean allowApiOverride, EConfigEntryPerformance performance, ArrayList listenerList) + private final T defaultValue; + private String comment; + private T min; + private T max; + private final ArrayList listenerList; + + // API control // + /** + * If true this config can be controlled by the API
+ * and any get() method calls will return the apiValue if it is set. + */ + public final boolean allowApiOverride; + private T apiValue; + + private final EConfigEntryPerformance performance; + + + /** Creates the entry */ + private ConfigEntry(EConfigEntryAppearance appearance, T value, String comment, T min, T max, boolean allowApiOverride, EConfigEntryPerformance performance, ArrayList listenerList) { - super(appearance, value); - - this.defaultValue = value; - this.comment = comment; - this.min = min; - this.max = max; - this.allowApiOverride = allowApiOverride; - this.performance = performance; - this.listenerList = listenerList; - } + super(appearance, value); + + this.defaultValue = value; + this.comment = comment; + this.min = min; + this.max = max; + this.allowApiOverride = allowApiOverride; + this.performance = performance; + this.listenerList = listenerList; + } - /** Gets the default value of the option */ + /** Gets the default value of the option */ @Override public T getDefaultValue() { return this.defaultValue; } @Override - public void setApiValue(T newApiValue) + public void setApiValue(T newApiValue) { this.apiValue = newApiValue; this.listenerList.forEach(IConfigListener::onConfigValueSet); } @Override public T getApiValue() { return this.apiValue; } - @Override + @Override public boolean getAllowApiOverride() { return this.allowApiOverride; } - @Override - public void set(T newValue) + @Override + public void set(T newValue) { - super.set(newValue); - this.save(); - this.listenerList.forEach(IConfigListener::onConfigValueSet); - } - public void uiSet(T newValue) + super.set(newValue); + this.save(); + this.listenerList.forEach(IConfigListener::onConfigValueSet); + } + public void uiSet(T newValue) { - this.set(newValue); - this.listenerList.forEach(IConfigListener::onUiModify); - } - @Override - public T get() + this.set(newValue); + this.listenerList.forEach(IConfigListener::onUiModify); + } + @Override + public T get() { - if (allowApiOverride && apiValue != null) + if (allowApiOverride && apiValue != null) { return apiValue; } - return super.get(); - } + return super.get(); + } @Override - public T getTrueValue() { - return super.get(); - } - - /** Sets the value without saving */ + public T getTrueValue() + { + return super.get(); + } + + /** Sets the value without saving */ @Override - public void setWithoutSaving(T newValue) + public void setWithoutSaving(T newValue) { super.set(newValue); this.listenerList.forEach(IConfigListener::onConfigValueSet); } - - /** Gets the min value */ - @Override - public T getMin() { return this.min; } - /** Sets the min value */ - @Override - public void setMin(T newMin) { this.min = newMin; } - /** Gets the max value */ - @Override - public T getMax() { return this.max; } - /** Sets the max value */ - @Override - public void setMax(T newMax) { this.max = newMax; } - /** Sets the min and max within a single setter */ - @Override - public void setMinMax(T newMin, T newMax) { - this.setMin(newMin); - this.setMax(newMax); - } - - /** - * Clamps the value within the set range - * @apiNote This does not save the value - */ - public void clampWithinRange() { this.clampWithinRange(this.min, this.max); } - /** - * Clamps the value within a set range - * - * @param min The minimum that the value can be - * @param max The maximum that the value can be - * @apiNote This does not save the value - */ - @SuppressWarnings("unchecked") // Suppress due to its always safe - public void clampWithinRange(T min, T max) { - byte validness = this.isValid(min, max); - if (validness == -1) this.value = (T) NumberUtil.getMinimum(this.value.getClass()); - if (validness == 1) this.value = (T) NumberUtil.getMaximum(this.value.getClass()); - } - - @Override - public String getComment() { return this.comment; } - @Override - public void setComment(String newComment) { this.comment = newComment; } - - /** Gets the performance impact of an option */ - public EConfigEntryPerformance getPerformance() { return this.performance; } - - public void addListener(IConfigListener newListener) { this.listenerList.add(newListener); } - public void removeListener(IConfigListener oldListener) { this.listenerList.remove(oldListener); } - public void clearListeners() { this.listenerList.clear(); } - public ArrayList getListeners() { return this.listenerList; } - /** Replaces the listener list */ - public void setListeners(ArrayList newListeners) - { - this.listenerList.clear(); - this.listenerList.addAll(newListeners); - } - public void setListeners(IConfigListener... newListeners) { this.listenerList.addAll(Arrays.asList(newListeners)); } - - - /** - * Checks if the option is valid - * - * @return 0 == valid - *

2 == invalid - *

1 == number too high - *

-1 == number too low - */ + /** Gets the min value */ @Override - public byte isValid() { return isValid(this.value, this.min, this.max); } - /** - * Checks if a new value is valid - * - * @param value Value that is being checked whether valid - * @return 0 == valid - *

2 == invalid - *

1 == number too high - *

-1 == number too low - */ - @Override - public byte isValid(T value) { return this.isValid(value, this.min, this.max); } - /** - * Checks if a new value is valid - * - * @param min The minimum that the value can be - * @param max The maximum that the value can be - * @return 0 == valid - *

2 == invalid - *

1 == number too high - *

-1 == number too low - */ - public byte isValid(T min, T max) { return this.isValid(this.value, min, max); } - /** - * Checks if a new value is valid - * - * @param value Value that is being checked whether valid - * @param min The minimum that the value can be - * @param max The maximum that the value can be - * @return 0 == valid - *

2 == invalid - *

1 == number too high - *

-1 == number too low - */ - public byte isValid(T value, T min, T max) { - if (this.configBase.disableMinMax) - return 0; - - if (value == null || this.value == null || value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid - return 2; - if (Number.class.isAssignableFrom(value.getClass())) { // Only check min max if it is a number - if (max != null && NumberUtil.greaterThan((Number) value, (Number) max)) - return 1; - if (min != null && NumberUtil.lessThan((Number) value, (Number) min)) - return -1; - - return 0; - } - return 0; - } - - /** This should normally not be called since set() automatically calls this */ - public void save() { configBase.configFileINSTANCE.saveEntry(this); } - /** This should normally not be called except for special circumstances */ - public void load() { configBase.configFileINSTANCE.loadEntry(this); } + public T getMin() { return this.min; } + /** Sets the min value */ + @Override + public void setMin(T newMin) { this.min = newMin; } + /** Gets the max value */ + @Override + public T getMax() { return this.max; } + /** Sets the max value */ + @Override + public void setMax(T newMax) { this.max = newMax; } + /** Sets the min and max within a single setter */ + @Override + public void setMinMax(T newMin, T newMax) + { + this.setMin(newMin); + this.setMax(newMax); + } + + /** + * Clamps the value within the set range + * + * @apiNote This does not save the value + */ + public void clampWithinRange() { this.clampWithinRange(this.min, this.max); } + /** + * Clamps the value within a set range + * + * @param min The minimum that the value can be + * @param max The maximum that the value can be + * @apiNote This does not save the value + */ + @SuppressWarnings("unchecked") // Suppress due to its always safe + public void clampWithinRange(T min, T max) + { + byte validness = this.isValid(min, max); + if (validness == -1) this.value = (T) NumberUtil.getMinimum(this.value.getClass()); + if (validness == 1) this.value = (T) NumberUtil.getMaximum(this.value.getClass()); + } + + @Override + public String getComment() { return this.comment; } + @Override + public void setComment(String newComment) { this.comment = newComment; } + + /** Gets the performance impact of an option */ + public EConfigEntryPerformance getPerformance() { return this.performance; } + + public void addListener(IConfigListener newListener) { this.listenerList.add(newListener); } + public void removeListener(IConfigListener oldListener) { this.listenerList.remove(oldListener); } + + public void clearListeners() { this.listenerList.clear(); } + public ArrayList getListeners() { return this.listenerList; } + /** Replaces the listener list */ + public void setListeners(ArrayList newListeners) + { + this.listenerList.clear(); + this.listenerList.addAll(newListeners); + } + public void setListeners(IConfigListener... newListeners) { this.listenerList.addAll(Arrays.asList(newListeners)); } + + + /** + * Checks if the option is valid + * + * @return 0 == valid + *

2 == invalid + *

1 == number too high + *

-1 == number too low + */ + @Override + public byte isValid() { return isValid(this.value, this.min, this.max); } + /** + * Checks if a new value is valid + * + * @param value Value that is being checked whether valid + * @return 0 == valid + *

2 == invalid + *

1 == number too high + *

-1 == number too low + */ + @Override + public byte isValid(T value) { return this.isValid(value, this.min, this.max); } + /** + * Checks if a new value is valid + * + * @param min The minimum that the value can be + * @param max The maximum that the value can be + * @return 0 == valid + *

2 == invalid + *

1 == number too high + *

-1 == number too low + */ + public byte isValid(T min, T max) { return this.isValid(this.value, min, max); } + /** + * Checks if a new value is valid + * + * @param value Value that is being checked whether valid + * @param min The minimum that the value can be + * @param max The maximum that the value can be + * @return 0 == valid + *

2 == invalid + *

1 == number too high + *

-1 == number too low + */ + public byte isValid(T value, T min, T max) + { + if (this.configBase.disableMinMax) + return 0; + + if (value == null || this.value == null || value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid + return 2; + if (Number.class.isAssignableFrom(value.getClass())) + { // Only check min max if it is a number + if (max != null && NumberUtil.greaterThan((Number) value, (Number) max)) + return 1; + if (min != null && NumberUtil.lessThan((Number) value, (Number) min)) + return -1; + + return 0; + } + return 0; + } + + /** This should normally not be called since set() automatically calls this */ + public void save() { configBase.configFileINSTANCE.saveEntry(this); } + /** This should normally not be called except for special circumstances */ + public void load() { configBase.configFileINSTANCE.loadEntry(this); } @Override public boolean equals(IConfigEntry obj) { return obj.getClass() == ConfigEntry.class && equals((ConfigEntry) obj); } - /** Is the value of this equal to another */ - public boolean equals(ConfigEntry obj) { - // Can all of this just be "return this.value.equals(obj.value)"? - - if (Number.class.isAssignableFrom(this.value.getClass())) - return this.value == obj.value; - else - return this.value.equals(obj.value); - } - - - public static class Builder extends AbstractConfigType.Builder> + /** Is the value of this equal to another */ + public boolean equals(ConfigEntry obj) { - private String tmpComment = null; - private T tmpMin = null; - private T tmpMax = null; - private boolean tmpUseApiOverwrite = true; - private EConfigEntryPerformance tmpPerformance = EConfigEntryPerformance.DONT_SHOW; - protected ArrayList tmpIConfigListener = new ArrayList<>(); - - public Builder comment(String newComment) + // Can all of this just be "return this.value.equals(obj.value)"? + + if (Number.class.isAssignableFrom(this.value.getClass())) + return this.value == obj.value; + else + return this.value.equals(obj.value); + } + + + public static class Builder extends AbstractConfigType.Builder> + { + private String tmpComment = null; + private T tmpMin = null; + private T tmpMax = null; + private boolean tmpUseApiOverwrite = true; + private EConfigEntryPerformance tmpPerformance = EConfigEntryPerformance.DONT_SHOW; + protected ArrayList tmpIConfigListener = new ArrayList<>(); + + public Builder comment(String newComment) { this.tmpComment = newComment; return this; } - - /** Allows most values to be set by 1 setter */ - public Builder setMinDefaultMax(T newMin, T newDefault, T newMax) + + /** Allows most values to be set by 1 setter */ + public Builder setMinDefaultMax(T newMin, T newDefault, T newMax) { this.set(newDefault); this.setMinMax(newMin, newMax); return this; } - - public Builder setMinMax(T newMin, T newMax) + + public Builder setMinMax(T newMin, T newMax) { this.tmpMin = newMin; this.tmpMax = newMax; return this; } - - public Builder setMin(T newMin) + + public Builder setMin(T newMin) { this.tmpMin = newMin; return this; @@ -281,20 +288,20 @@ public class ConfigEntry extends AbstractConfigType> implem this.tmpMax = newMax; return this; } - - public Builder setUseApiOverwrite(boolean newUseApiOverwrite) + + public Builder setUseApiOverwrite(boolean newUseApiOverwrite) { this.tmpUseApiOverwrite = newUseApiOverwrite; return this; } - - public Builder setPerformance(EConfigEntryPerformance newPerformance) + + public Builder setPerformance(EConfigEntryPerformance newPerformance) { this.tmpPerformance = newPerformance; return this; } - - public Builder replaceListener(ArrayList newConfigListener) + + public Builder replaceListener(ArrayList newConfigListener) { this.tmpIConfigListener = newConfigListener; return this; @@ -317,13 +324,14 @@ public class ConfigEntry extends AbstractConfigType> implem this.tmpIConfigListener.clear(); return this; } - - - - public ConfigEntry build() + + + + public ConfigEntry build() { return new ConfigEntry<>(this.tmpAppearance, this.tmpValue, this.tmpComment, this.tmpMin, this.tmpMax, this.tmpUseApiOverwrite, this.tmpPerformance, this.tmpIConfigListener); - } + } - } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java index debfb97d9..b4c8f275b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java @@ -8,29 +8,36 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance * * @author coolGi */ -public class ConfigLinkedEntry extends AbstractConfigType { - public ConfigLinkedEntry(AbstractConfigType value) { - super(EConfigEntryAppearance.ONLY_IN_GUI, value); - } - - /** Appearance shouldn't be changed */ - @Override - public void setAppearance(EConfigEntryAppearance newAppearance) {} - - /** Value shouldn't be changed after creation */ - @Override - public void set(AbstractConfigType newValue) {} - - - public static class Builder extends AbstractConfigType.Builder { - /** Appearance shouldn't be changed */ - @Override - public Builder setAppearance(EConfigEntryAppearance newAppearance) { - return this; - } - - public ConfigLinkedEntry build() { - return new ConfigLinkedEntry(this.tmpValue); - } - } +public class ConfigLinkedEntry extends AbstractConfigType +{ + public ConfigLinkedEntry(AbstractConfigType value) + { + super(EConfigEntryAppearance.ONLY_IN_GUI, value); + } + + /** Appearance shouldn't be changed */ + @Override + public void setAppearance(EConfigEntryAppearance newAppearance) { } + + /** Value shouldn't be changed after creation */ + @Override + public void set(AbstractConfigType newValue) { } + + + public static class Builder extends AbstractConfigType.Builder + { + /** Appearance shouldn't be changed */ + @Override + public Builder setAppearance(EConfigEntryAppearance newAppearance) + { + return this; + } + + public ConfigLinkedEntry build() + { + return new ConfigLinkedEntry(this.tmpValue); + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIButton.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIButton.java index 07f56fd77..d96afea82 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIButton.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIButton.java @@ -2,24 +2,32 @@ package com.seibel.distanthorizons.core.config.types; import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance; -public class ConfigUIButton extends AbstractConfigType { - public ConfigUIButton(Runnable runnable) { - super(EConfigEntryAppearance.ONLY_IN_GUI, runnable); - } - - public void runAction() { - new Thread(this.value).start(); - } - - public static class Builder extends AbstractConfigType.Builder { - /** Appearance shouldn't be changed */ - @Override - public Builder setAppearance(EConfigEntryAppearance newAppearance) { - return this; - } - - public ConfigUIButton build() { - return new ConfigUIButton(this.tmpValue); - } - } +public class ConfigUIButton extends AbstractConfigType +{ + public ConfigUIButton(Runnable runnable) + { + super(EConfigEntryAppearance.ONLY_IN_GUI, runnable); + } + + public void runAction() + { + new Thread(this.value).start(); + } + + public static class Builder extends AbstractConfigType.Builder + { + /** Appearance shouldn't be changed */ + @Override + public Builder setAppearance(EConfigEntryAppearance newAppearance) + { + return this; + } + + public ConfigUIButton build() + { + return new ConfigUIButton(this.tmpValue); + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIComment.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIComment.java index c0baf1e1d..991258db3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIComment.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigUIComment.java @@ -7,34 +7,42 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance * * @author coolGi */ -public class ConfigUIComment extends AbstractConfigType { - public ConfigUIComment() { - super(EConfigEntryAppearance.ONLY_IN_GUI, ""); - } - - /** Appearance shouldn't be changed */ - @Override - public void setAppearance(EConfigEntryAppearance newAppearance) {} - - /** Pointless to set the value */ - @Override - public void set(String newValue) {} - - public static class Builder extends AbstractConfigType.Builder { - /** Appearance shouldn't be changed */ - @Override - public Builder setAppearance(EConfigEntryAppearance newAppearance) { - return this; - } - - /** Pointless to set the value */ - @Override - public Builder set(String newValue) { - return this; - } - - public ConfigUIComment build() { - return new ConfigUIComment(); - } - } +public class ConfigUIComment extends AbstractConfigType +{ + public ConfigUIComment() + { + super(EConfigEntryAppearance.ONLY_IN_GUI, ""); + } + + /** Appearance shouldn't be changed */ + @Override + public void setAppearance(EConfigEntryAppearance newAppearance) { } + + /** Pointless to set the value */ + @Override + public void set(String newValue) { } + + public static class Builder extends AbstractConfigType.Builder + { + /** Appearance shouldn't be changed */ + @Override + public Builder setAppearance(EConfigEntryAppearance newAppearance) + { + return this; + } + + /** Pointless to set the value */ + @Override + public Builder set(String newValue) + { + return this; + } + + public ConfigUIComment build() + { + return new ConfigUIComment(); + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryAppearance.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryAppearance.java index d4e40f27c..f05384ff3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryAppearance.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryAppearance.java @@ -8,22 +8,22 @@ package com.seibel.distanthorizons.core.config.types.enums; */ public enum EConfigEntryAppearance { - /** Defeat option */ - ALL(true, true), - /** Will only show the option in the UI. The option will be reverted on game restart */ - ONLY_IN_GUI(true, false), - /** Only show the option in the file. There would be no way to access it using the UI */ - ONLY_IN_FILE(true, false); + /** Defeat option */ + ALL(true, true), + /** Will only show the option in the UI. The option will be reverted on game restart */ + ONLY_IN_GUI(true, false), + /** Only show the option in the file. There would be no way to access it using the UI */ + ONLY_IN_FILE(true, false); - /** Sets whether the option should show in the UI */ - public final boolean showInGui; - /** Sets whether to save an option,
If set to false, the option will be reset on game restart */ - public final boolean showInFile; + /** Sets whether the option should show in the UI */ + public final boolean showInGui; + /** Sets whether to save an option,
If set to false, the option will be reset on game restart */ + public final boolean showInFile; - EConfigEntryAppearance(boolean showInGui, boolean showInFile) - { + EConfigEntryAppearance(boolean showInGui, boolean showInFile) + { // If both are false then the config won't touch the option, but it would still be accessible if explicitly called - this.showInGui = showInGui; - this.showInFile = showInFile; - } + this.showInGui = showInGui; + this.showInFile = showInFile; + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryPerformance.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryPerformance.java index eebff2ea0..f9253bee4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryPerformance.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/enums/EConfigEntryPerformance.java @@ -8,12 +8,12 @@ package com.seibel.distanthorizons.core.config.types.enums; */ public enum EConfigEntryPerformance { - NONE, - VERY_LOW, - LOW, - MEDIUM, - HIGH, - VERY_HIGH, + NONE, + VERY_LOW, + LOW, + MEDIUM, + HIGH, + VERY_HIGH, - DONT_SHOW + DONT_SHOW } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java index 44015411d..4a2bdff8e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java @@ -13,100 +13,126 @@ import org.apache.logging.log4j.Logger; import java.util.ArrayList; import java.util.concurrent.CompletableFuture; -public class FullDataDownSampler { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static CompletableFuture createDownSamplingFuture(DhSectionPos newTarget, IFullDataSourceProvider provider) { - // TODO: Make this future somehow run with lowest priority (to ensure ram usage stays low) - return createDownSamplingFuture(CompleteFullDataSource.createEmpty(newTarget), provider); - } - - public static CompletableFuture createDownSamplingFuture(CompleteFullDataSource target, IFullDataSourceProvider provider) { - int sectionSizeNeeded = 1 << target.getDataDetailLevel(); - - ArrayList> futures; - DhLodPos basePos = target.getSectionPos().getSectionBBoxPos().getCornerLodPos(CompleteFullDataSource.SECTION_SIZE_OFFSET); - if (sectionSizeNeeded <= CompleteFullDataSource.SECTION_SIZE_OFFSET) { - futures = new ArrayList<>(sectionSizeNeeded * sectionSizeNeeded); - for (int ox = 0; ox < sectionSizeNeeded; ox++) { - for (int oz = 0; oz < sectionSizeNeeded; oz++) { - CompletableFuture future = provider.read(new DhSectionPos( - CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox, basePos.z + oz)); - future = future.whenComplete((source, ex) -> { - if (ex == null && source != null && source instanceof CompleteFullDataSource) { - downSample(target, (CompleteFullDataSource) source); - } else if (ex != null) { - LOGGER.error("Error while down sampling", ex); - } - }); - futures.add(future); - } - } - } else { - futures = new ArrayList<>(CompleteFullDataSource.WIDTH * CompleteFullDataSource.WIDTH); - int multiplier = sectionSizeNeeded / CompleteFullDataSource.WIDTH; - for (int ox = 0; ox < CompleteFullDataSource.WIDTH; ox++) { - for (int oz = 0; oz < CompleteFullDataSource.WIDTH; oz++) { - CompletableFuture future = provider.read(new DhSectionPos( - CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox * multiplier, basePos.z + oz * multiplier)); - future = future.whenComplete((source, ex) -> { - if (ex == null && source != null && source instanceof CompleteFullDataSource) { - downSample(target, (CompleteFullDataSource) source); - } else if (ex != null) { - LOGGER.error("Error while down sampling", ex); - } - }); - futures.add(future); - } - } - } - return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenApply(v -> target); - } - - public static void downSample(CompleteFullDataSource target, CompleteFullDataSource source) { - LodUtil.assertTrue(target.getSectionPos().overlaps(source.getSectionPos())); - LodUtil.assertTrue(target.getDataDetailLevel() > source.getDataDetailLevel()); - - byte detailDiff = (byte) (target.getDataDetailLevel() - source.getDataDetailLevel()); - DhSectionPos trgPos = target.getSectionPos(); - DhSectionPos srcPos = source.getSectionPos(); - - if (detailDiff >= CompleteFullDataSource.SECTION_SIZE_OFFSET) { - // The source occupies only 1 datapoint in the target - // FIXME: TEMP method for down-sampling: take only the corner column - int sourceSectionPerTargetData = 1 << (detailDiff - CompleteFullDataSource.SECTION_SIZE_OFFSET); - if (srcPos.sectionX % sourceSectionPerTargetData != 0 || srcPos.sectionZ % sourceSectionPerTargetData != 0) { - return; - } - DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel()); - DhLodPos srcOffset = srcPos.getSectionBBoxPos().convertToDetailLevel(target.getDataDetailLevel()); - int offsetX = trgOffset.x - srcOffset.x; - int offsetZ = trgOffset.z - srcOffset.z; - LodUtil.assertTrue(offsetX >= 0 && offsetX < CompleteFullDataSource.WIDTH - && offsetZ >= 0 && offsetZ < CompleteFullDataSource.WIDTH); - target.markNotEmpty(); - source.get(0,0).deepCopyTo(target.get(offsetX, offsetZ)); - - } else if (detailDiff > 0) { - // The source occupies multiple data-points in the target - int srcDataPerTrgData = 1 << detailDiff; - int overlappedTrgDataSize = CompleteFullDataSource.WIDTH / srcDataPerTrgData; - - DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel()); - DhLodPos srcOffset = srcPos.getSectionBBoxPos().getCornerLodPos(target.getDataDetailLevel()); - int offsetX = trgOffset.x - srcOffset.x; - int offsetZ = trgOffset.z - srcOffset.z; - LodUtil.assertTrue(offsetX >= 0 && offsetX < CompleteFullDataSource.WIDTH - && offsetZ >= 0 && offsetZ < CompleteFullDataSource.WIDTH); - target.markNotEmpty(); - - for (int ox = 0; ox < overlappedTrgDataSize; ox++) { - for (int oz = 0; oz < overlappedTrgDataSize; oz++) { - SingleColumnFullDataAccessor column = target.get(ox + offsetX, oz + offsetZ); - column.downsampleFrom(source.subView(srcDataPerTrgData, ox * srcDataPerTrgData, oz * srcDataPerTrgData)); - } - } - } else { - LodUtil.assertNotReach(); - } - } +public class FullDataDownSampler +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + public static CompletableFuture createDownSamplingFuture(DhSectionPos newTarget, IFullDataSourceProvider provider) + { + // TODO: Make this future somehow run with lowest priority (to ensure ram usage stays low) + return createDownSamplingFuture(CompleteFullDataSource.createEmpty(newTarget), provider); + } + + public static CompletableFuture createDownSamplingFuture(CompleteFullDataSource target, IFullDataSourceProvider provider) + { + int sectionSizeNeeded = 1 << target.getDataDetailLevel(); + + ArrayList> futures; + DhLodPos basePos = target.getSectionPos().getSectionBBoxPos().getCornerLodPos(CompleteFullDataSource.SECTION_SIZE_OFFSET); + if (sectionSizeNeeded <= CompleteFullDataSource.SECTION_SIZE_OFFSET) + { + futures = new ArrayList<>(sectionSizeNeeded * sectionSizeNeeded); + for (int ox = 0; ox < sectionSizeNeeded; ox++) + { + for (int oz = 0; oz < sectionSizeNeeded; oz++) + { + CompletableFuture future = provider.read(new DhSectionPos( + CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox, basePos.z + oz)); + future = future.whenComplete((source, ex) -> { + if (ex == null && source != null && source instanceof CompleteFullDataSource) + { + downSample(target, (CompleteFullDataSource) source); + } + else if (ex != null) + { + LOGGER.error("Error while down sampling", ex); + } + }); + futures.add(future); + } + } + } + else + { + futures = new ArrayList<>(CompleteFullDataSource.WIDTH * CompleteFullDataSource.WIDTH); + int multiplier = sectionSizeNeeded / CompleteFullDataSource.WIDTH; + for (int ox = 0; ox < CompleteFullDataSource.WIDTH; ox++) + { + for (int oz = 0; oz < CompleteFullDataSource.WIDTH; oz++) + { + CompletableFuture future = provider.read(new DhSectionPos( + CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox * multiplier, basePos.z + oz * multiplier)); + future = future.whenComplete((source, ex) -> { + if (ex == null && source != null && source instanceof CompleteFullDataSource) + { + downSample(target, (CompleteFullDataSource) source); + } + else if (ex != null) + { + LOGGER.error("Error while down sampling", ex); + } + }); + futures.add(future); + } + } + } + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenApply(v -> target); + } + + public static void downSample(CompleteFullDataSource target, CompleteFullDataSource source) + { + LodUtil.assertTrue(target.getSectionPos().overlaps(source.getSectionPos())); + LodUtil.assertTrue(target.getDataDetailLevel() > source.getDataDetailLevel()); + + byte detailDiff = (byte) (target.getDataDetailLevel() - source.getDataDetailLevel()); + DhSectionPos trgPos = target.getSectionPos(); + DhSectionPos srcPos = source.getSectionPos(); + + if (detailDiff >= CompleteFullDataSource.SECTION_SIZE_OFFSET) + { + // The source occupies only 1 datapoint in the target + // FIXME: TEMP method for down-sampling: take only the corner column + int sourceSectionPerTargetData = 1 << (detailDiff - CompleteFullDataSource.SECTION_SIZE_OFFSET); + if (srcPos.sectionX % sourceSectionPerTargetData != 0 || srcPos.sectionZ % sourceSectionPerTargetData != 0) + { + return; + } + DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel()); + DhLodPos srcOffset = srcPos.getSectionBBoxPos().convertToDetailLevel(target.getDataDetailLevel()); + int offsetX = trgOffset.x - srcOffset.x; + int offsetZ = trgOffset.z - srcOffset.z; + LodUtil.assertTrue(offsetX >= 0 && offsetX < CompleteFullDataSource.WIDTH + && offsetZ >= 0 && offsetZ < CompleteFullDataSource.WIDTH); + target.markNotEmpty(); + source.get(0, 0).deepCopyTo(target.get(offsetX, offsetZ)); + + } + else if (detailDiff > 0) + { + // The source occupies multiple data-points in the target + int srcDataPerTrgData = 1 << detailDiff; + int overlappedTrgDataSize = CompleteFullDataSource.WIDTH / srcDataPerTrgData; + + DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel()); + DhLodPos srcOffset = srcPos.getSectionBBoxPos().getCornerLodPos(target.getDataDetailLevel()); + int offsetX = trgOffset.x - srcOffset.x; + int offsetZ = trgOffset.z - srcOffset.z; + LodUtil.assertTrue(offsetX >= 0 && offsetX < CompleteFullDataSource.WIDTH + && offsetZ >= 0 && offsetZ < CompleteFullDataSource.WIDTH); + target.markNotEmpty(); + + for (int ox = 0; ox < overlappedTrgDataSize; ox++) + { + for (int oz = 0; oz < overlappedTrgDataSize; oz++) + { + SingleColumnFullDataAccessor column = target.get(ox + offsetX, oz + offsetZ); + column.downsampleFrom(source.subView(srcDataPerTrgData, ox * srcDataPerTrgData, oz * srcDataPerTrgData)); + } + } + } + else + { + LodUtil.assertNotReach(); + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java index 660f597a8..319e78fae 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java @@ -15,18 +15,18 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; -/** - * WARNING: This is not THREAD-SAFE! +/** + * WARNING: This is not THREAD-SAFE! *

* Used to map a numerical IDs to a Biome/BlockState pair. - * + * * @author Leetom * @version 2022-10-2 */ public class FullDataPointIdMap { private static final Logger LOGGER = LogManager.getLogger(); - /** + /** * Should only be enabled when debugging. * Has the system check if any duplicate Entries were read/written * when (de)serializing. @@ -61,7 +61,7 @@ public class FullDataPointIdMap // methods // //=========// - private Entry getEntry(int id) + private Entry getEntry(int id) { this.readWriteLock.readLock().lock(); Entry entry; @@ -71,7 +71,7 @@ public class FullDataPointIdMap } catch (IndexOutOfBoundsException e) { - LOGGER.error("FullData ID Map out of sync for pos: "+this.pos+". ID: ["+id+"] greater than the number of known ID's: ["+this.entryList.size()+"]."); + LOGGER.error("FullData ID Map out of sync for pos: " + this.pos + ". ID: [" + id + "] greater than the number of known ID's: [" + this.entryList.size() + "]."); throw e; } @@ -82,15 +82,18 @@ public class FullDataPointIdMap public IBiomeWrapper getBiomeWrapper(int id) { return this.getEntry(id).biome; } public IBlockStateWrapper getBlockStateWrapper(int id) { return this.getEntry(id).blockState; } - /** - * If an entry with the given values already exists nothing will + /** + * If an entry with the given values already exists nothing will * be added but the existing item's ID will still be returned. */ public int addIfNotPresentAndGetId(IBiomeWrapper biome, IBlockStateWrapper blockState) { return this.addIfNotPresentAndGetId(new Entry(biome, blockState), true); } /** @param useWriteLocks should only be false if this method is already in a write lock to prevent unlocking at the wrong time */ private int addIfNotPresentAndGetId(Entry biomeBlockStateEntry, boolean useWriteLocks) { - if (useWriteLocks) { this.readWriteLock.writeLock().lock(); } + if (useWriteLocks) + { + this.readWriteLock.writeLock().lock(); + } int id; @@ -108,19 +111,23 @@ public class FullDataPointIdMap } - if (useWriteLocks) { this.readWriteLock.writeLock().unlock(); } + if (useWriteLocks) + { + this.readWriteLock.writeLock().unlock(); + } return id; } - /** - * Adds each entry from the given map to this map. + /** + * Adds each entry from the given map to this map. + * * @return an array of each added entry's ID in this map in order */ public int[] mergeAndReturnRemappedEntityIds(FullDataPointIdMap target) { - LOGGER.trace("merging {"+this.pos+", "+this.entryList.size()+"} and {"+target.pos+", "+target.entryList.size()+"}"); + LOGGER.trace("merging {" + this.pos + ", " + this.entryList.size() + "} and {" + target.pos + ", " + target.entryList.size() + "}"); target.readWriteLock.readLock().lock(); this.readWriteLock.writeLock().lock(); @@ -137,7 +144,7 @@ public class FullDataPointIdMap this.readWriteLock.writeLock().unlock(); target.readWriteLock.readLock().unlock(); - LOGGER.trace("finished merging {"+this.pos+", "+this.entryList.size()+"} and {"+target.pos+", "+target.entryList.size()+"}"); + LOGGER.trace("finished merging {" + this.pos + ", " + this.entryList.size() + "} and {" + target.pos + ", " + target.entryList.size() + "}"); return remappedEntryIds; } @@ -171,7 +178,7 @@ public class FullDataPointIdMap } this.readWriteLock.readLock().unlock(); - LOGGER.trace("serialize "+this.pos+" "+this.entryList.size()); + LOGGER.trace("serialize " + this.pos + " " + this.entryList.size()); } /** Creates a new IdBiomeBlockStateMap from the given UTF formatted stream */ @@ -180,7 +187,7 @@ public class FullDataPointIdMap int entityCount = inputStream.readInt(); // only used when debugging - HashMap dataPointEntryBySerialization = new HashMap<>(); + HashMap dataPointEntryBySerialization = new HashMap<>(); FullDataPointIdMap newMap = new FullDataPointIdMap(pos); for (int i = 0; i < entityCount; i++) @@ -203,7 +210,7 @@ public class FullDataPointIdMap } } - LOGGER.trace("deserialized "+pos+" "+newMap.entryList.size()+"-"+entityCount); + LOGGER.trace("deserialized " + pos + " " + newMap.entryList.size() + "-" + entityCount); return newMap; } @@ -235,7 +242,7 @@ public class FullDataPointIdMap public final IBiomeWrapper biome; public final IBlockStateWrapper blockState; - private Integer hashCode = null; + private Integer hashCode = null; // constructor // @@ -294,7 +301,7 @@ public class FullDataPointIdMap // necessary to prevent issues with deserializing objects after the level has been closed if (Thread.interrupted()) { - throw new InterruptedException(FullDataPointIdMap.class.getSimpleName()+" task interrupted."); + throw new InterruptedException(FullDataPointIdMap.class.getSimpleName() + " task interrupted."); } IBiomeWrapper biome = WRAPPER_FACTORY.deserializeBiomeWrapper(stringArray[0]); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java index 156ab3c79..faf82939b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java @@ -8,9 +8,9 @@ import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; /** - * A more specific version of {@link FullDataArrayAccessor} + * A more specific version of {@link FullDataArrayAccessor} * that only contains full data for a single chunk. - * + * * @see FullDataPointUtil */ public class ChunkSizedFullDataAccessor extends FullDataArrayAccessor @@ -23,8 +23,8 @@ public class ChunkSizedFullDataAccessor extends FullDataArrayAccessor public ChunkSizedFullDataAccessor(DhChunkPos pos) { - super(new FullDataPointIdMap(new DhSectionPos(pos)), - new long[LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH][0], + super(new FullDataPointIdMap(new DhSectionPos(pos)), + new long[LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH][0], LodUtil.CHUNK_WIDTH); this.pos = pos; @@ -52,6 +52,6 @@ public class ChunkSizedFullDataAccessor extends FullDataArrayAccessor public DhLodPos getLodPos() { return new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, this.pos.x, this.pos.z); } @Override - public String toString() { return this.pos+" "+this.nonEmptyCount(); } + public String toString() { return this.pos + " " + this.nonEmptyCount(); } } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/FullDataArrayAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/FullDataArrayAccessor.java index 3e2fc792f..48f79492c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/FullDataArrayAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/FullDataArrayAccessor.java @@ -9,7 +9,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.LowDetailInc /** * Contains Full Data points and basic methods for getting and setting them.
* Can be used standalone or as the base for Full data sources. - * + * * @see CompleteFullDataSource * @see LowDetailIncompleteFullDataSource */ @@ -17,8 +17,8 @@ public class FullDataArrayAccessor implements IFullDataAccessor { protected final FullDataPointIdMap mapping; - /** - * A flattened 2D array (for the X and Z directions) containing an array for the Y direction. + /** + * A flattened 2D array (for the X and Z directions) containing an array for the Y direction. * TODO the flattened array is probably to reduce garbage collection overhead, but is doing it this way worth while? Having a 3D array would be much easier to understand */ protected final long[][] dataArrays; @@ -113,6 +113,7 @@ public class FullDataArrayAccessor implements IFullDataAccessor /** * Takes a higher detail {@link FullDataArrayAccessor}'s and converts the data to a lower detail level. + * * @param fullDataAccessor must be larger than this {@link FullDataArrayAccessor} and its width must a power of two larger (example: this.width = 4, other.width = 8) */ public void downsampleFrom(FullDataArrayAccessor fullDataAccessor) @@ -143,19 +144,19 @@ public class FullDataArrayAccessor implements IFullDataAccessor @Override public SingleColumnFullDataAccessor get(int index) { return this.get(index / this.width, index % this.width); } @Override - public SingleColumnFullDataAccessor get(int relativeX, int relativeZ) - { + public SingleColumnFullDataAccessor get(int relativeX, int relativeZ) + { int dataArrayIndex = (relativeX * this.width) + relativeZ + this.offset; if (dataArrayIndex >= this.dataArrays.length) { LodUtil.assertNotReach( - "FullDataArrayAccessor.get() called with a relative position that is outside the data source. \n" + - "source width: ["+this.width+"] source offset: ["+this.offset+"]\n" + - "given relative pos X: ["+relativeX+"] Z: ["+relativeZ+"]\n" + - "dataArrays.length: ["+this.dataArrays.length+"] dataArrayIndex: ["+dataArrayIndex+"]."); + "FullDataArrayAccessor.get() called with a relative position that is outside the data source. \n" + + "source width: [" + this.width + "] source offset: [" + this.offset + "]\n" + + "given relative pos X: [" + relativeX + "] Z: [" + relativeZ + "]\n" + + "dataArrays.length: [" + this.dataArrays.length + "] dataArrayIndex: [" + dataArrayIndex + "]."); } - return new SingleColumnFullDataAccessor(this.mapping, this.dataArrays, dataArrayIndex); + return new SingleColumnFullDataAccessor(this.mapping, this.dataArrays, dataArrayIndex); } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/IFullDataAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/IFullDataAccessor.java index 3601ff09e..82f2ad8db 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/IFullDataAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/IFullDataAccessor.java @@ -10,7 +10,7 @@ import java.util.Iterator; /** * Contains raw full data points, which must be interpreted by the {@link FullDataPointUtil}.
* Often used by {@link IFullDataSource}'s. - * + * * @see IFullDataSource * @see FullDataArrayAccessor * @see FullDataPointUtil @@ -26,8 +26,8 @@ public interface IFullDataAccessor /** measured in full data points */ int width(); - /** - * Creates a new {@link IFullDataAccessor} with the given width and starting at the given X and Z offsets.
+ /** + * Creates a new {@link IFullDataAccessor} with the given width and starting at the given X and Z offsets.
* The returned object will use the same underlining data structure (IE memory addresses) as the source {@link IFullDataAccessor}. */ IFullDataAccessor subView(int width, int xOffset, int zOffset); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java index 26be2929e..f23056a8d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java @@ -6,14 +6,15 @@ import com.seibel.distanthorizons.core.util.LodUtil; /** * Represents a single column of Full LOD data. - * + * * @see FullDataPointUtil */ public class SingleColumnFullDataAccessor implements IFullDataAccessor { /** - * A flattened 2D array (for the X and Z directions) containing an array for the Y direction. + * A flattened 2D array (for the X and Z directions) containing an array for the Y direction. * TODO the flattened array is probably to reduce garbage collection overhead, but is doing it this way worth while? Having a 3D array would be much easier to understand + * * @see FullDataArrayAccessor#dataArrays */ private final long[][] dataArrays; @@ -29,13 +30,13 @@ public class SingleColumnFullDataAccessor implements IFullDataAccessor this.dataArrayIndex = dataArrayIndex; this.mapping = mapping; - LodUtil.assertTrue(this.dataArrayIndex < this.dataArrays.length, "dataArrays.length ["+this.dataArrays.length+"] is less than the dataArrayIndex ["+this.dataArrayIndex+"]."); + LodUtil.assertTrue(this.dataArrayIndex < this.dataArrays.length, "dataArrays.length [" + this.dataArrays.length + "] is less than the dataArrayIndex [" + this.dataArrayIndex + "]."); } /** @return true if any data exists in this column. */ - public boolean doesColumnExist() + public boolean doesColumnExist() { long[] dataColumn = this.dataArrays[this.dataArrayIndex]; return dataColumn != null && dataColumn.length != 0; @@ -135,8 +136,8 @@ public class SingleColumnFullDataAccessor implements IFullDataAccessor } } - /** - * Replaces this column's data with data from the input {@link IFullDataAccessor}.
+ /** + * Replaces this column's data with data from the input {@link IFullDataAccessor}.
* This is used to convert higher detail LOD data to lower detail LOD data. */ public void downsampleFrom(IFullDataAccessor source) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/AbstractFullDataSourceLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/AbstractFullDataSourceLoader.java index 869cc1975..da45c77d7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/AbstractFullDataSourceLoader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/AbstractFullDataSourceLoader.java @@ -34,17 +34,17 @@ public abstract class AbstractFullDataSourceLoader } Set loaders = loaderRegistry.get(clazz); if (loaders.stream().anyMatch(other -> + { + // see if any loaderSupportsVersion conflicts with this one + for (byte otherVer : other.loaderSupportedVersions) { - // see if any loaderSupportsVersion conflicts with this one - for (byte otherVer : other.loaderSupportedVersions) + if (Arrays.binarySearch(loaderSupportedVersions, otherVer) >= 0) { - if (Arrays.binarySearch(loaderSupportedVersions, otherVer) >= 0) - { - return true; - } + return true; } - return false; - })) + } + return false; + })) { throw new IllegalArgumentException("Loader for class " + clazz + " that supports one of the version in " + Arrays.toString(loaderSupportedVersions) + " already registered!"); @@ -53,8 +53,9 @@ public abstract class AbstractFullDataSourceLoader loaderRegistry.put(clazz, this); } - /** + /** * Can return null if any of the requirements aren't met. + * * @throws InterruptedException if the loader thread is interrupted, generally happens when the level is shutting down */ public abstract IFullDataSource loadData(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/CompleteFullDataSourceLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/CompleteFullDataSourceLoader.java index 3c4d1903c..1b41b38b4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/CompleteFullDataSourceLoader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/CompleteFullDataSourceLoader.java @@ -10,17 +10,17 @@ import java.io.IOException; public class CompleteFullDataSourceLoader extends AbstractFullDataSourceLoader { - public CompleteFullDataSourceLoader() + public CompleteFullDataSourceLoader() { - super(CompleteFullDataSource.class, CompleteFullDataSource.TYPE_ID, new byte[]{ CompleteFullDataSource.DATA_FORMAT_VERSION }); - } + super(CompleteFullDataSource.class, CompleteFullDataSource.TYPE_ID, new byte[]{CompleteFullDataSource.DATA_FORMAT_VERSION}); + } - @Override - public IFullDataSource loadData(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException + @Override + public IFullDataSource loadData(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException { CompleteFullDataSource dataSource = CompleteFullDataSource.createEmpty(dataFile.pos); dataSource.populateFromStream(dataFile, inputStream, level); - return dataSource; - } + return dataSource; + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/HighDetailIncompleteFullDataSourceLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/HighDetailIncompleteFullDataSourceLoader.java index 906fb8cc9..b56211e65 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/HighDetailIncompleteFullDataSourceLoader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/HighDetailIncompleteFullDataSourceLoader.java @@ -12,14 +12,15 @@ public class HighDetailIncompleteFullDataSourceLoader extends AbstractFullDataSo { public HighDetailIncompleteFullDataSourceLoader() { - super(HighDetailIncompleteFullDataSource.class, HighDetailIncompleteFullDataSource.TYPE_ID, new byte[] { HighDetailIncompleteFullDataSource.DATA_FORMAT_VERSION }); + super(HighDetailIncompleteFullDataSource.class, HighDetailIncompleteFullDataSource.TYPE_ID, new byte[]{HighDetailIncompleteFullDataSource.DATA_FORMAT_VERSION}); } - - @Override + + @Override public IFullDataSource loadData(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException { HighDetailIncompleteFullDataSource dataSource = HighDetailIncompleteFullDataSource.createEmpty(dataFile.pos); dataSource.populateFromStream(dataFile, inputStream, level); return dataSource; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/LowDetailIncompleteFullDataSourceLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/LowDetailIncompleteFullDataSourceLoader.java index 6486d1dff..572c1eed3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/LowDetailIncompleteFullDataSourceLoader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/loader/LowDetailIncompleteFullDataSourceLoader.java @@ -10,15 +10,17 @@ import java.io.IOException; public class LowDetailIncompleteFullDataSourceLoader extends AbstractFullDataSourceLoader { - public LowDetailIncompleteFullDataSourceLoader() { - super(LowDetailIncompleteFullDataSource.class, LowDetailIncompleteFullDataSource.TYPE_ID, new byte[]{ LowDetailIncompleteFullDataSource.DATA_FORMAT_VERSION }); - } - - @Override - public IFullDataSource loadData(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException + public LowDetailIncompleteFullDataSourceLoader() + { + super(LowDetailIncompleteFullDataSource.class, LowDetailIncompleteFullDataSource.TYPE_ID, new byte[]{LowDetailIncompleteFullDataSource.DATA_FORMAT_VERSION}); + } + + @Override + public IFullDataSource loadData(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException { LowDetailIncompleteFullDataSource dataSource = LowDetailIncompleteFullDataSource.createEmpty(dataFile.pos); dataSource.populateFromStream(dataFile, inputStream, level); return dataSource; - } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java index 77d9e8801..d5bb3990c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java @@ -24,25 +24,25 @@ import java.io.*; /** * This data source contains every datapoint over its given {@link DhSectionPos}. - * + * * @see FullDataPointUtil * @see LowDetailIncompleteFullDataSource * @see HighDetailIncompleteFullDataSource */ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFullDataSource, IStreamableFullDataSource { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; - /** measured in dataPoints */ + public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + /** measured in dataPoints */ public static final int WIDTH = BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); - + public static final byte DATA_FORMAT_VERSION = 3; /** written to the binary file to mark what {@link IFullDataSource} the binary file corresponds to */ - public static final long TYPE_ID = "CompleteFullDataSource".hashCode(); + public static final long TYPE_ID = "CompleteFullDataSource".hashCode(); - private final DhSectionPos sectionPos; - private boolean isEmpty = true; + private final DhSectionPos sectionPos; + private boolean isEmpty = true; public EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.EMPTY; @@ -54,9 +54,9 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu public static CompleteFullDataSource createEmpty(DhSectionPos pos) { return new CompleteFullDataSource(pos); } private CompleteFullDataSource(DhSectionPos sectionPos) { - super(new FullDataPointIdMap(sectionPos), new long[WIDTH * WIDTH][0], WIDTH); - this.sectionPos = sectionPos; - } + super(new FullDataPointIdMap(sectionPos), new long[WIDTH * WIDTH][0], WIDTH); + this.sectionPos = sectionPos; + } public CompleteFullDataSource(DhSectionPos pos, FullDataPointIdMap mapping, long[][] data) { @@ -85,23 +85,23 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu } @Override public FullDataSourceSummaryData readSourceSummaryInfo(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException - { + { int dataDetail = inputStream.readInt(); if (dataDetail != dataFile.baseMetaData.dataLevel) { - throw new IOException(LodUtil.formatLog("Data level mismatch: "+dataDetail+" != "+dataFile.baseMetaData.dataLevel)); + throw new IOException(LodUtil.formatLog("Data level mismatch: " + dataDetail + " != " + dataFile.baseMetaData.dataLevel)); } int width = inputStream.readInt(); if (width != WIDTH) { - throw new IOException(LodUtil.formatLog("Section width mismatch: "+width+" != "+ WIDTH +" (Currently only 1 section width is supported)")); + throw new IOException(LodUtil.formatLog("Section width mismatch: " + width + " != " + WIDTH + " (Currently only 1 section width is supported)")); } int minY = inputStream.readInt(); if (minY != level.getMinY()) { - LOGGER.warn("Data minY mismatch: "+minY+" != "+level.getMinY()+". Will ignore data's y level"); + LOGGER.warn("Data minY mismatch: " + minY + " != " + level.getMinY() + ". Will ignore data's y level"); } byte worldGenByte = inputStream.readByte(); @@ -109,7 +109,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu if (worldGenStep == null) { worldGenStep = EDhApiWorldGenerationStep.SURFACE; - LOGGER.warn("Missing WorldGenStep, defaulting to: "+worldGenStep.name()); + LOGGER.warn("Missing WorldGenStep, defaulting to: " + worldGenStep.name()); } @@ -177,7 +177,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu } else if (dataPresentFlag != IFullDataSource.DATA_GUARD_BYTE) { - throw new IOException("Invalid file format. Data Points guard byte expected: (no data) ["+IFullDataSource.NO_DATA_FLAG_BYTE+"] or (data present) ["+IFullDataSource.DATA_GUARD_BYTE+"], but found ["+dataPresentFlag+"]."); + throw new IOException("Invalid file format. Data Points guard byte expected: (no data) [" + IFullDataSource.NO_DATA_FLAG_BYTE + "] or (data present) [" + IFullDataSource.DATA_GUARD_BYTE + "], but found [" + dataPresentFlag + "]."); } @@ -242,7 +242,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu return FullDataPointIdMap.deserialize(inputStream, this.sectionPos); } - @Override + @Override public void setIdMapping(FullDataPointIdMap mappings) { this.mapping.mergeAndReturnRemappedEntityIds(mappings); } @@ -326,7 +326,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu } } - + //================// @@ -352,7 +352,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu // if the difference in detail levels is very large, the posToWrite // may be skipped, due to how we sample large detail levels by only // getting the corners. - + // In this case the difference isn't very large, so return true return true; } @@ -362,7 +362,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu // check if the posToWrite is in a corner of posToTest byte sectPerData = (byte) BitShiftUtil.powerOfTwo(posToWrite.sectionDetailLevel - posToTest.sectionDetailLevel - SECTION_SIZE_OFFSET); LodUtil.assertTrue(sectPerData != 0); - return posToTest.sectionX % sectPerData == 0 && posToTest.sectionZ % sectPerData == 0; + return posToTest.sectionX % sectPerData == 0 && posToTest.sectionZ % sectPerData == 0; } } @@ -373,9 +373,9 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu //=====================// @Override - public DhSectionPos getSectionPos() { return this.sectionPos; } + public DhSectionPos getSectionPos() { return this.sectionPos; } @Override - public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel -SECTION_SIZE_OFFSET); } + public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); } @Override public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java index 0ef41aa3c..b19d820e7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java @@ -25,45 +25,45 @@ import java.util.BitSet; /** * Used for small incomplete LOD blocks.
- * Handles incomplete full data with a detail level equal to or lower than + * Handles incomplete full data with a detail level equal to or lower than * {@link HighDetailIncompleteFullDataSource#MAX_SECTION_DETAIL}.

- * + * * Compared to other {@link IIncompleteFullDataSource}'s, this object doesn't extend {@link FullDataArrayAccessor}, * instead it contains several "sections" of data, represented by {@link FullDataArrayAccessor}s.

- * + * * Formerly "SparseFullDataSource". - * + * * @see LowDetailIncompleteFullDataSource * @see CompleteFullDataSource * @see FullDataPointUtil */ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSource, IStreamableFullDataSource { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); // TODO James would like to rename, comment, and potentially remove some of these constants. // But he doesn't currently have the understanding to do so. - public static final byte SPARSE_UNIT_DETAIL = LodUtil.CHUNK_DETAIL_LEVEL; - public static final byte SPARSE_UNIT_SIZE = (byte) BitShiftUtil.powerOfTwo(SPARSE_UNIT_DETAIL); + public static final byte SPARSE_UNIT_DETAIL = LodUtil.CHUNK_DETAIL_LEVEL; + public static final byte SPARSE_UNIT_SIZE = (byte) BitShiftUtil.powerOfTwo(SPARSE_UNIT_DETAIL); - public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; - public static final int SECTION_SIZE = (byte) BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); + public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + public static final int SECTION_SIZE = (byte) BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); /** aka max detail level */ - public static final byte MAX_SECTION_DETAIL = SECTION_SIZE_OFFSET + SPARSE_UNIT_DETAIL; + public static final byte MAX_SECTION_DETAIL = SECTION_SIZE_OFFSET + SPARSE_UNIT_DETAIL; - public static final byte DATA_FORMAT_VERSION = 3; + public static final byte DATA_FORMAT_VERSION = 3; /** written to the binary file to mark what {@link IFullDataSource} the binary file corresponds to */ - public static final long TYPE_ID = "HighDetailIncompleteFullDataSource".hashCode(); + public static final long TYPE_ID = "HighDetailIncompleteFullDataSource".hashCode(); protected final FullDataPointIdMap mapping; - private final DhSectionPos sectionPos; - private final FullDataArrayAccessor[] sparseData; - private final DhLodPos chunkPos; + private final DhSectionPos sectionPos; + private final FullDataArrayAccessor[] sparseData; + private final DhLodPos chunkPos; public final int sectionCount; public final int dataPointsPerSection; - public boolean isEmpty = true; + public boolean isEmpty = true; public EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.EMPTY; private boolean isPromoted = false; @@ -73,27 +73,27 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo // constructors // //==============// - public static HighDetailIncompleteFullDataSource createEmpty(DhSectionPos pos) { return new HighDetailIncompleteFullDataSource(pos); } - private HighDetailIncompleteFullDataSource(DhSectionPos sectionPos) + public static HighDetailIncompleteFullDataSource createEmpty(DhSectionPos pos) { return new HighDetailIncompleteFullDataSource(pos); } + private HighDetailIncompleteFullDataSource(DhSectionPos sectionPos) { - LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL); - LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL); + LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL); + LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL); - this.sectionPos = sectionPos; + this.sectionPos = sectionPos; this.sectionCount = BitShiftUtil.powerOfTwo(sectionPos.sectionDetailLevel - SPARSE_UNIT_DETAIL); this.dataPointsPerSection = SECTION_SIZE / this.sectionCount; this.sparseData = new FullDataArrayAccessor[this.sectionCount * this.sectionCount]; this.chunkPos = sectionPos.getCorner(SPARSE_UNIT_DETAIL); this.mapping = new FullDataPointIdMap(sectionPos); - } + } - protected HighDetailIncompleteFullDataSource(DhSectionPos sectionPos, FullDataPointIdMap mapping, FullDataArrayAccessor[] data) + protected HighDetailIncompleteFullDataSource(DhSectionPos sectionPos, FullDataPointIdMap mapping, FullDataArrayAccessor[] data) { - LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL); - LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL); + LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL); + LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL); - this.sectionPos = sectionPos; + this.sectionPos = sectionPos; this.sectionCount = 1 << (byte) (sectionPos.sectionDetailLevel - SPARSE_UNIT_DETAIL); this.dataPointsPerSection = SECTION_SIZE / this.sectionCount; @@ -101,8 +101,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo this.sparseData = data; this.chunkPos = sectionPos.getCorner(SPARSE_UNIT_DETAIL); this.isEmpty = false; - this.mapping = mapping; - } + this.mapping = mapping; + } @@ -128,7 +128,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo LodUtil.assertTrue(dataFile.pos.sectionDetailLevel <= MAX_SECTION_DETAIL); int dataDetail = inputStream.readShort(); - if(dataDetail != dataFile.baseMetaData.dataLevel) + if (dataDetail != dataFile.baseMetaData.dataLevel) { throw new IOException(LodUtil.formatLog("Data level mismatch: {} != {}", dataDetail, dataFile.baseMetaData.dataLevel)); } @@ -152,14 +152,14 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo int minY = inputStream.readInt(); if (minY != level.getMinY()) { - LOGGER.warn("Data minY mismatch: "+minY+" != "+level.getMinY()+". Will ignore data's y level"); + LOGGER.warn("Data minY mismatch: " + minY + " != " + level.getMinY() + ". Will ignore data's y level"); } EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.fromValue(inputStream.readByte()); if (worldGenStep == null) { worldGenStep = EDhApiWorldGenerationStep.SURFACE; - LOGGER.warn("Missing WorldGenStep, defaulting to: "+worldGenStep.name()); + LOGGER.warn("Missing WorldGenStep, defaulting to: " + worldGenStep.name()); } @@ -193,8 +193,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo // Data array content (only non-empty data is written) dataOutputStream.writeInt(IFullDataSource.DATA_GUARD_BYTE); for (int dataArrayIndex = dataArrayIndexHasData.nextSetBit(0); - dataArrayIndex >= 0; - dataArrayIndex = dataArrayIndexHasData.nextSetBit(dataArrayIndex+1)) + dataArrayIndex >= 0; + dataArrayIndex = dataArrayIndexHasData.nextSetBit(dataArrayIndex + 1)) { // column data length FullDataArrayAccessor array = this.sparseData[dataArrayIndex]; @@ -249,7 +249,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo else if (dataPresentFlag != IFullDataSource.DATA_GUARD_BYTE) { // the file format is incorrect - throw new IOException("Invalid file format. Data Points guard byte expected: (no data) ["+IFullDataSource.NO_DATA_FLAG_BYTE+"] or (data present) ["+IFullDataSource.DATA_GUARD_BYTE+"], but found ["+dataPresentFlag+"]."); + throw new IOException("Invalid file format. Data Points guard byte expected: (no data) [" + IFullDataSource.NO_DATA_FLAG_BYTE + "] or (data present) [" + IFullDataSource.DATA_GUARD_BYTE + "], but found [" + dataPresentFlag + "]."); } @@ -287,9 +287,9 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo // read in each column that has data written to it long[][][] rawFullDataArrays = new long[chunks * chunks][][]; for (int fullDataIndex = dataArrayIndexHasData.nextSetBit(0); - fullDataIndex >= 0 && // TODO why does this happen? - fullDataIndex < rawFullDataArrays.length; - fullDataIndex = dataArrayIndexHasData.nextSetBit(fullDataIndex + 1)) + fullDataIndex >= 0 && // TODO why does this happen? + fullDataIndex < rawFullDataArrays.length; + fullDataIndex = dataArrayIndexHasData.nextSetBit(fullDataIndex + 1)) { long[][] dataColumn = new long[dataPointsPerChunk * dataPointsPerChunk][]; @@ -380,7 +380,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { - LodUtil.assertTrue(relativeX >=0 && relativeX < SECTION_SIZE && relativeZ >=0 && relativeZ < SECTION_SIZE); + LodUtil.assertTrue(relativeX >= 0 && relativeX < SECTION_SIZE && relativeZ >= 0 && relativeZ < SECTION_SIZE); int chunkX = relativeX / this.dataPointsPerSection; int chunkZ = relativeZ / this.dataPointsPerSection; FullDataArrayAccessor chunk = this.sparseData[chunkX * this.sectionCount + chunkZ]; @@ -398,15 +398,15 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo // getters // //=========// - @Override - public DhSectionPos getSectionPos() { return this.sectionPos; } - @Override - public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); } - - @Override - public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; } + @Override + public DhSectionPos getSectionPos() { return this.sectionPos; } + @Override + public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); } - @Override + @Override + public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; } + + @Override public EDhApiWorldGenerationStep getWorldGenStep() { return this.worldGenStep; } @Override @@ -421,11 +421,11 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo private int calculateOffset(int chunkX, int chunkZ) { - int offsetX = chunkX - this.chunkPos.x; - int offsetZ = chunkZ - this.chunkPos.z; - LodUtil.assertTrue(offsetX >= 0 && offsetZ >= 0 && offsetX < this.sectionCount && offsetZ < this.sectionCount); - return offsetX * this.sectionCount + offsetZ; - } + int offsetX = chunkX - this.chunkPos.x; + int offsetZ = chunkZ - this.chunkPos.z; + LodUtil.assertTrue(offsetX >= 0 && offsetZ >= 0 && offsetX < this.sectionCount && offsetZ < this.sectionCount); + return offsetX * this.sectionCount + offsetZ; + } @@ -433,8 +433,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo // data update // //=============// - @Override - public void update(ChunkSizedFullDataAccessor chunkDataView) + @Override + public void update(ChunkSizedFullDataAccessor chunkDataView) { int arrayOffset = this.calculateOffset(chunkDataView.pos.x, chunkDataView.pos.z); FullDataArrayAccessor newArray = new FullDataArrayAccessor(this.mapping, new long[this.dataPointsPerSection * this.dataPointsPerSection][], this.dataPointsPerSection); @@ -446,7 +446,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo { int count = this.dataPointsPerSection; int dataPerCount = SPARSE_UNIT_SIZE / this.dataPointsPerSection; - + for (int xOffset = 0; xOffset < count; xOffset++) { for (int zOffset = 0; zOffset < count; zOffset++) @@ -459,12 +459,12 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo this.isEmpty = false; this.sparseData[arrayOffset] = newArray; - } + } // data sampling // - @Override + @Override public void sampleFrom(IFullDataSource fullDataSource) { DhSectionPos pos = fullDataSource.getSectionPos(); @@ -487,30 +487,30 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo else if (fullDataSource instanceof LowDetailIncompleteFullDataSource) { // this.sampleFrom((LowDetailIncompleteFullDataSource) fullDataSource); - LodUtil.assertNotReach("SampleFrom not implemented for ["+IFullDataSource.class.getSimpleName()+"] with class ["+fullDataSource.getClass().getSimpleName()+"]."); + LodUtil.assertNotReach("SampleFrom not implemented for [" + IFullDataSource.class.getSimpleName() + "] with class [" + fullDataSource.getClass().getSimpleName() + "]."); } else { - LodUtil.assertNotReach("SampleFrom not implemented for ["+IFullDataSource.class.getSimpleName()+"] with class ["+fullDataSource.getClass().getSimpleName()+"]."); + LodUtil.assertNotReach("SampleFrom not implemented for [" + IFullDataSource.class.getSimpleName() + "] with class [" + fullDataSource.getClass().getSimpleName() + "]."); } } - private void sampleFrom(CompleteFullDataSource completeDataSource) + private void sampleFrom(CompleteFullDataSource completeDataSource) { - DhSectionPos pos = completeDataSource.getSectionPos(); + DhSectionPos pos = completeDataSource.getSectionPos(); this.isEmpty = false; - - DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL); - DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL); - + + DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL); + DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL); + int coveredChunks = pos.getWidth(SPARSE_UNIT_DETAIL).numberOfLodSectionsWide; - int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> completeDataSource.getDataDetailLevel(); - LodUtil.assertTrue((coveredChunks * sourceDataPerChunk) == CompleteFullDataSource.WIDTH); - + int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> completeDataSource.getDataDetailLevel(); + LodUtil.assertTrue((coveredChunks * sourceDataPerChunk) == CompleteFullDataSource.WIDTH); + int xDataOffset = dataPos.x - basePos.x; - int zDataOffset = dataPos.z - basePos.z; - LodUtil.assertTrue(xDataOffset >= 0 && xDataOffset < this.sectionCount && zDataOffset >= 0 && zDataOffset < this.sectionCount); - + int zDataOffset = dataPos.z - basePos.z; + LodUtil.assertTrue(xDataOffset >= 0 && xDataOffset < this.sectionCount && zDataOffset >= 0 && zDataOffset < this.sectionCount); + for (int xOffset = 0; xOffset < coveredChunks; xOffset++) { for (int zOffset = 0; zOffset < coveredChunks; zOffset++) @@ -521,7 +521,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo this.sparseData[(xOffset + xDataOffset) * this.sectionCount + (zOffset + zDataOffset)] = newFullDataAccessor; } } - } + } private void sampleFrom(HighDetailIncompleteFullDataSource sparseDataSource) { DhSectionPos pos = sparseDataSource.getSectionPos(); @@ -530,8 +530,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL); DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL); - int offsetX = dataPos.x-basePos.x; - int offsetZ = dataPos.z-basePos.z; + int offsetX = dataPos.x - basePos.x; + int offsetZ = dataPos.z - basePos.z; LodUtil.assertTrue(offsetX >= 0 && offsetX < this.sectionCount && offsetZ >= 0 && offsetZ < this.sectionCount); for (int xOffset = 0; xOffset < sparseDataSource.sectionCount; xOffset++) @@ -551,7 +551,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo private void sampleFrom(LowDetailIncompleteFullDataSource spottyDataSource) { // TODO implement - + // DhSectionPos pos = spottyDataSource.getSectionPos(); // this.isEmpty = false; // @@ -579,10 +579,10 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo } - private void applyToFullDataSource(CompleteFullDataSource dataSource) + private void applyToFullDataSource(CompleteFullDataSource dataSource) { - LodUtil.assertTrue(dataSource.getSectionPos().equals(this.sectionPos)); - LodUtil.assertTrue(dataSource.getDataDetailLevel() == this.getDataDetailLevel()); + LodUtil.assertTrue(dataSource.getSectionPos().equals(this.sectionPos)); + LodUtil.assertTrue(dataSource.getDataDetailLevel() == this.getDataDetailLevel()); for (int x = 0; x < this.sectionCount; x++) { for (int z = 0; z < this.sectionCount; z++) @@ -597,17 +597,17 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo array.shadowCopyTo(view); } } - } - - public IFullDataSource tryPromotingToCompleteDataSource() + } + + public IFullDataSource tryPromotingToCompleteDataSource() { - if (this.isEmpty) + if (this.isEmpty) { return this; } // promotion can only succeed if every data column is present - for (FullDataArrayAccessor array : this.sparseData) + for (FullDataArrayAccessor array : this.sparseData) { if (array == null) { @@ -615,14 +615,15 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo } } isPromoted = true; - CompleteFullDataSource fullDataSource = CompleteFullDataSource.createEmpty(this.sectionPos); + CompleteFullDataSource fullDataSource = CompleteFullDataSource.createEmpty(this.sectionPos); this.applyToFullDataSource(fullDataSource); - return fullDataSource; - } - + return fullDataSource; + } + @Override - public boolean hasBeenPromoted() { + public boolean hasBeenPromoted() + { return isPromoted; } - + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java index 5dfd2f207..41e691c83 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java @@ -25,32 +25,32 @@ import java.util.BitSet; /** * Used for large incomplete LOD blocks.
- * Handles incomplete full data with a detail level higher than + * Handles incomplete full data with a detail level higher than * {@link HighDetailIncompleteFullDataSource#MAX_SECTION_DETAIL}.

- * + * * Formerly "SpottyFullDataSource". - * + * * @see HighDetailIncompleteFullDataSource * @see CompleteFullDataSource * @see FullDataPointUtil */ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor implements IIncompleteFullDataSource, IStreamableFullDataSource { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; /** measured in dataPoints */ - public static final int WIDTH = BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); + public static final int WIDTH = BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); - public static final byte DATA_FORMAT_VERSION = 3; + public static final byte DATA_FORMAT_VERSION = 3; /** written to the binary file to mark what {@link IFullDataSource} the binary file corresponds to */ - public static final long TYPE_ID = "LowDetailIncompleteFullDataSource".hashCode(); + public static final long TYPE_ID = "LowDetailIncompleteFullDataSource".hashCode(); - private final DhSectionPos sectionPos; + private final DhSectionPos sectionPos; private final BitSet isColumnNotEmpty; - private boolean isEmpty = true; + private boolean isEmpty = true; public EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.EMPTY; private boolean isPromoted = false; @@ -61,15 +61,15 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp //==============// public static LowDetailIncompleteFullDataSource createEmpty(DhSectionPos pos) { return new LowDetailIncompleteFullDataSource(pos); } - private LowDetailIncompleteFullDataSource(DhSectionPos sectionPos) + private LowDetailIncompleteFullDataSource(DhSectionPos sectionPos) { - super(new FullDataPointIdMap(sectionPos), new long[WIDTH * WIDTH][0], WIDTH); - LodUtil.assertTrue(sectionPos.sectionDetailLevel > HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL); + super(new FullDataPointIdMap(sectionPos), new long[WIDTH * WIDTH][0], WIDTH); + LodUtil.assertTrue(sectionPos.sectionDetailLevel > HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL); - this.sectionPos = sectionPos; + this.sectionPos = sectionPos; this.isColumnNotEmpty = new BitSet(WIDTH * WIDTH); this.worldGenStep = EDhApiWorldGenerationStep.EMPTY; - } + } private LowDetailIncompleteFullDataSource(DhSectionPos pos, FullDataPointIdMap mapping, EDhApiWorldGenerationStep worldGenStep, BitSet isColumnNotEmpty, long[][] data) { @@ -102,28 +102,28 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp public FullDataSourceSummaryData readSourceSummaryInfo(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException { int dataDetail = inputStream.readInt(); - if(dataDetail != dataFile.baseMetaData.dataLevel) + if (dataDetail != dataFile.baseMetaData.dataLevel) { - throw new IOException(LodUtil.formatLog("Data level mismatch: "+dataDetail+" != "+dataFile.baseMetaData.dataLevel)); + throw new IOException(LodUtil.formatLog("Data level mismatch: " + dataDetail + " != " + dataFile.baseMetaData.dataLevel)); } int width = inputStream.readInt(); if (width != WIDTH) { - throw new IOException(LodUtil.formatLog("Section size mismatch: "+width+" != "+ WIDTH +" (Currently only 1 section size is supported)")); + throw new IOException(LodUtil.formatLog("Section size mismatch: " + width + " != " + WIDTH + " (Currently only 1 section size is supported)")); } int minY = inputStream.readInt(); if (minY != level.getMinY()) { - LOGGER.warn("Data minY mismatch: "+minY+" != "+level.getMinY()+". Will ignore data's y level"); + LOGGER.warn("Data minY mismatch: " + minY + " != " + level.getMinY() + ". Will ignore data's y level"); } EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.fromValue(inputStream.readByte()); if (worldGenStep == null) { worldGenStep = EDhApiWorldGenerationStep.SURFACE; - LOGGER.warn("Missing WorldGenStep, defaulting to: "+worldGenStep.name()); + LOGGER.warn("Missing WorldGenStep, defaulting to: " + worldGenStep.name()); } @@ -178,13 +178,13 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp } else if (dataPresentFlag != IFullDataSource.DATA_GUARD_BYTE) { - throw new IOException("Invalid file format. Data Points guard byte expected: (no data) ["+IFullDataSource.NO_DATA_FLAG_BYTE+"] or (data present) ["+IFullDataSource.DATA_GUARD_BYTE+"], but found ["+dataPresentFlag+"]."); + throw new IOException("Invalid file format. Data Points guard byte expected: (no data) [" + IFullDataSource.NO_DATA_FLAG_BYTE + "] or (data present) [" + IFullDataSource.DATA_GUARD_BYTE + "], but found [" + dataPresentFlag + "]."); } // data column presence int length = inputStream.readInt(); - if (length < 0 || length > (WIDTH * WIDTH /8+64)*2) // TODO replace magic numbers or comment what they mean + if (length < 0 || length > (WIDTH * WIDTH / 8 + 64) * 2) // TODO replace magic numbers or comment what they mean { throw new IOException(LodUtil.formatLog("Spotty Flag BitSet size outside reasonable range: {} (expects {} to {})", length, 1, WIDTH * WIDTH / 8 + 63)); @@ -263,8 +263,8 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp // data // //======// - @Override - public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { return this.isColumnNotEmpty.get(relativeX * WIDTH + relativeZ) ? this.get(relativeX, relativeZ) : null; } + @Override + public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { return this.isColumnNotEmpty.get(relativeX * WIDTH + relativeZ) ? this.get(relativeX, relativeZ) : null; } @@ -277,14 +277,14 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp @Override public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); } @Override - public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; } + public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; } @Override public EDhApiWorldGenerationStep getWorldGenStep() { return this.worldGenStep; } @Override public boolean isEmpty() { return this.isEmpty; } - public void markNotEmpty() { this.isEmpty = false; } + public void markNotEmpty() { this.isEmpty = false; } @Override public int getWidthInDataPoints() { return WIDTH; } @@ -317,8 +317,8 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp this.isEmpty = false; SingleColumnFullDataAccessor columnFullDataAccessor = this.get(offsetX, offsetZ); - data.get(0,0).deepCopyTo(columnFullDataAccessor); - + data.get(0, 0).deepCopyTo(columnFullDataAccessor); + this.isColumnNotEmpty.set(offsetX * WIDTH + offsetZ, columnFullDataAccessor.doesColumnExist()); } else @@ -358,7 +358,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp else { // TODO implement - LodUtil.assertNotReach("SampleFrom not implemented for ["+this.getClass().getSimpleName()+"] with class ["+fullDataSource.getClass().getSimpleName()+"]."); + LodUtil.assertNotReach("SampleFrom not implemented for [" + this.getClass().getSimpleName() + "] with class [" + fullDataSource.getClass().getSimpleName() + "]."); } } @@ -518,13 +518,14 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp isPromoted = true; return new CompleteFullDataSource(this.sectionPos, this.mapping, this.dataArrays); } - + @Override - public boolean hasBeenPromoted() { + public boolean hasBeenPromoted() + { return isPromoted; } - - + + //================// // helper classes // //================// @@ -540,6 +541,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp this.dataPoints = dataPoints; this.isColumnNotEmpty = isColumnNotEmpty; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java index 889b30726..98af3e610 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java @@ -19,10 +19,10 @@ import java.util.LinkedList; /** * Base for all Full Data Source objects.

- * + * * Contains full DH data, methods related to file/stream reading/writing, and the data necessary to create {@link ColumnRenderSource}'s.
* {@link IFullDataSource}'s will either implement or contain {@link IFullDataAccessor}'s. - * + * * @see IFullDataAccessor * @see IIncompleteFullDataSource * @see IStreamableFullDataSource @@ -31,7 +31,7 @@ public interface IFullDataSource { /** * This is the byte put between different sections in the binary save file. - * The presence and absence of this byte indicates if the file is correctly formatted. + * The presence and absence of this byte indicates if the file is correctly formatted. */ int DATA_GUARD_BYTE = 0xFFFFFFFF; /** indicates the binary save file represents an empty data source */ @@ -59,19 +59,20 @@ public interface IFullDataSource // data // //======// - /** + /** * Attempts to get the data column for the given relative x and z position. + * * @return null if the data doesn't exist */ SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ); FullDataPointIdMap getMapping(); - /** + /** * @param highestGeneratorDetailLevel the smallest numerical detail level that the un-generated positions should be split into - * @return the list of {@link DhSectionPos} that aren't generated in this data source. + * @return the list of {@link DhSectionPos} that aren't generated in this data source. */ - default ArrayList getUngeneratedPosList(byte highestGeneratorDetailLevel, boolean onlyReturnPositionsTheGeneratorCanAccept) + default ArrayList getUngeneratedPosList(byte highestGeneratorDetailLevel, boolean onlyReturnPositionsTheGeneratorCanAccept) { ArrayList posArray = this.getUngeneratedPosList(this.getSectionPos(), highestGeneratorDetailLevel); @@ -154,7 +155,7 @@ public interface IFullDataSource } } } - + if (!quadrantFullyGenerated) { // at least 1 data point is missing, @@ -167,7 +168,7 @@ public interface IFullDataSource // TODO comment // TODO combine duplicate code - byte childDetailLevel = (byte) (quadrantPos.sectionDetailLevel-1); + byte childDetailLevel = (byte) (quadrantPos.sectionDetailLevel - 1); for (int i = 0; i < 4; i++) { @@ -244,14 +245,16 @@ public interface IFullDataSource //=======================// // TODO make this blow up in IStreamableFullDataSource instead of the children - /** - * Should only be implemented by {@link IStreamableFullDataSource} to prevent potential stream read/write inconsistencies. + /** + * Should only be implemented by {@link IStreamableFullDataSource} to prevent potential stream read/write inconsistencies. + * * @see IStreamableFullDataSource#writeToStream(DhDataOutputStream, IDhLevel) */ void writeToStream(DhDataOutputStream outputStream, IDhLevel level) throws IOException; - /** - * Should only be implemented by {@link IStreamableFullDataSource} to prevent potential stream read/write inconsistencies. + /** + * Should only be implemented by {@link IStreamableFullDataSource} to prevent potential stream read/write inconsistencies. + * * @see IStreamableFullDataSource#populateFromStream(FullDataMetaFile, DhDataInputStream, IDhLevel) */ void populateFromStream(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IIncompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IIncompleteFullDataSource.java index fbc797f05..5c00c7be4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IIncompleteFullDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IIncompleteFullDataSource.java @@ -6,17 +6,18 @@ public interface IIncompleteFullDataSource extends IFullDataSource { /** * Overwrites data in this object with non-null data from the input {@link IFullDataSource}.

- * - * This can be used to either merge same sized data sources or downsample to + * + * This can be used to either merge same sized data sources or downsample to */ void sampleFrom(IFullDataSource fullDataSource); - /** - * Attempts to convert this {@link IIncompleteFullDataSource} into a {@link CompleteFullDataSource}. - * + /** + * Attempts to convert this {@link IIncompleteFullDataSource} into a {@link CompleteFullDataSource}. + * * @return a new {@link CompleteFullDataSource} if successful, this if the promotion failed, . */ IFullDataSource tryPromotingToCompleteDataSource(); - + boolean hasBeenPromoted(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IStreamableFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IStreamableFullDataSource.java index 92d9fc146..88453aece 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IStreamableFullDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IStreamableFullDataSource.java @@ -12,19 +12,18 @@ import com.seibel.distanthorizons.core.util.objects.dataStreams.*; import java.io.IOException; /** - * This interface holds the complete method list necessary for reading and writing a {@link IFullDataSource} + * This interface holds the complete method list necessary for reading and writing a {@link IFullDataSource} * to and from data streams.

- * + * * This interface's purpose is to reduce the chance of accidentally mismatching read/write operation data types or content by splitting * up each read/write method into small easy to understand chunks. - * - * @apiNote James would've preferred to have this as an abstract class, - * however that is impossible. See the apiNote in - * {@link IStreamableFullDataSource#populateFromStream(FullDataMetaFile, DhDataInputStream, IDhLevel) populateFromStream} - * for the full reasoning. - * - * @param defines the object holding this data source's summary data, extends {@link IStreamableFullDataSource.FullDataSourceSummaryData}. + * + * @param defines the object holding this data source's summary data, extends {@link IStreamableFullDataSource.FullDataSourceSummaryData}. * @param defines the object holding the data points, probably long[][] or long[][][]. + * @apiNote James would've preferred to have this as an abstract class, + * however that is impossible. See the apiNote in + * {@link IStreamableFullDataSource#populateFromStream(FullDataMetaFile, DhDataInputStream, IDhLevel) populateFromStream} + * for the full reasoning. */ public interface IStreamableFullDataSource extends IFullDataSource { @@ -33,11 +32,11 @@ public interface IStreamableFullDataSource * This specifically checks any fields that should be set when the {@link IStreamableFullDataSource} was first constructed. - * + * * @throws IOException if the {@link FullDataMetaFile} isn't valid for this object. */ SummaryDataType readSourceSummaryInfo(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java index f5d5da4f2..3efe0effd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java @@ -19,7 +19,7 @@ import java.nio.ByteOrder; /** * Handles loading and parsing {@link RenderMetaDataFile}s to create {@link ColumnRenderSource}s.

- * + * * Please see the {@link ColumnRenderLoader#loadRenderSource} method to see what * file versions this class can handle. */ @@ -35,7 +35,7 @@ public class ColumnRenderLoader - public ColumnRenderSource loadRenderSource(RenderMetaDataFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException + public ColumnRenderSource loadRenderSource(RenderMetaDataFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException { int dataFileVersion = dataFile.baseMetaData.binaryDataFormatVersion; @@ -47,17 +47,17 @@ public class ColumnRenderLoader ParsedColumnData parsedColumnData = readDataV1(inputStream, level.getMinY()); if (parsedColumnData.isEmpty) { - LOGGER.warn("Empty render file "+dataFile.pos); + LOGGER.warn("Empty render file " + dataFile.pos); } return new ColumnRenderSource(dataFile.pos, parsedColumnData, level); default: - throw new IOException("Invalid Data: The data version ["+dataFileVersion+"] is not supported"); + throw new IOException("Invalid Data: The data version [" + dataFileVersion + "] is not supported"); } - } + } /** @throws InterruptedException see {@link FullDataToRenderDataTransformer#transformFullDataToColumnData(IDhClientLevel, CompleteFullDataSource) FullDataToRenderDataTransformer#transformFullDataToColumnData} for documentation */ - public ColumnRenderSource createRenderSource(IFullDataSource fullDataSource, IDhClientLevel level) throws InterruptedException + public ColumnRenderSource createRenderSource(IFullDataSource fullDataSource, IDhClientLevel level) throws InterruptedException { if (fullDataSource instanceof CompleteFullDataSource) { @@ -70,7 +70,7 @@ public class ColumnRenderLoader LodUtil.assertNotReach(); return null; - } + } @@ -80,8 +80,7 @@ public class ColumnRenderLoader /** * @param inputStream Expected format: 1st byte: detail level, 2nd byte: vertical size, 3rd byte on: column data - * - * @throws IOException if there was an issue reading the stream + * @throws IOException if there was an issue reading the stream */ private static ParsedColumnData readDataV1(DhDataInputStream inputStream, int expectedYOffset) throws IOException { @@ -101,7 +100,7 @@ public class ColumnRenderLoader byte dataPresentFlag = inputStream.readByte(); if (dataPresentFlag != ColumnRenderSource.NO_DATA_FLAG_BYTE && dataPresentFlag != ColumnRenderSource.DATA_GUARD_BYTE) { - throw new IOException("Incorrect render file format. Expected either: NO_DATA_FLAG_BYTE ["+ColumnRenderSource.NO_DATA_FLAG_BYTE+"] or DATA_GUARD_BYTE ["+ColumnRenderSource.DATA_GUARD_BYTE+"], Found: ["+dataPresentFlag+"]"); + throw new IOException("Incorrect render file format. Expected either: NO_DATA_FLAG_BYTE [" + ColumnRenderSource.NO_DATA_FLAG_BYTE + "] or DATA_GUARD_BYTE [" + ColumnRenderSource.DATA_GUARD_BYTE + "], Found: [" + dataPresentFlag + "]"); } else if (dataPresentFlag == ColumnRenderSource.NO_DATA_FLAG_BYTE) { @@ -115,7 +114,7 @@ public class ColumnRenderLoader int fileYOffset = inputStream.readInt(); if (fileYOffset != expectedYOffset) { - throw new IOException("Invalid data: yOffset is incorrect. Expected: ["+expectedYOffset+"], found: ["+fileYOffset+"]."); + throw new IOException("Invalid data: yOffset is incorrect. Expected: [" + expectedYOffset + "], found: [" + fileYOffset + "]."); } @@ -149,7 +148,7 @@ public class ColumnRenderLoader EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.fromValue(inputStream.readByte()); if (worldGenStep == null) { - LOGGER.warn("Missing WorldGenStep, defaulting to: "+EDhApiWorldGenerationStep.SURFACE.name()); + LOGGER.warn("Missing WorldGenStep, defaulting to: " + EDhApiWorldGenerationStep.SURFACE.name()); worldGenStep = EDhApiWorldGenerationStep.SURFACE; } @@ -175,6 +174,7 @@ public class ColumnRenderLoader this.dataContainer = dataContainer; this.isEmpty = isEmpty; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java index 720e85aad..9eb09fad1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java @@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicLong; /** * Stores the render data used to generate OpenGL buffers. * - * @see RenderDataPointUtil + * @see RenderDataPointUtil */ public class ColumnRenderSource { @@ -39,7 +39,7 @@ public class ColumnRenderSource /** * This is the byte put between different sections in the binary save file. - * The presence and absence of this byte indicates if the file is correctly formatted. + * The presence and absence of this byte indicates if the file is correctly formatted. */ public static final int DATA_GUARD_BYTE = 0xFFFFFFFF; /** indicates the binary save file represents an empty data source */ @@ -57,7 +57,7 @@ public class ColumnRenderSource private boolean isEmpty = true; public EDhApiWorldGenerationStep worldGenStep; - + public AtomicLong localVersion = new AtomicLong(0); // used to track changes to the data source, so that buffers can be updated when necessary //==============// @@ -67,7 +67,7 @@ public class ColumnRenderSource public static ColumnRenderSource createEmptyRenderSource(DhSectionPos sectionPos) { return new ColumnRenderSource(sectionPos, 0, 0); } /** * Creates an empty ColumnRenderSource. - * + * * @param sectionPos the relative position of the container * @param maxVerticalSize the maximum vertical size of the container */ @@ -83,7 +83,7 @@ public class ColumnRenderSource /** * Creates a new ColumnRenderSource from the parsedColumnData. - * + * * @throws IOException if the DataInputStream's detail level isn't what was expected */ public ColumnRenderSource(DhSectionPos sectionPos, ColumnRenderLoader.ParsedColumnData parsedColumnData, IDhLevel level) throws IOException @@ -241,7 +241,7 @@ public class ColumnRenderSource } // the source isn't empty, this object won't be empty after the method finishes this.isEmpty = false; - + for (int i = 0; i < this.renderDataContainer.length; i += this.verticalDataCount) { int thisGenMode = RenderDataPointUtil.getGenerationMode(this.renderDataContainer[i]); @@ -264,7 +264,7 @@ public class ColumnRenderSource } } } - /** + /** * If the newVerticalSize is different than the current verticalSize, * this will delete any data currently in this object and re-size it.
* Otherwise this method will do nothing. @@ -282,23 +282,25 @@ public class ColumnRenderSource { try { - if (FullDataToRenderDataTransformer.writeFullDataChunkToColumnData(this, level, chunkData)) { + if (FullDataToRenderDataTransformer.writeFullDataChunkToColumnData(this, level, chunkData)) + { localVersion.incrementAndGet(); return true; } - else { + else + { return false; } } catch (InterruptedException e) { // expected if the transformer is shut down, the exception can be ignored - LOGGER.warn(ColumnRenderSource.class.getSimpleName()+" fast write interrupted."); + LOGGER.warn(ColumnRenderSource.class.getSimpleName() + " fast write interrupted."); } catch (Throwable e) { // shouldn't happen, but just in case - LOGGER.warn("Unable to complete fastWrite for RenderSource pos: ["+this.sectionPos+"] and chunk pos: ["+chunkData.pos+"].", e); + LOGGER.warn("Unable to complete fastWrite for RenderSource pos: [" + this.sectionPos + "] and chunk pos: [" + chunkData.pos + "].", e); } return false; } @@ -329,10 +331,10 @@ public class ColumnRenderSource /** @return how many data points wide this {@link ColumnRenderSource} is. */ public int getWidthInDataPoints() { return BitShiftUtil.powerOfTwo(this.getDetailOffset()); } public byte getDetailOffset() { return SECTION_SIZE_OFFSET; } - + public byte getRenderDataFormatVersion() { return DATA_FORMAT_VERSION; } - /** + /** * Whether this object is still valid. If not, a new one should be created. * TODO this will be necessary for dedicated multiplayer support, if the server has newer data this section should no longer be valid */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java index 7c96ef1ea..555dc8fdc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/BufferQuad.java @@ -26,16 +26,17 @@ import com.seibel.distanthorizons.core.util.LodUtil; /** Represents a render-able quad. */ public final class BufferQuad { - /** - * The maximum number of blocks wide a quad can be.

- * - * This could be increased beyond 2048, for use with + /** + * The maximum number of blocks wide a quad can be.

+ * + * This could be increased beyond 2048, for use with * extremely low detail levels if the need arises. */ public static final int NORMAL_MAX_QUAD_WIDTH = 2048; - /** The maximum number of blocks wide a quad can be - * when {@link Config.Client.Advanced.Graphics.AdvancedGraphics#earthCurveRatio earthCurveRatio} - * is enabled. + /** + * The maximum number of blocks wide a quad can be + * when {@link Config.Client.Advanced.Graphics.AdvancedGraphics#earthCurveRatio earthCurveRatio} + * is enabled. */ public static final int MAX_QUAD_WIDTH_FOR_EARTH_CURVATURE = LodUtil.CHUNK_WIDTH; @@ -48,8 +49,9 @@ public final class BufferQuad /** This is both North/South and Up/Down since the merging logic is the same either way */ public short widthNorthSouthOrUpDown; - /** - * not final since it may need to be modified to be opaque + /** + * not final since it may need to be modified to be opaque + * * @see LodQuadBuilder#fixTransparencyOverVoid */ public int color; @@ -62,7 +64,8 @@ public final class BufferQuad - BufferQuad(short x, short y, short z, short widthEastWest, short widthNorthSouthOrUpDown, + BufferQuad( + short x, short y, short z, short widthEastWest, short widthNorthSouthOrUpDown, int color, byte skylight, byte blockLight, EDhDirection direction) { @@ -100,30 +103,30 @@ public final class BufferQuad { switch (this.direction.getAxis()) { - case X: - return threeDimensionalCompare(this.x, this.y, this.z, quad.x, quad.y, quad.z); - case Y: - return threeDimensionalCompare(this.y, this.z, this.x, quad.y, quad.z, quad.x); - case Z: - return threeDimensionalCompare(this.z, this.y, this.x, quad.z, quad.y, quad.x); + case X: + return threeDimensionalCompare(this.x, this.y, this.z, quad.x, quad.y, quad.z); + case Y: + return threeDimensionalCompare(this.y, this.z, this.x, quad.y, quad.z, quad.x); + case Z: + return threeDimensionalCompare(this.z, this.y, this.x, quad.z, quad.y, quad.x); - default: - throw new IllegalArgumentException("Invalid Axis enum: " + this.direction.getAxis()); + default: + throw new IllegalArgumentException("Invalid Axis enum: " + this.direction.getAxis()); } } else { switch (this.direction.getAxis()) { - case X: - return threeDimensionalCompare(this.x, this.z, this.y, quad.x, quad.z, quad.y); - case Y: - return threeDimensionalCompare(this.y, this.x, this.z, quad.y, quad.x, quad.z); - case Z: - return threeDimensionalCompare(this.z, this.x, this.y, quad.z, quad.x, quad.y); - - default: - throw new IllegalArgumentException("Invalid Axis enum: " + this.direction.getAxis()); + case X: + return threeDimensionalCompare(this.x, this.z, this.y, quad.x, quad.z, quad.y); + case Y: + return threeDimensionalCompare(this.y, this.x, this.z, quad.y, quad.x, quad.z); + case Z: + return threeDimensionalCompare(this.z, this.x, this.y, quad.z, quad.x, quad.y); + + default: + throw new IllegalArgumentException("Invalid Axis enum: " + this.direction.getAxis()); } } } @@ -143,11 +146,12 @@ public final class BufferQuad /** * Attempts to merge the given quad into this one. + * * @return true if the quads were merged, false otherwise. */ public boolean tryMerge(BufferQuad quad, BufferMergeDirectionEnum mergeDirection) { - if (quad.hasError || this.hasError) + if (quad.hasError || this.hasError) return false; // only merge quads that are in the same direction if (this.direction != quad.direction) @@ -168,63 +172,63 @@ public final class BufferQuad short otherParallelCompareStartPos; switch (this.direction.getAxis()) { - default: // shouldn't normally happen, just here to make the compiler happy - case X: - if (mergeDirection == BufferMergeDirectionEnum.EastWest) - { - thisPerpendicularCompareStartPos = this.z; - thisParallelCompareStartPos = this.x; - - otherPerpendicularCompareStartPos = quad.z; - otherParallelCompareStartPos = quad.x; - } - else //if (mergeDirection == MergeDirection.NorthSouthOrUpDown) - { - thisPerpendicularCompareStartPos = this.y; - thisParallelCompareStartPos = this.z; - - otherPerpendicularCompareStartPos = quad.y; - otherParallelCompareStartPos = quad.z; - } - break; - - case Y: - if (mergeDirection == BufferMergeDirectionEnum.EastWest) - { - thisPerpendicularCompareStartPos = this.x; - thisParallelCompareStartPos = this.z; - - otherPerpendicularCompareStartPos = quad.x; - otherParallelCompareStartPos = quad.z; - } - else //if (mergeDirection == MergeDirection.NorthSouthOrUpDown) - { - thisPerpendicularCompareStartPos = this.z; - thisParallelCompareStartPos = this.y; - - otherPerpendicularCompareStartPos = quad.z; - otherParallelCompareStartPos = quad.y; - } - break; - - case Z: - if (mergeDirection == BufferMergeDirectionEnum.EastWest) - { - thisPerpendicularCompareStartPos = this.x; - thisParallelCompareStartPos = this.z; - - otherPerpendicularCompareStartPos = quad.x; - otherParallelCompareStartPos = quad.z; - } - else //if (mergeDirection == MergeDirection.NorthSouthOrUpDown) - { - thisPerpendicularCompareStartPos = this.y; - thisParallelCompareStartPos = this.z; - - otherPerpendicularCompareStartPos = quad.y; - otherParallelCompareStartPos = quad.z; - } - break; + default: // shouldn't normally happen, just here to make the compiler happy + case X: + if (mergeDirection == BufferMergeDirectionEnum.EastWest) + { + thisPerpendicularCompareStartPos = this.z; + thisParallelCompareStartPos = this.x; + + otherPerpendicularCompareStartPos = quad.z; + otherParallelCompareStartPos = quad.x; + } + else //if (mergeDirection == MergeDirection.NorthSouthOrUpDown) + { + thisPerpendicularCompareStartPos = this.y; + thisParallelCompareStartPos = this.z; + + otherPerpendicularCompareStartPos = quad.y; + otherParallelCompareStartPos = quad.z; + } + break; + + case Y: + if (mergeDirection == BufferMergeDirectionEnum.EastWest) + { + thisPerpendicularCompareStartPos = this.x; + thisParallelCompareStartPos = this.z; + + otherPerpendicularCompareStartPos = quad.x; + otherParallelCompareStartPos = quad.z; + } + else //if (mergeDirection == MergeDirection.NorthSouthOrUpDown) + { + thisPerpendicularCompareStartPos = this.z; + thisParallelCompareStartPos = this.y; + + otherPerpendicularCompareStartPos = quad.z; + otherParallelCompareStartPos = quad.y; + } + break; + + case Z: + if (mergeDirection == BufferMergeDirectionEnum.EastWest) + { + thisPerpendicularCompareStartPos = this.x; + thisParallelCompareStartPos = this.z; + + otherPerpendicularCompareStartPos = quad.x; + otherParallelCompareStartPos = quad.z; + } + else //if (mergeDirection == MergeDirection.NorthSouthOrUpDown) + { + thisPerpendicularCompareStartPos = this.y; + thisParallelCompareStartPos = this.z; + + otherPerpendicularCompareStartPos = quad.y; + otherParallelCompareStartPos = quad.z; + } + break; } // get the width of this quad in the relevant axis @@ -236,7 +240,7 @@ public final class BufferQuad { thisPerpendicularCompareWidth = this.widthEastWest; thisParallelCompareWidth = this.widthNorthSouthOrUpDown; - + otherPerpendicularCompareWidth = quad.widthEastWest; otherParallelCompareWidth = quad.widthNorthSouthOrUpDown; } @@ -244,11 +248,11 @@ public final class BufferQuad { thisPerpendicularCompareWidth = this.widthNorthSouthOrUpDown; thisParallelCompareWidth = this.widthEastWest; - + otherPerpendicularCompareWidth = quad.widthNorthSouthOrUpDown; otherParallelCompareWidth = quad.widthEastWest; } - + // quad width should only be limited when earth curvature is enabled @@ -264,7 +268,7 @@ public final class BufferQuad return false; } if (Math.floorDiv(otherPerpendicularCompareStartPos, maxQuadWidth) - != Math.floorDiv(thisPerpendicularCompareStartPos, maxQuadWidth)) + != Math.floorDiv(thisPerpendicularCompareStartPos, maxQuadWidth)) { return false; } @@ -272,14 +276,15 @@ public final class BufferQuad // check if these quads are adjacent if (thisPerpendicularCompareStartPos + thisPerpendicularCompareWidth < otherPerpendicularCompareStartPos || - thisParallelCompareStartPos != otherParallelCompareStartPos) + thisParallelCompareStartPos != otherParallelCompareStartPos) { // these quads aren't adjacent, they can't be merged return false; } else if (thisPerpendicularCompareStartPos + thisPerpendicularCompareWidth > otherPerpendicularCompareStartPos) { - if (thisPerpendicularCompareStartPos < otherPerpendicularCompareStartPos + otherPerpendicularCompareWidth) { + if (thisPerpendicularCompareStartPos < otherPerpendicularCompareStartPos + otherPerpendicularCompareWidth) + { // these quads are overlapping, they can't be merged //EVENT_LOGGER.warn("Overlapping quads detected!"); quad.hasError = true; @@ -287,7 +292,7 @@ public final class BufferQuad } return false; } - + // only merge quads that have the same width edges if (thisParallelCompareWidth != otherParallelCompareWidth) { @@ -296,8 +301,8 @@ public final class BufferQuad // do the quads' color, light, etc. match? if (this.color != quad.color || - this.skyLight != quad.skyLight || - this.blockLight != quad.blockLight) + this.skyLight != quad.skyLight || + this.blockLight != quad.blockLight) { // we can only merge identically colored/lit quads return false; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java index 17ce6c588..ca0ffe467 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java @@ -30,22 +30,22 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil; public class ColumnBox { - private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - public static void addBoxQuadsToBuilder( - LodQuadBuilder builder, - short xSize, short ySize, short zSize, - short x, short minY, short z, - int color, byte skyLight, byte blockLight, + public static void addBoxQuadsToBuilder( + LodQuadBuilder builder, + short xSize, short ySize, short zSize, + short x, short minY, short z, + int color, byte skyLight, byte blockLight, long topData, long bottomData, ColumnArrayView[][] adjData) { - short maxX = (short) (x + xSize); - short maxY = (short) (minY + ySize); - short maxZ = (short) (z + zSize); - byte skyLightTop = skyLight; - byte skyLightBot = RenderDataPointUtil.doesDataPointExist(bottomData) ? RenderDataPointUtil.getLightSky(bottomData) : 0; + short maxX = (short) (x + xSize); + short maxY = (short) (minY + ySize); + short maxZ = (short) (z + zSize); + byte skyLightTop = skyLight; + byte skyLightBot = RenderDataPointUtil.doesDataPointExist(bottomData) ? RenderDataPointUtil.getLightSky(bottomData) : 0; - boolean isTransparent = ColorUtil.getAlpha(color) < 255 && LodRenderer.transparencyEnabled; + boolean isTransparent = ColorUtil.getAlpha(color) < 255 && LodRenderer.transparencyEnabled; boolean overVoid = !RenderDataPointUtil.doesDataPointExist(bottomData); boolean isTopTransparent = RenderDataPointUtil.getAlpha(topData) < 255 && LodRenderer.transparencyEnabled; boolean isBottomTransparent = RenderDataPointUtil.getAlpha(bottomData) < 255 && LodRenderer.transparencyEnabled; @@ -61,22 +61,22 @@ public class ColumnBox // cave culling prevention // prevents certain faces from being culled underground that should be allowed if (builder.skipQuadsWithZeroSkylight - && 0 == skyLight - && builder.skyLightCullingBelow > maxY - && + && 0 == skyLight + && builder.skyLightCullingBelow > maxY + && ( - (RenderDataPointUtil.getAlpha(topData) < 255 && RenderDataPointUtil.getYMax(topData) >= builder.skyLightCullingBelow) - || (RenderDataPointUtil.getYMin(topData) >= builder.skyLightCullingBelow) - || !RenderDataPointUtil.doesDataPointExist(topData) + (RenderDataPointUtil.getAlpha(topData) < 255 && RenderDataPointUtil.getYMax(topData) >= builder.skyLightCullingBelow) + || (RenderDataPointUtil.getYMin(topData) >= builder.skyLightCullingBelow) + || !RenderDataPointUtil.doesDataPointExist(topData) ) - ) + ) { - maxY = builder.skyLightCullingBelow; - } + maxY = builder.skyLightCullingBelow; + } - // fake ocean transparency + // fake ocean transparency if (LodRenderer.transparencyEnabled && LodRenderer.fakeOceanFloor) { if (!isTransparent && isTopTransparent && RenderDataPointUtil.doesDataPointExist(topData)) @@ -98,13 +98,13 @@ public class ColumnBox // add top and bottom faces if requested // boolean skipTop = RenderDataPointUtil.doesDataPointExist(topData) && (RenderDataPointUtil.getYMin(topData) == maxY) && !isTopTransparent; - if (!skipTop) + if (!skipTop) { builder.addQuadUp(x, maxY, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(EDhDirection.UP)), skyLightTop, blockLight); } boolean skipBottom = RenderDataPointUtil.doesDataPointExist(bottomData) && (RenderDataPointUtil.getYMax(bottomData) == minY) && !isBottomTransparent; - if (!skipBottom) + if (!skipBottom) { builder.addQuadDown(x, minY, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(EDhDirection.DOWN)), skyLightBot, blockLight); } @@ -113,8 +113,8 @@ public class ColumnBox // add North, south, east, and west faces if requested // // TODO merge duplicate code - //NORTH face vertex creation - { + //NORTH face vertex creation + { ColumnArrayView[] adjDataNorth = adjData[EDhDirection.NORTH.ordinal() - 2]; // TODO can we use something other than ordinal-2? int adjOverlapNorth = ColorUtil.INVISIBLE; if (adjDataNorth == null) @@ -140,11 +140,11 @@ public class ColumnBox color, adjOverlapNorth, skyLightTop, blockLight, topData, bottomData); } - } - - //SOUTH face vertex creation - { - ColumnArrayView[] adjDataSouth = adjData[EDhDirection.SOUTH.ordinal() - 2]; + } + + //SOUTH face vertex creation + { + ColumnArrayView[] adjDataSouth = adjData[EDhDirection.SOUTH.ordinal() - 2]; int adjOverlapSouth = ColorUtil.INVISIBLE; if (adjDataSouth == null) { @@ -162,16 +162,16 @@ public class ColumnBox makeAdjVerticalQuad(builder, adjDataSouth[0], EDhDirection.SOUTH, x, minY, maxZ, (short) (xSize / 2), ySize, color, adjOverlapSouth, skyLightTop, blockLight, topData, bottomData); - + makeAdjVerticalQuad(builder, adjDataSouth[1], EDhDirection.SOUTH, (short) (x + xSize / 2), minY, maxZ, (short) (xSize / 2), ySize, color, adjOverlapSouth, skyLightTop, blockLight, topData, bottomData); } - } - - //WEST face vertex creation - { - ColumnArrayView[] adjDataWest = adjData[EDhDirection.WEST.ordinal() - 2]; + } + + //WEST face vertex creation + { + ColumnArrayView[] adjDataWest = adjData[EDhDirection.WEST.ordinal() - 2]; int adjOverlapWest = ColorUtil.INVISIBLE; if (adjDataWest == null) { @@ -193,11 +193,11 @@ public class ColumnBox color, adjOverlapWest, skyLightTop, blockLight, topData, bottomData); } - } + } - //EAST face vertex creation - { - ColumnArrayView[] adjDataEast = adjData[EDhDirection.EAST.ordinal() - 2]; + //EAST face vertex creation + { + ColumnArrayView[] adjDataEast = adjData[EDhDirection.EAST.ordinal() - 2]; int adjOverlapEast = ColorUtil.INVISIBLE; if (adjData[EDhDirection.EAST.ordinal() - 2] == null) { @@ -219,13 +219,13 @@ public class ColumnBox color, adjOverlapEast, skyLightTop, blockLight, topData, bottomData); } - } - } + } + } // the overlap color can be used to see faces that shouldn't be rendered - private static void makeAdjVerticalQuad( - LodQuadBuilder builder, ColumnArrayView adjColumnView, EDhDirection direction, - short x, short yMin, short z, short horizontalWidth, short ySize, + private static void makeAdjVerticalQuad( + LodQuadBuilder builder, ColumnArrayView adjColumnView, EDhDirection direction, + short x, short yMin, short z, short horizontalWidth, short ySize, int color, int debugOverlapColor, byte skyLightTop, byte blockLight, long topData, long bottomData) { @@ -241,13 +241,13 @@ public class ColumnBox int yMax = yMin + ySize; - int adjIndex; - boolean firstFace = true; - boolean inputAboveAdjLods = true; - short previousAdjDepth = -1; - byte nextTopSkyLight = skyLightTop; - boolean inputTransparent = ColorUtil.getAlpha(color) < 255 && LodRenderer.transparencyEnabled; - boolean lastAdjWasTransparent = false; + int adjIndex; + boolean firstFace = true; + boolean inputAboveAdjLods = true; + short previousAdjDepth = -1; + byte nextTopSkyLight = skyLightTop; + boolean inputTransparent = ColorUtil.getAlpha(color) < 255 && LodRenderer.transparencyEnabled; + boolean lastAdjWasTransparent = false; @@ -263,10 +263,10 @@ public class ColumnBox // (prevents invisible sides underwater) int adjCount = adjColumnView.size(); for (adjIndex = 0; // iterates top down - adjIndex < adjCount - && RenderDataPointUtil.doesDataPointExist(adjColumnView.get(adjIndex)) - && !RenderDataPointUtil.isVoid(adjColumnView.get(adjIndex)); - adjIndex++) + adjIndex < adjCount + && RenderDataPointUtil.doesDataPointExist(adjColumnView.get(adjIndex)) + && !RenderDataPointUtil.isVoid(adjColumnView.get(adjIndex)); + adjIndex++) { long adjPoint = adjColumnView.get(adjIndex); boolean adjTransparent = RenderDataPointUtil.getAlpha(adjPoint) < 255 && LodRenderer.transparencyEnabled; @@ -287,7 +287,7 @@ public class ColumnBox { adjYMax = (short) (RenderDataPointUtil.getYMax(adjColumnView.get(adjIndex - 1)) - 1); } - else if (adjTransparent && (adjIndex+1) < adjCount) + else if (adjTransparent && (adjIndex + 1) < adjCount) { if (RenderDataPointUtil.getAlpha(adjColumnView.get(adjIndex + 1)) == 255) { @@ -319,10 +319,10 @@ public class ColumnBox // its sky lighting won't be affected by anything above it skyLight = RenderDataPointUtil.getLightSky(adjPoint); } - else + else { // TODO improve the comments here, this is a bit confusing - long aboveAdjPoint = adjColumnView.get(adjIndex-1); + long aboveAdjPoint = adjColumnView.get(adjIndex - 1); if (RenderDataPointUtil.getAlpha(aboveAdjPoint) != 255) { // above adjacent LOD is transparent... @@ -497,5 +497,6 @@ public class ColumnBox // We need to finish the last quad. builder.addQuadAdj(direction, x, yMin, z, horizontalWidth, (short) (previousAdjDepth - yMin), color, nextTopSkyLight, blockLight); } - } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java index 6ba7cbfcf..f651207fc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java @@ -23,7 +23,7 @@ import java.util.concurrent.*; /** * Java representation of one or more OpenGL buffers for rendering. - * + * * @see ColumnRenderBufferBuilder */ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRenderable @@ -38,9 +38,9 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe public boolean buffersUploaded = false; private GLVertexBuffer[] vbos; - private GLVertexBuffer[] vbosTransparent; + private GLVertexBuffer[] vbosTransparent; private boolean closed = false; - + private final DhSectionPos debugPos; @@ -56,10 +56,11 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe vbosTransparent = new GLVertexBuffer[0]; DebugRenderer.register(this); } - + public void debugRender(DebugRenderer r) { - if (closed || vbos == null) { + if (closed || vbos == null) + { return; } Color c = Color.green; @@ -194,7 +195,7 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe // render // //========// - @Override + @Override public boolean renderOpaque(LodRenderer renderContext) { boolean hasRendered = false; @@ -218,7 +219,7 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe return hasRendered; } - @Override + @Override public boolean renderTransparent(LodRenderer renderContext) { boolean hasRendered = false; @@ -250,8 +251,8 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe // misc methods // //==============// - @Override - public void debugDumpStats(StatsMap statsMap) + @Override + public void debugDumpStats(StatsMap statsMap) { statsMap.incStat("RenderBuffers"); statsMap.incStat("SimpleRenderBuffers"); @@ -274,17 +275,17 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe } } - @Override - public void close() + @Override + public void close() { - if (this.closed) + if (this.closed) { return; } this.closed = true; this.buffersUploaded = false; - GLProxy.getInstance().recordOpenGlCall(() -> + GLProxy.getInstance().recordOpenGlCall(() -> { for (GLVertexBuffer buffer : this.vbos) { @@ -301,6 +302,7 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe buffer.destroy(false); } } - }); - } + }); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java index b1e73a0fb..b2fe58c57 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java @@ -29,7 +29,7 @@ import java.util.concurrent.ThreadPoolExecutor; /** * Used to populate the buffers in a {@link ColumnRenderSource} object. - * + * * @see ColumnRenderSource */ public class ColumnRenderBufferBuilder @@ -52,9 +52,9 @@ public class ColumnRenderBufferBuilder //==============// // vbo building // //==============// - + public static CompletableFuture buildBuffersAsync( - IDhClientLevel clientLevel, Reference renderBufferRef, + IDhClientLevel clientLevel, Reference renderBufferRef, ColumnRenderSource renderSource, ColumnRenderSource[] adjData) { /* if (isBusy()) @@ -63,91 +63,91 @@ public class ColumnRenderBufferBuilder }*/ //LOGGER.info("RenderRegion startBuild @ {}", renderSource.sectionPos); return CompletableFuture.supplyAsync(() -> - { - try { - boolean enableTransparency = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; - - EVENT_LOGGER.trace("RenderRegion start QuadBuild @ "+renderSource.sectionPos); - boolean enableSkyLightCulling = Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get(); - - int skyLightCullingBelow = Config.Client.Advanced.Graphics.AdvancedGraphics.caveCullingHeight.get(); - // FIXME: Clamp also to the max world height. - skyLightCullingBelow = Math.max(skyLightCullingBelow, clientLevel.getMinY()); - - LodQuadBuilder builder = new LodQuadBuilder(enableSkyLightCulling, - (short) (skyLightCullingBelow - clientLevel.getMinY()), enableTransparency); - - makeLodRenderData(builder, renderSource, adjData); - EVENT_LOGGER.trace("RenderRegion end QuadBuild @ "+renderSource.sectionPos); - return builder; - } - catch (UncheckedInterruptedException e) - { - throw e; - } - catch (Throwable e3) - { - LOGGER.error("\"LodNodeBufferBuilder\" was unable to build quads: ", e3); - throw e3; - } - }, bufferBuilderThreadPool) - .thenApplyAsync((quadBuilder) -> - { - try - { - EVENT_LOGGER.trace("RenderRegion start Upload @ "+renderSource.sectionPos); - GLProxy glProxy = GLProxy.getInstance(); - EGpuUploadMethod method = GLProxy.getInstance().getGpuUploadMethod(); - EGLProxyContext oldContext = glProxy.getGlContext(); - glProxy.setGlContext(EGLProxyContext.LOD_BUILDER); - ColumnRenderBuffer buffer = renderBufferRef.swap(null); - - if (buffer == null) - { - buffer = new ColumnRenderBuffer(new DhBlockPos(renderSource.sectionPos.getCorner().getCornerBlockPos(), clientLevel.getMinY()), renderSource.sectionPos); - } - try { - buffer.uploadBuffer(quadBuilder, method); - LodUtil.assertTrue(buffer.buffersUploaded); - EVENT_LOGGER.trace("RenderRegion end Upload @ "+renderSource.sectionPos); - return buffer; + boolean enableTransparency = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; + + EVENT_LOGGER.trace("RenderRegion start QuadBuild @ " + renderSource.sectionPos); + boolean enableSkyLightCulling = Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get(); + + int skyLightCullingBelow = Config.Client.Advanced.Graphics.AdvancedGraphics.caveCullingHeight.get(); + // FIXME: Clamp also to the max world height. + skyLightCullingBelow = Math.max(skyLightCullingBelow, clientLevel.getMinY()); + + LodQuadBuilder builder = new LodQuadBuilder(enableSkyLightCulling, + (short) (skyLightCullingBelow - clientLevel.getMinY()), enableTransparency); + + makeLodRenderData(builder, renderSource, adjData); + EVENT_LOGGER.trace("RenderRegion end QuadBuild @ " + renderSource.sectionPos); + return builder; } - catch (Exception e) + catch (UncheckedInterruptedException e) { - buffer.close(); throw e; } - finally + catch (Throwable e3) { - glProxy.setGlContext(oldContext); + LOGGER.error("\"LodNodeBufferBuilder\" was unable to build quads: ", e3); + throw e3; } - } - catch (InterruptedException e) + }, bufferBuilderThreadPool) + .thenApplyAsync((quadBuilder) -> { - throw UncheckedInterruptedException.convert(e); - } - catch (Throwable e3) - { - LOGGER.error("\"LodNodeBufferBuilder\" was unable to upload buffer: ", e3); - throw e3; - } - }, bufferUploaderThreadPool) - .handle((columnRenderBuffer, ex) -> + try + { + EVENT_LOGGER.trace("RenderRegion start Upload @ " + renderSource.sectionPos); + GLProxy glProxy = GLProxy.getInstance(); + EGpuUploadMethod method = GLProxy.getInstance().getGpuUploadMethod(); + EGLProxyContext oldContext = glProxy.getGlContext(); + glProxy.setGlContext(EGLProxyContext.LOD_BUILDER); + ColumnRenderBuffer buffer = renderBufferRef.swap(null); + + if (buffer == null) + { + buffer = new ColumnRenderBuffer(new DhBlockPos(renderSource.sectionPos.getCorner().getCornerBlockPos(), clientLevel.getMinY()), renderSource.sectionPos); + } + + try + { + buffer.uploadBuffer(quadBuilder, method); + LodUtil.assertTrue(buffer.buffersUploaded); + EVENT_LOGGER.trace("RenderRegion end Upload @ " + renderSource.sectionPos); + return buffer; + } + catch (Exception e) + { + buffer.close(); + throw e; + } + finally + { + glProxy.setGlContext(oldContext); + } + } + catch (InterruptedException e) + { + throw UncheckedInterruptedException.convert(e); + } + catch (Throwable e3) + { + LOGGER.error("\"LodNodeBufferBuilder\" was unable to upload buffer: ", e3); + throw e3; + } + }, bufferUploaderThreadPool) + .handle((columnRenderBuffer, ex) -> { //LOGGER.info("RenderRegion endBuild @ {}", renderSource.sectionPos); if (ex != null) { - LOGGER.warn("Buffer building failed: "+ex.getMessage(), ex); - + LOGGER.warn("Buffer building failed: " + ex.getMessage(), ex); + if (!renderBufferRef.isEmpty()) { ColumnRenderBuffer buffer = renderBufferRef.swap(null); buffer.close(); } - + return null; } else @@ -225,7 +225,7 @@ public class ColumnRenderBufferBuilder int zAdj = z + lodDirection.getNormal().z; boolean isCrossRegionBoundary = (xAdj < 0 || xAdj >= ColumnRenderSource.SECTION_SIZE) || - (zAdj < 0 || zAdj >= ColumnRenderSource.SECTION_SIZE); + (zAdj < 0 || zAdj >= ColumnRenderSource.SECTION_SIZE); ColumnRenderSource adjRenderSource; byte adjDetailLevel; @@ -288,7 +288,7 @@ public class ColumnRenderBufferBuilder } catch (RuntimeException e) { - EVENT_LOGGER.warn("Failed to get adj data for ["+detailLevel+":"+x+","+z+"] at ["+lodDirection+"]"); + EVENT_LOGGER.warn("Failed to get adj data for [" + detailLevel + ":" + x + "," + z + "] at [" + lodDirection + "]"); EVENT_LOGGER.warn("Detail exception: ", e); } } // for adjacent directions @@ -383,11 +383,11 @@ public class ColumnRenderBufferBuilder if (bufferBuilderThreadPool == null || bufferBuilderThreadPool.isTerminated()) { - LOGGER.info("Starting "+ ColumnRenderBufferBuilder.class.getSimpleName()); + LOGGER.info("Starting " + ColumnRenderBufferBuilder.class.getSimpleName()); setThreadPoolSize(Config.Client.Advanced.MultiThreading.numberOfBufferBuilderThreads.get()); } } - public static void setThreadPoolSize(int threadPoolSize) + public static void setThreadPoolSize(int threadPoolSize) { if (bufferBuilderThreadPool != null) { @@ -407,7 +407,7 @@ public class ColumnRenderBufferBuilder { if (bufferBuilderThreadPool != null) { - LOGGER.info("Stopping "+ColumnRenderBufferBuilder.class.getSimpleName()); + LOGGER.info("Stopping " + ColumnRenderBufferBuilder.class.getSimpleName()); bufferBuilderThreadPool.shutdownNow(); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java index dea4ae9e8..1782a0ebf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java @@ -31,15 +31,16 @@ import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; /** * Builds LODs as rectangular prisms. + * * @author James Seibel * @version 2022-1-2 */ public class CubicLodTemplate { - + public static void addLodToBuffer( long data, long topData, long bottomData, ColumnArrayView[][] adjColumnViews, - byte detailLevel, int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, + byte detailLevel, int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, EDebugRendering debugging, ColumnRenderSource.DebugSourceFlag debugSource) { DhLodPos blockOffsetPos = new DhLodPos(detailLevel, offsetPosX, offsetOosZ).convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL); @@ -63,7 +64,8 @@ public class CubicLodTemplate int color; boolean fullBright = false; - switch (debugging) { + switch (debugging) + { case OFF: { float saturationMultiplier = Config.Client.Advanced.Graphics.AdvancedGraphics.saturationMultiplier.get().floatValue(); @@ -119,4 +121,5 @@ public class CubicLodTemplate fullBright ? 15 : RenderDataPointUtil.getLightBlock(data), // setBlockLights topData, bottomData, adjColumnViews); // setAdjData } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java index 2b23b4a62..78862959d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java @@ -37,7 +37,7 @@ import org.apache.logging.log4j.Logger; /** * Used to create the quads before they are converted to render-able buffers.

- * + * * Note: the magic number 6 you see throughout this method represents the number of sides on a cube. */ public class LodQuadBuilder @@ -54,62 +54,62 @@ public class LodQuadBuilder private final boolean doTransparency; /** Used to turn transparent LODs above the void opaque to prevent seeing the void. */ - private final HashMap minOpaqueHeightByRelativePos = new HashMap<>(64*64); // the 64*64 capacity was the smallest James saw the builder work with, so it should be a good starting point + private final HashMap minOpaqueHeightByRelativePos = new HashMap<>(64 * 64); // the 64*64 capacity was the smallest James saw the builder work with, so it should be a good starting point /** See {@link LodQuadBuilder#minOpaqueHeightByRelativePos} */ - private final HashMap minTransparentHeightByRelativePos = new HashMap<>(64*64); + private final HashMap minTransparentHeightByRelativePos = new HashMap<>(64 * 64); public static final int[][][] DIRECTION_VERTEX_IBO_QUAD = new int[][][] - { - // X,Z // - { // UP - { 1, 0 }, // 0 - { 1, 1 }, // 1 - { 0, 1 }, // 2 - { 0, 0 }, // 3 - }, - { // DOWN - { 0, 0 }, // 0 - { 0, 1 }, // 1 - { 1, 1 }, // 2 - { 1, 0 }, // 3 - }, - - // X,Y // - { // NORTH - { 0, 0 }, // 0 - { 0, 1 }, // 1 - { 1, 1 }, // 2 - - { 1, 0 }, // 3 - }, - { // SOUTH - { 1, 0 }, // 0 - { 1, 1 }, // 1 - { 0, 1 }, // 2 - - { 0, 0 }, // 3 - }, - - // Z,Y // - { // WEST - { 0, 0 }, // 0 - { 1, 0 }, // 1 - { 1, 1 }, // 2 - - { 0, 1 }, // 3 - }, - { // EAST - { 0, 1 }, // 0 - { 1, 1 }, // 1 - { 1, 0 }, // 2 - - { 0, 0 }, // 3 - }, - }; + { + // X,Z // + { // UP + {1, 0}, // 0 + {1, 1}, // 1 + {0, 1}, // 2 + {0, 0}, // 3 + }, + { // DOWN + {0, 0}, // 0 + {0, 1}, // 1 + {1, 1}, // 2 + {1, 0}, // 3 + }, + + // X,Y // + { // NORTH + {0, 0}, // 0 + {0, 1}, // 1 + {1, 1}, // 2 + + {1, 0}, // 3 + }, + { // SOUTH + {1, 0}, // 0 + {1, 1}, // 1 + {0, 1}, // 2 + + {0, 0}, // 3 + }, + + // Z,Y // + { // WEST + {0, 0}, // 0 + {1, 0}, // 1 + {1, 1}, // 2 + + {0, 1}, // 3 + }, + { // EAST + {0, 1}, // 0 + {1, 1}, // 1 + {1, 0}, // 2 + + {0, 0}, // 3 + }, + }; private int premergeCount = 0; - + //=============// @@ -136,7 +136,8 @@ public class LodQuadBuilder // add quads // //===========// - public void addQuadAdj(EDhDirection dir, short x, short y, short z, + public void addQuadAdj( + EDhDirection dir, short x, short y, short z, short widthEastWest, short widthNorthSouthOrUpDown, int color, byte skyLight, byte blockLight) { @@ -153,10 +154,10 @@ public class LodQuadBuilder BufferQuad quad = new BufferQuad(x, y, z, widthEastWest, widthNorthSouthOrUpDown, color, skyLight, blockLight, dir); ArrayList quadList = (this.doTransparency && ColorUtil.getAlpha(color) < 255) ? this.transparentQuads[dir.ordinal()] : this.opaqueQuads[dir.ordinal()]; if (!quadList.isEmpty() && - ( - quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) - || quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) - ) + ( + quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) + || quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) + ) { this.premergeCount++; return; @@ -180,11 +181,11 @@ public class LodQuadBuilder // update the minimum relative height for this quad's positions - for (int xRel = x; xRel < (x+widthEastWest); xRel++) + for (int xRel = x; xRel < (x + widthEastWest); xRel++) { - for (int zRel = z; zRel < (z+widthNorthSouthOrUpDown); zRel++) + for (int zRel = z; zRel < (z + widthNorthSouthOrUpDown); zRel++) { - Pos2D relPos = new Pos2D(xRel,zRel); + Pos2D relPos = new Pos2D(xRel, zRel); HashMap minHeightByRelativePos = isTransparent ? this.minTransparentHeightByRelativePos : this.minOpaqueHeightByRelativePos; Short currentHeight = minHeightByRelativePos.get(relPos); @@ -198,10 +199,10 @@ public class LodQuadBuilder // attempt to merge this quad with adjacent ones if (!quadList.isEmpty() && - ( - quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) - || quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) - ) + ( + quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) + || quadList.get(quadList.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) + ) { this.premergeCount++; return; @@ -218,9 +219,10 @@ public class LodQuadBuilder ArrayList qs = (doTransparency && ColorUtil.getAlpha(color) < 255) ? transparentQuads[EDhDirection.DOWN.ordinal()] : opaqueQuads[EDhDirection.DOWN.ordinal()]; if (!qs.isEmpty() && - (qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) - || qs.get(qs.size()-1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) - ) { + (qs.get(qs.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.EastWest) + || qs.get(qs.size() - 1).tryMerge(quad, BufferMergeDirectionEnum.NorthSouthOrUpDown)) + ) + { premergeCount++; return; } @@ -245,32 +247,32 @@ public class LodQuadBuilder int mx, my, mz; switch (axis) { - case X: // ZY - dx = 0; - dy = quadBase[i][1] == 1 ? widthNorthSouth : 0; - dz = quadBase[i][0] == 1 ? widthEastWest : 0; - mx = 0; - my = quadBase[i][1] == 1 ? 1 : -1; - mz = quadBase[i][0] == 1 ? 1 : -1; - break; - case Y: // XZ - dx = quadBase[i][0] == 1 ? widthEastWest : 0; - dy = 0; - dz = quadBase[i][1] == 1 ? widthNorthSouth : 0; - mx = quadBase[i][0] == 1 ? 1 : -1; - my = 0; - mz = quadBase[i][1] == 1 ? 1 : -1; - break; - case Z: // XY - dx = quadBase[i][0] == 1 ? widthEastWest : 0; - dy = quadBase[i][1] == 1 ? widthNorthSouth : 0; - dz = 0; - mx = quadBase[i][0] == 1 ? 1 : -1; - my = quadBase[i][1] == 1 ? 1 : -1; - mz = 0; - break; - default: - throw new IllegalArgumentException("Invalid Axis enum: " + axis); + case X: // ZY + dx = 0; + dy = quadBase[i][1] == 1 ? widthNorthSouth : 0; + dz = quadBase[i][0] == 1 ? widthEastWest : 0; + mx = 0; + my = quadBase[i][1] == 1 ? 1 : -1; + mz = quadBase[i][0] == 1 ? 1 : -1; + break; + case Y: // XZ + dx = quadBase[i][0] == 1 ? widthEastWest : 0; + dy = 0; + dz = quadBase[i][1] == 1 ? widthNorthSouth : 0; + mx = quadBase[i][0] == 1 ? 1 : -1; + my = 0; + mz = quadBase[i][1] == 1 ? 1 : -1; + break; + case Z: // XY + dx = quadBase[i][0] == 1 ? widthEastWest : 0; + dy = quadBase[i][1] == 1 ? widthNorthSouth : 0; + dz = 0; + mx = quadBase[i][0] == 1 ? 1 : -1; + my = quadBase[i][1] == 1 ? 1 : -1; + mz = 0; + break; + default: + throw new IllegalArgumentException("Invalid Axis enum: " + axis); } putVertex(bb, (short) (quad.x + dx), (short) (quad.y + dy), (short) (quad.z + dz), quad.hasError ? ColorUtil.RED : quad.color, // TODO add debug config that allows toggling this @@ -363,14 +365,14 @@ public class LodQuadBuilder //if (mergeCount != 0) LOGGER.debug("Merged {}/{}({}) quads", mergeCount, preQuadsCount, mergeCount / (double) preQuadsCount); } - + /** Merges all of this builder's quads for the given directionIndex (up, down, left, etc.) in the given direction */ private static long mergeQuadsInternal(ArrayList[] list, int directionIndex, BufferMergeDirectionEnum mergeDirection) { if (list[directionIndex].size() <= 1) return 0; - - list[directionIndex].sort( (objOne, objTwo) -> objOne.compare(objTwo, mergeDirection) ); + + list[directionIndex].sort((objOne, objTwo) -> objOne.compare(objTwo, mergeDirection)); long mergeCount = 0; ListIterator iter = list[directionIndex].listIterator(); @@ -448,7 +450,9 @@ public class LodQuadBuilder private int skipEmpty(int d) { while (d < 6 && opaqueQuads[d].isEmpty()) + { d++; + } return d; } @@ -514,8 +518,8 @@ public class LodQuadBuilder private int skipEmptyDirectionIndices(int directionIndex) { while (directionIndex < 6 && - (LodQuadBuilder.this.transparentQuads[directionIndex] == null - || LodQuadBuilder.this.transparentQuads[directionIndex].isEmpty())) + (LodQuadBuilder.this.transparentQuads[directionIndex] == null + || LodQuadBuilder.this.transparentQuads[directionIndex].isEmpty())) { directionIndex++; } @@ -544,7 +548,7 @@ public class LodQuadBuilder this.bb.rewind(); return this.bb; } - + private void writeData() { int i = this.quad; @@ -556,7 +560,7 @@ public class LodQuadBuilder } putQuad(this.bb, LodQuadBuilder.this.transparentQuads[this.directionIndex].get(i)); } - + if (i >= LodQuadBuilder.this.transparentQuads[this.directionIndex].size()) { this.quad = 0; @@ -574,6 +578,7 @@ public class LodQuadBuilder { /** If true: more data needs to be filled */ boolean fill(GLVertexBuffer vbo); + } public BufferFiller makeOpaqueBufferFiller(EGpuUploadMethod method) @@ -611,7 +616,7 @@ public class LodQuadBuilder } bb.rewind(); vbo.unmapBuffer(); - vbo.setVertexCount(numOfQuads*4); + vbo.setVertexCount(numOfQuads * 4); return dir < 6; } @@ -644,7 +649,9 @@ public class LodQuadBuilder quad = 0; dir++; while (dir < 6 && opaqueQuads[dir].isEmpty()) + { dir++; + } } else { @@ -660,7 +667,7 @@ public class LodQuadBuilder { int dir = 0; int quad = 0; - + public boolean fill(GLVertexBuffer vbo) { if (dir >= 6) @@ -668,7 +675,7 @@ public class LodQuadBuilder vbo.setVertexCount(0); return false; } - + int numOfQuads = _countRemainingQuads(); if (numOfQuads > AbstractRenderBuffer.MAX_QUADS_PER_BUFFER) numOfQuads = AbstractRenderBuffer.MAX_QUADS_PER_BUFFER; @@ -689,10 +696,10 @@ public class LodQuadBuilder } bb.rewind(); vbo.unmapBuffer(); - vbo.setVertexCount(numOfQuads*4); + vbo.setVertexCount(numOfQuads * 4); return dir < 6; } - + private int _countRemainingQuads() { int a = transparentQuads[dir].size() - quad; @@ -702,11 +709,11 @@ public class LodQuadBuilder } return a; } - + private void writeData(ByteBuffer bb) { int startQ = quad; - + int i = startQ; for (i = startQ; i < transparentQuads[dir].size(); i++) { @@ -716,13 +723,15 @@ public class LodQuadBuilder } putQuad(bb, transparentQuads[dir].get(i)); } - + if (i >= transparentQuads[dir].size()) { quad = 0; dir++; while (dir < 6 && transparentQuads[dir].isEmpty()) + { dir++; + } } else { @@ -763,7 +772,7 @@ public class LodQuadBuilder return i; } - + /** Returns how many GpuBuffers will be needed to render opaque quads in this builder. */ public int getCurrentNeededOpaqueVertexBufferCount() { return MathUtil.ceilDiv(this.getCurrentOpaqueQuadsCount(), AbstractRenderBuffer.MAX_QUADS_PER_BUFFER); } /** Returns how many GpuBuffers will be needed to render transparent quads in this builder. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnArrayView.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnArrayView.java index a01a5158f..8cd2e2ea4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnArrayView.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnArrayView.java @@ -159,19 +159,22 @@ public final class ColumnArrayView implements IColumnDataView return sb.toString(); } - - public int getDataHash() { + + public int getDataHash() + { return arrayHash(data, offset, size); } - - private static int arrayHash(long[] a, int offset, int length) { + + private static int arrayHash(long[] a, int offset, int length) + { if (a == null) return 0; int result = 1; int end = offset + length; - for (int i = offset; i < end; i++) { + for (int i = offset; i < end; i++) + { long element = a[i]; - int elementHash = (int)(element ^ (element >>> 32)); + int elementHash = (int) (element ^ (element >>> 32)); result = 31 * result + elementHash; } return result; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnQuadView.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnQuadView.java index 659ed2bc8..99b192760 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnQuadView.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/ColumnQuadView.java @@ -1,130 +1,155 @@ package com.seibel.distanthorizons.core.dataObjects.render.columnViews; -public class ColumnQuadView implements IColumnDataView { - private final long[] data; - private final int perColumnOffset; // per column (of columns of data) offset in longs - private final int xSize; // x size in datapoints - private final int zSize; // x size in datapoints - private final int offset; // offset in longs - private final int vertSize; // vertical size in longs - - public ColumnQuadView(long[] data, int dataZWidth, int dataVertSize, int viewXOffset, int viewZOffset, int xSize, int zSize) { - if (viewXOffset + xSize > (data.length / (dataZWidth* dataVertSize)) || viewZOffset + zSize > dataZWidth) - throw new IllegalArgumentException("View is out of bounds"); - this.data = data; - this.xSize = xSize; - this.zSize = zSize; - this.vertSize = dataVertSize; - this.perColumnOffset = dataZWidth * dataVertSize; - this.offset = viewXOffset * perColumnOffset + viewZOffset * dataVertSize; - } - private ColumnQuadView(long[] data, int perColumnOffset, int offset, int vertSize, int xSize, int zSize) { - this.data = data; - this.perColumnOffset = perColumnOffset; - this.offset = offset; - this.vertSize = vertSize; - this.xSize = xSize; - this.zSize = zSize; - } - - @Override - public long get(int index) { - int x = index / perColumnOffset; - int z = (index % perColumnOffset) / vertSize; - int v = index % vertSize; - return get(x, z, v); - } - - public long get(int x, int z, int v) { - return data[offset + x * perColumnOffset + z * vertSize + v]; - } - - public long set(int x, int z, int v, long value) { - return data[offset + x * perColumnOffset + z * vertSize + v] = value; - } - - public ColumnArrayView get(int x, int z) { - return new ColumnArrayView(data, vertSize, offset + x * perColumnOffset + z * vertSize, vertSize); - } - - public ColumnArrayView getRow(int x) { - return new ColumnArrayView(data, zSize * vertSize, offset + x * perColumnOffset, vertSize); - } - - public void set(int x, int z, IColumnDataView singleColumn) { - if (singleColumn.verticalSize() != vertSize) throw new IllegalArgumentException("Vertical size of singleColumn must be equal to vertSize"); - if (singleColumn.dataCount() != 1) throw new IllegalArgumentException("SingleColumn must contain exactly one data point"); - singleColumn.copyTo(data, offset + x * perColumnOffset + z * vertSize, singleColumn.size()); - } - - @Override - public int size() { - return xSize * zSize * vertSize; - } - - @Override - public int verticalSize() { - return vertSize; - } - - @Override - public int dataCount() { - return xSize * zSize; - } - - @Override - public IColumnDataView subView(int dataIndexStart, int dataCount) { - if (dataCount != 1) throw new UnsupportedOperationException("Fixme: subView for QUadView only support one data point!"); - int x = dataIndexStart / xSize; - int z = dataIndexStart % xSize; - return new ColumnArrayView(data, vertSize * dataCount, offset + x * perColumnOffset + z * vertSize, vertSize); - } - - public ColumnQuadView subView(int xOffset, int zOffset, int xSize, int zSize) { - if (xOffset + xSize > this.xSize || zOffset + zSize > this.zSize) throw new IllegalArgumentException("SubView is out of bounds"); - return new ColumnQuadView(data, perColumnOffset, offset + xOffset * perColumnOffset + zOffset * vertSize, vertSize, xSize, zSize); - } - - @Override - public void copyTo(long[] target, int offset, int size) { - if (size != this.size() && size > zSize * vertSize) throw new UnsupportedOperationException("Not supported yet"); - if (size <= xSize * vertSize) { - System.arraycopy(data, this.offset, target, offset, size); - } else { - for (int x = 0; x < xSize; x++) { - System.arraycopy(data, this.offset + x * perColumnOffset, target, offset + x * xSize * vertSize, xSize * vertSize); - } - } - } - - public void copyTo(ColumnQuadView target) { - if (target.xSize != xSize || target.zSize != zSize) - throw new IllegalArgumentException("Target view must have same size as this view"); - - for (int x = 0; x < xSize; x++) { - target.getRow(x).changeVerticalSizeFrom(getRow(x)); - } - } - - public void mergeMultiColumnFrom(ColumnQuadView source) { - if (source.xSize == xSize && source.zSize == zSize) - { - source.copyTo(this); - return; - } - if (source.xSize < xSize || source.zSize < zSize) - throw new IllegalArgumentException("Source view must have same or larger size as this view"); - - int srcXPerTrgX = source.xSize / xSize; - int srcZPerTrgZ = source.zSize / zSize; - if (source.xSize % xSize != 0 || source.zSize % zSize != 0) - throw new IllegalArgumentException("Source view's size must be a multiple of this view's size"); - - for (int x = 0; x < xSize; x++) { - for (int z = 0; z < zSize; z++) { - ColumnQuadView srcBlock = source.subView(x * srcXPerTrgX, z * srcZPerTrgZ, srcXPerTrgX, srcZPerTrgZ); - get(x, z).mergeMultiDataFrom(srcBlock); - } - } - } +public class ColumnQuadView implements IColumnDataView +{ + private final long[] data; + private final int perColumnOffset; // per column (of columns of data) offset in longs + private final int xSize; // x size in datapoints + private final int zSize; // x size in datapoints + private final int offset; // offset in longs + private final int vertSize; // vertical size in longs + + public ColumnQuadView(long[] data, int dataZWidth, int dataVertSize, int viewXOffset, int viewZOffset, int xSize, int zSize) + { + if (viewXOffset + xSize > (data.length / (dataZWidth * dataVertSize)) || viewZOffset + zSize > dataZWidth) + throw new IllegalArgumentException("View is out of bounds"); + this.data = data; + this.xSize = xSize; + this.zSize = zSize; + this.vertSize = dataVertSize; + this.perColumnOffset = dataZWidth * dataVertSize; + this.offset = viewXOffset * perColumnOffset + viewZOffset * dataVertSize; + } + private ColumnQuadView(long[] data, int perColumnOffset, int offset, int vertSize, int xSize, int zSize) + { + this.data = data; + this.perColumnOffset = perColumnOffset; + this.offset = offset; + this.vertSize = vertSize; + this.xSize = xSize; + this.zSize = zSize; + } + + @Override + public long get(int index) + { + int x = index / perColumnOffset; + int z = (index % perColumnOffset) / vertSize; + int v = index % vertSize; + return get(x, z, v); + } + + public long get(int x, int z, int v) + { + return data[offset + x * perColumnOffset + z * vertSize + v]; + } + + public long set(int x, int z, int v, long value) + { + return data[offset + x * perColumnOffset + z * vertSize + v] = value; + } + + public ColumnArrayView get(int x, int z) + { + return new ColumnArrayView(data, vertSize, offset + x * perColumnOffset + z * vertSize, vertSize); + } + + public ColumnArrayView getRow(int x) + { + return new ColumnArrayView(data, zSize * vertSize, offset + x * perColumnOffset, vertSize); + } + + public void set(int x, int z, IColumnDataView singleColumn) + { + if (singleColumn.verticalSize() != vertSize) throw new IllegalArgumentException("Vertical size of singleColumn must be equal to vertSize"); + if (singleColumn.dataCount() != 1) throw new IllegalArgumentException("SingleColumn must contain exactly one data point"); + singleColumn.copyTo(data, offset + x * perColumnOffset + z * vertSize, singleColumn.size()); + } + + @Override + public int size() + { + return xSize * zSize * vertSize; + } + + @Override + public int verticalSize() + { + return vertSize; + } + + @Override + public int dataCount() + { + return xSize * zSize; + } + + @Override + public IColumnDataView subView(int dataIndexStart, int dataCount) + { + if (dataCount != 1) throw new UnsupportedOperationException("Fixme: subView for QUadView only support one data point!"); + int x = dataIndexStart / xSize; + int z = dataIndexStart % xSize; + return new ColumnArrayView(data, vertSize * dataCount, offset + x * perColumnOffset + z * vertSize, vertSize); + } + + public ColumnQuadView subView(int xOffset, int zOffset, int xSize, int zSize) + { + if (xOffset + xSize > this.xSize || zOffset + zSize > this.zSize) throw new IllegalArgumentException("SubView is out of bounds"); + return new ColumnQuadView(data, perColumnOffset, offset + xOffset * perColumnOffset + zOffset * vertSize, vertSize, xSize, zSize); + } + + @Override + public void copyTo(long[] target, int offset, int size) + { + if (size != this.size() && size > zSize * vertSize) throw new UnsupportedOperationException("Not supported yet"); + if (size <= xSize * vertSize) + { + System.arraycopy(data, this.offset, target, offset, size); + } + else + { + for (int x = 0; x < xSize; x++) + { + System.arraycopy(data, this.offset + x * perColumnOffset, target, offset + x * xSize * vertSize, xSize * vertSize); + } + } + } + + public void copyTo(ColumnQuadView target) + { + if (target.xSize != xSize || target.zSize != zSize) + throw new IllegalArgumentException("Target view must have same size as this view"); + + for (int x = 0; x < xSize; x++) + { + target.getRow(x).changeVerticalSizeFrom(getRow(x)); + } + } + + public void mergeMultiColumnFrom(ColumnQuadView source) + { + if (source.xSize == xSize && source.zSize == zSize) + { + source.copyTo(this); + return; + } + if (source.xSize < xSize || source.zSize < zSize) + throw new IllegalArgumentException("Source view must have same or larger size as this view"); + + int srcXPerTrgX = source.xSize / xSize; + int srcZPerTrgZ = source.zSize / zSize; + if (source.xSize % xSize != 0 || source.zSize % zSize != 0) + throw new IllegalArgumentException("Source view's size must be a multiple of this view's size"); + + for (int x = 0; x < xSize; x++) + { + for (int z = 0; z < zSize; z++) + { + ColumnQuadView srcBlock = source.subView(x * srcXPerTrgX, z * srcZPerTrgZ, srcXPerTrgX, srcZPerTrgZ); + get(x, z).mergeMultiDataFrom(srcBlock); + } + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/ChunkToLodBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/ChunkToLodBuilder.java index 5fde3959f..1931fb0cb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/ChunkToLodBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/ChunkToLodBuilder.java @@ -24,8 +24,8 @@ public class ChunkToLodBuilder implements AutoCloseable private static ConfigChangeListener threadConfigListener; public static final long MAX_TICK_TIME_NS = 1000000000L / 20L; - /** - * This is done to prevent tasks infinitely piling up if a queued chunk could never be generated, + /** + * This is done to prevent tasks infinitely piling up if a queued chunk could never be generated, * But should also prevent de-queuing chunks that should still be generated. */ public static final short MAX_NUMBER_OF_CHUNK_GENERATION_ATTEMPTS_BEFORE_DISCARDING = 64; @@ -83,7 +83,7 @@ public class ChunkToLodBuilder implements AutoCloseable else if (MC == null || !MC.playerExists()) { // TODO handle server side properly - + // MC hasn't finished loading (or is currently unloaded) // can be uncommented if tasks aren't being cleared correctly @@ -92,7 +92,7 @@ public class ChunkToLodBuilder implements AutoCloseable } - for (int i = 0; i< threadCount; i++) + for (int i = 0; i < threadCount; i++) { this.runningCount.incrementAndGet(); CompletableFuture.runAsync(() -> @@ -133,7 +133,7 @@ public class ChunkToLodBuilder implements AutoCloseable IChunkWrapper latestChunk = this.concurrentChunkToBuildByChunkPos.remove(task.chunkPos); // Basically an Exchange operation if (latestChunk == null) { - LOGGER.error("Somehow Task at "+task.chunkPos+" has latestChunk as null. Skipping task."); + LOGGER.error("Somehow Task at " + task.chunkPos + " has latestChunk as null. Skipping task."); task.future.complete(null); continue; } @@ -149,7 +149,7 @@ public class ChunkToLodBuilder implements AutoCloseable continue; } } - else if(task.generationAttemptNumber > MAX_NUMBER_OF_CHUNK_GENERATION_ATTEMPTS_BEFORE_DISCARDING) + else if (task.generationAttemptNumber > MAX_NUMBER_OF_CHUNK_GENERATION_ATTEMPTS_BEFORE_DISCARDING) { // this task won't be re-queued continue; @@ -157,7 +157,7 @@ public class ChunkToLodBuilder implements AutoCloseable } catch (Exception ex) { - LOGGER.error("Error while processing Task at "+task.chunkPos, ex); + LOGGER.error("Error while processing Task at " + task.chunkPos, ex); } // Failed to build due to chunk not meeting requirement, @@ -187,7 +187,7 @@ public class ChunkToLodBuilder implements AutoCloseable } /** - * should be called whenever changing levels/worlds + * should be called whenever changing levels/worlds * to prevent trying to generate LODs for chunk(s) that are no longer loaded * (which can cause exceptions) */ @@ -218,7 +218,7 @@ public class ChunkToLodBuilder implements AutoCloseable if (executorThreadPool == null || executorThreadPool.isTerminated()) { - LOGGER.info("Starting "+ChunkToLodBuilder.class.getSimpleName()); + LOGGER.info("Starting " + ChunkToLodBuilder.class.getSimpleName()); setThreadPoolSize(Config.Client.Advanced.MultiThreading.numberOfChunkLodConverterThreads.get()); } } @@ -241,7 +241,7 @@ public class ChunkToLodBuilder implements AutoCloseable { if (executorThreadPool != null) { - LOGGER.info("Stopping "+ChunkToLodBuilder.class.getSimpleName()); + LOGGER.info("Stopping " + ChunkToLodBuilder.class.getSimpleName()); executorThreadPool.shutdownNow(); } } @@ -273,6 +273,7 @@ public class ChunkToLodBuilder implements AutoCloseable this.chunkPos = chunkPos; this.future = future; } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/DataRenderTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/DataRenderTransformer.java index 42e76529a..99d1c2120 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/DataRenderTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/DataRenderTransformer.java @@ -20,7 +20,7 @@ public class DataRenderTransformer { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - + private static ExecutorService transformerThreadPool = null; private static ConfigChangeListener configListener; @@ -30,19 +30,19 @@ public class DataRenderTransformer // transformers // //==============// - public static CompletableFuture transformDataSourceAsync(IFullDataSource fullDataSource, IDhClientLevel level) + public static CompletableFuture transformDataSourceAsync(IFullDataSource fullDataSource, IDhClientLevel level) { - return CompletableFuture.supplyAsync(() -> transform(fullDataSource, level), transformerThreadPool); - } + return CompletableFuture.supplyAsync(() -> transform(fullDataSource, level), transformerThreadPool); + } - public static CompletableFuture transformDataSourceAsync(CompletableFuture fullDataSourceFuture, IDhClientLevel level) + public static CompletableFuture transformDataSourceAsync(CompletableFuture fullDataSourceFuture, IDhClientLevel level) { - return fullDataSourceFuture.thenApplyAsync((fullDataSource) -> transform(fullDataSource, level), transformerThreadPool); - } + return fullDataSourceFuture.thenApplyAsync((fullDataSource) -> transform(fullDataSource, level), transformerThreadPool); + } - private static ColumnRenderSource transform(IFullDataSource fullDataSource, IDhClientLevel level) + private static ColumnRenderSource transform(IFullDataSource fullDataSource, IDhClientLevel level) { - if (fullDataSource == null) + if (fullDataSource == null) { return null; } @@ -56,11 +56,11 @@ public class DataRenderTransformer { return ColumnRenderLoader.INSTANCE.createRenderSource(fullDataSource, level); } - catch (InterruptedException e) + catch (InterruptedException e) { return null; } - } + } @@ -71,7 +71,7 @@ public class DataRenderTransformer /** * Creates a new executor.
* Does nothing if an executor already exists. - */ + */ public static void setupExecutorService() { // static setup @@ -84,11 +84,11 @@ public class DataRenderTransformer // TODO this didn't seem to be re-sizing when changed via the config if (transformerThreadPool == null || transformerThreadPool.isTerminated()) { - LOGGER.info("Starting "+DataRenderTransformer.class.getSimpleName()); + LOGGER.info("Starting " + DataRenderTransformer.class.getSimpleName()); setThreadPoolSize(Config.Client.Advanced.MultiThreading.numberOfDataTransformerThreads.get()); } } - public static void setThreadPoolSize(int threadPoolSize) + public static void setThreadPoolSize(int threadPoolSize) { if (transformerThreadPool != null) { @@ -96,10 +96,10 @@ public class DataRenderTransformer transformerThreadPool.shutdown(); } - transformerThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, "Full/Render Data Transformer", Config.Client.Advanced.MultiThreading.runTimeRatioForDataTransformerThreads); + transformerThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, "Full/Render Data Transformer", Config.Client.Advanced.MultiThreading.runTimeRatioForDataTransformerThreads); } - /** + /** * Stops any executing tasks and destroys the executor.
* Does nothing if the executor isn't running. */ @@ -107,7 +107,7 @@ public class DataRenderTransformer { if (transformerThreadPool != null) { - LOGGER.info("Stopping "+DataRenderTransformer.class.getSimpleName()); + LOGGER.info("Stopping " + DataRenderTransformer.class.getSimpleName()); transformerThreadPool.shutdownNow(); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 6fd140464..aa807a998 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -43,7 +43,7 @@ public class FullDataToRenderDataTransformer { if (Thread.interrupted()) { - throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName()+" task interrupted."); + throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName() + " task interrupted."); } } @@ -52,48 +52,49 @@ public class FullDataToRenderDataTransformer // transformers // //==============// - /** - * Creates a LodNode for a chunk in the given world. - * @throws IllegalArgumentException thrown if either the chunk or world is null. + /** + * Creates a LodNode for a chunk in the given world. + * + * @throws IllegalArgumentException thrown if either the chunk or world is null. * @throws InterruptedException Can be caused by interrupting the thread upstream. - * Generally thrown if the method is running after the client leaves the current world. - */ - public static ColumnRenderSource transformFullDataToColumnData(IDhClientLevel level, CompleteFullDataSource fullDataSource) throws InterruptedException + * Generally thrown if the method is running after the client leaves the current world. + */ + public static ColumnRenderSource transformFullDataToColumnData(IDhClientLevel level, CompleteFullDataSource fullDataSource) throws InterruptedException { - final DhSectionPos pos = fullDataSource.getSectionPos(); - final byte dataDetail = fullDataSource.getDataDetailLevel(); - final int vertSize = Config.Client.Advanced.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(fullDataSource.getDataDetailLevel()); - final ColumnRenderSource columnSource = new ColumnRenderSource(pos, vertSize, level.getMinY()); - if (fullDataSource.isEmpty()) + final DhSectionPos pos = fullDataSource.getSectionPos(); + final byte dataDetail = fullDataSource.getDataDetailLevel(); + final int vertSize = Config.Client.Advanced.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(fullDataSource.getDataDetailLevel()); + final ColumnRenderSource columnSource = new ColumnRenderSource(pos, vertSize, level.getMinY()); + if (fullDataSource.isEmpty()) { return columnSource; } - columnSource.markNotEmpty(); - - if (dataDetail == columnSource.getDataDetail()) + columnSource.markNotEmpty(); + + if (dataDetail == columnSource.getDataDetail()) { - int baseX = pos.getCorner().getCornerBlockPos().x; - int baseZ = pos.getCorner().getCornerBlockPos().z; + int baseX = pos.getCorner().getCornerBlockPos().x; + int baseZ = pos.getCorner().getCornerBlockPos().z; - for (int x = 0; x < pos.getWidth(dataDetail).numberOfLodSectionsWide; x++) + for (int x = 0; x < pos.getWidth(dataDetail).numberOfLodSectionsWide; x++) { - for (int z = 0; z < pos.getWidth(dataDetail).numberOfLodSectionsWide; z++) + for (int z = 0; z < pos.getWidth(dataDetail).numberOfLodSectionsWide; z++) { throwIfThreadInterrupted(); - ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); - SingleColumnFullDataAccessor fullArrayView = fullDataSource.get(x, z); - convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1); - + ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); + SingleColumnFullDataAccessor fullArrayView = fullDataSource.get(x, z); + convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1); + if (fullArrayView.doesColumnExist()) { LodUtil.assertTrue(columnSource.doesDataPointExist(x, z)); } - } - } + } + } - columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL); + columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL); } else @@ -102,24 +103,24 @@ public class FullDataToRenderDataTransformer //FIXME: Implement different size creation of renderData } return columnSource; - } + } /** * @throws InterruptedException Can be caused by interrupting the thread upstream. - * Generally thrown if the method is running after the client leaves the current world. + * Generally thrown if the method is running after the client leaves the current world. */ - public static ColumnRenderSource transformIncompleteDataToColumnData(IDhClientLevel level, IIncompleteFullDataSource data) throws InterruptedException + public static ColumnRenderSource transformIncompleteDataToColumnData(IDhClientLevel level, IIncompleteFullDataSource data) throws InterruptedException { - final DhSectionPos pos = data.getSectionPos(); - final byte dataDetail = data.getDataDetailLevel(); - final int vertSize = Config.Client.Advanced.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(data.getDataDetailLevel()); - final ColumnRenderSource columnSource = new ColumnRenderSource(pos, vertSize, level.getMinY()); - if (data.isEmpty()) + final DhSectionPos pos = data.getSectionPos(); + final byte dataDetail = data.getDataDetailLevel(); + final int vertSize = Config.Client.Advanced.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(data.getDataDetailLevel()); + final ColumnRenderSource columnSource = new ColumnRenderSource(pos, vertSize, level.getMinY()); + if (data.isEmpty()) { return columnSource; } - columnSource.markNotEmpty(); + columnSource.markNotEmpty(); if (dataDetail == columnSource.getDataDetail()) { @@ -151,12 +152,12 @@ public class FullDataToRenderDataTransformer throw new UnsupportedOperationException("To be implemented"); //FIXME: Implement different size creation of renderData } - return columnSource; - } - + return columnSource; + } + /** * @throws InterruptedException Can be caused by interrupting the thread upstream. - * Generally thrown if the method is running after the client leaves the current world. + * Generally thrown if the method is running after the client leaves the current world. */ public static boolean writeFullDataChunkToColumnData(ColumnRenderSource renderSource, IDhClientLevel level, ChunkSizedFullDataAccessor chunkDataView) throws InterruptedException, IllegalArgumentException { @@ -172,19 +173,19 @@ public class FullDataToRenderDataTransformer final int sourceDataPointBlockWidth = BitShiftUtil.powerOfTwo(renderSource.getDataDetail()); boolean changed = false; - + if (chunkDataView.detailLevel == renderSource.getDataDetail()) { renderSource.markNotEmpty(); // confirm the render source contains this chunk if (blockOffsetX < 0 - || blockOffsetX + LodUtil.CHUNK_WIDTH > renderSource.getWidthInDataPoints() - || blockOffsetZ < 0 - || blockOffsetZ + LodUtil.CHUNK_WIDTH > renderSource.getWidthInDataPoints()) + || blockOffsetX + LodUtil.CHUNK_WIDTH > renderSource.getWidthInDataPoints() + || blockOffsetZ < 0 + || blockOffsetZ + LodUtil.CHUNK_WIDTH > renderSource.getWidthInDataPoints()) { throw new IllegalArgumentException("Data offset is out of bounds"); } - + throwIfThreadInterrupted(); for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++) @@ -194,7 +195,7 @@ public class FullDataToRenderDataTransformer ColumnArrayView columnArrayView = renderSource.getVerticalDataPointView(blockOffsetX + x, blockOffsetZ + z); int hash = columnArrayView.getDataHash(); SingleColumnFullDataAccessor fullArrayView = chunkDataView.get(x, z); - convertColumnData(level, + convertColumnData(level, sourceBlockX + sourceDataPointBlockWidth * (blockOffsetX + x), sourceBlockZ + sourceDataPointBlockWidth * (blockOffsetZ + z), columnArrayView, fullArrayView, 2); @@ -203,7 +204,8 @@ public class FullDataToRenderDataTransformer } renderSource.fillDebugFlag(blockOffsetX, blockOffsetZ, LodUtil.CHUNK_WIDTH, LodUtil.CHUNK_WIDTH, ColumnRenderSource.DebugSourceFlag.DIRECT); } - else if (chunkDataView.detailLevel < renderSource.getDataDetail() && renderSource.getDataDetail() <= chunkDataView.getLodPos().detailLevel) { + else if (chunkDataView.detailLevel < renderSource.getDataDetail() && renderSource.getDataDetail() <= chunkDataView.getLodPos().detailLevel) + { renderSource.markNotEmpty(); // multiple chunk data points converting to 1 column data point DhLodPos dataCornerPos = chunkDataView.getLodPos().getCornerLodPos(chunkDataView.detailLevel); @@ -213,9 +215,11 @@ public class FullDataToRenderDataTransformer int relStartZ = Math.floorMod(sourceStartingChangePos.z, renderSource.getWidthInDataPoints()); int dataToSourceScale = sourceCornerPos.getWidthAtDetail(chunkDataView.detailLevel); int columnsInChunk = chunkDataView.getLodPos().getWidthAtDetail(renderSource.getDataDetail()); - - for (int ox = 0; ox < columnsInChunk; ox++) { - for (int oz = 0; oz < columnsInChunk; oz++) { + + for (int ox = 0; ox < columnsInChunk; ox++) + { + for (int oz = 0; oz < columnsInChunk; oz++) + { int relSourceX = relStartX + ox; int relSourceZ = relStartZ + oz; ColumnArrayView columnArrayView = renderSource.getVerticalDataPointView(relSourceX, relSourceZ); @@ -230,13 +234,15 @@ public class FullDataToRenderDataTransformer } renderSource.fillDebugFlag(relStartX, relStartZ, columnsInChunk, columnsInChunk, ColumnRenderSource.DebugSourceFlag.DIRECT); } - else if (chunkDataView.getLodPos().detailLevel < renderSource.getDataDetail()) { + else if (chunkDataView.getLodPos().detailLevel < renderSource.getDataDetail()) + { // The entire chunk is being converted to a single column data point, possibly. DhLodPos dataCornerPos = chunkDataView.getLodPos().getCornerLodPos(chunkDataView.detailLevel); DhLodPos sourceCornerPos = renderSourcePos.getCorner(renderSource.getDataDetail()); DhLodPos sourceStartingChangePos = dataCornerPos.convertToDetailLevel(renderSource.getDataDetail()); int chunksPerColumn = sourceStartingChangePos.getWidthAtDetail(chunkDataView.getLodPos().detailLevel); - if (chunkDataView.getLodPos().x % chunksPerColumn != 0 || chunkDataView.getLodPos().z % chunksPerColumn != 0) { + if (chunkDataView.getLodPos().x % chunksPerColumn != 0 || chunkDataView.getLodPos().z % chunksPerColumn != 0) + { return false; // not a multiple of the column size, so no change } int relStartX = Math.floorMod(sourceStartingChangePos.x, renderSource.getWidthInDataPoints()); @@ -252,31 +258,31 @@ public class FullDataToRenderDataTransformer } return changed; } - - private static void convertColumnData(IDhClientLevel level, int blockX, int blockZ, ColumnArrayView columnArrayView, SingleColumnFullDataAccessor fullArrayView, int genMode) + + private static void convertColumnData(IDhClientLevel level, int blockX, int blockZ, ColumnArrayView columnArrayView, SingleColumnFullDataAccessor fullArrayView, int genMode) { - if (!fullArrayView.doesColumnExist()) + if (!fullArrayView.doesColumnExist()) { return; } - + int dataTotalLength = fullArrayView.getSingleLength(); - if (dataTotalLength == 0) + if (dataTotalLength == 0) { return; } - - if (dataTotalLength > columnArrayView.verticalSize()) + + if (dataTotalLength > columnArrayView.verticalSize()) { - ColumnArrayView totalColumnData = new ColumnArrayView(new long[dataTotalLength], dataTotalLength, 0, dataTotalLength); - iterateAndConvert(level, blockX, blockZ, genMode, totalColumnData, fullArrayView); - columnArrayView.changeVerticalSizeFrom(totalColumnData); + ColumnArrayView totalColumnData = new ColumnArrayView(new long[dataTotalLength], dataTotalLength, 0, dataTotalLength); + iterateAndConvert(level, blockX, blockZ, genMode, totalColumnData, fullArrayView); + columnArrayView.changeVerticalSizeFrom(totalColumnData); } else { iterateAndConvert(level, blockX, blockZ, genMode, columnArrayView, fullArrayView); //Directly use the arrayView since it fits. } - } + } private static void iterateAndConvert(IDhClientLevel level, int blockX, int blockZ, int genMode, ColumnArrayView column, SingleColumnFullDataAccessor data) { @@ -346,9 +352,9 @@ public class FullDataToRenderDataTransformer column.set(0, RenderDataPointUtil.createVoidDataPoint((byte) genMode)); } } - - - + + + // /** creates a vertical DataPoint */ // private void writeVerticalData(long[] data, int dataOffset, int maxVerticalData, // IChunkWrapper chunk, LodBuilderConfig config, int chunkSubPosX, int chunkSubPosZ) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodBuilderConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodBuilderConfig.java index d43b3b1a4..4c8dbf426 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodBuilderConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodBuilderConfig.java @@ -26,7 +26,7 @@ import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGenerat * Generally this will only be used if we want to generate a * LodChunk using incomplete data, otherwise the defaults * should work best for a fully generated chunk (IE has correct surface blocks). - * + * * @author James Seibel * @version 2022-12-10 */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index b0e50bc37..2d2789a32 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -13,67 +13,68 @@ import it.unimi.dsi.fastutil.longs.LongArrayList; public class LodDataBuilder { - private static final IBlockStateWrapper AIR = SingletonInjector.INSTANCE.get(IWrapperFactory.class).getAirBlockStateWrapper(); + private static final IBlockStateWrapper AIR = SingletonInjector.INSTANCE.get(IWrapperFactory.class).getAirBlockStateWrapper(); - public static ChunkSizedFullDataAccessor createChunkData(IChunkWrapper chunkWrapper) - { - if (!canGenerateLodFromChunk(chunkWrapper)) - { - return null; - } - - - ChunkSizedFullDataAccessor chunkData = new ChunkSizedFullDataAccessor(chunkWrapper.getChunkPos()); - - for (int x=0; x=chunkWrapper.getMinBuildHeight(); y--) + LongArrayList longs = new LongArrayList(chunkWrapper.getHeight() / 4); + int lastY = chunkWrapper.getMaxBuildHeight(); + IBiomeWrapper biome = chunkWrapper.getBiome(x, lastY, z); + IBlockStateWrapper blockState = AIR; + int mappedId = chunkData.getMapping().addIfNotPresentAndGetId(biome, blockState); + // FIXME: The +1 offset to reproduce the old behavior. Remove this when we get per-face lighting + byte light = (byte) ((chunkWrapper.getBlockLight(x, lastY + 1, z) << 4) + chunkWrapper.getSkyLight(x, lastY + 1, z)); + + int y = chunkWrapper.getLightBlockingHeightMapValue(x, z); + + for (; y >= chunkWrapper.getMinBuildHeight(); y--) { - IBiomeWrapper newBiome = chunkWrapper.getBiome(x, y, z); - IBlockStateWrapper newBlockState = chunkWrapper.getBlockState(x, y, z); - byte newLight = (byte) ((chunkWrapper.getBlockLight(x,y+1,z) << 4) + chunkWrapper.getSkyLight(x,y+1,z)); - - if (!newBiome.equals(biome) || !newBlockState.equals(blockState)) + IBiomeWrapper newBiome = chunkWrapper.getBiome(x, y, z); + IBlockStateWrapper newBlockState = chunkWrapper.getBlockState(x, y, z); + byte newLight = (byte) ((chunkWrapper.getBlockLight(x, y + 1, z) << 4) + chunkWrapper.getSkyLight(x, y + 1, z)); + + if (!newBiome.equals(biome) || !newBlockState.equals(blockState)) { - longs.add(FullDataPointUtil.encode(mappedId, lastY-y, y+1 - chunkWrapper.getMinBuildHeight(), light)); - biome = newBiome; - blockState = newBlockState; - mappedId = chunkData.getMapping().addIfNotPresentAndGetId(biome, blockState); - light = newLight; - lastY = y; - } + longs.add(FullDataPointUtil.encode(mappedId, lastY - y, y + 1 - chunkWrapper.getMinBuildHeight(), light)); + biome = newBiome; + blockState = newBlockState; + mappedId = chunkData.getMapping().addIfNotPresentAndGetId(biome, blockState); + light = newLight; + lastY = y; + } // else if (newLight != light) { // longs.add(FullFormat.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light)); // light = newLight; // lastY = y; // } - } - longs.add(FullDataPointUtil.encode(mappedId, lastY-y, y+1 - chunkWrapper.getMinBuildHeight(), light)); - - chunkData.setSingleColumn(longs.toArray(new long[0]), x, z); - } - } - if (!canGenerateLodFromChunk(chunkWrapper)) return null; - LodUtil.assertTrue(chunkData.emptyCount() == 0); - return chunkData; - } - - public static boolean canGenerateLodFromChunk(IChunkWrapper chunk) - { - //return true; - return chunk != null && chunk.isLightCorrect(); // TODO client only chunks return chunks with bad lighting, preventing chunk building (or transparent only chunks) - } + } + longs.add(FullDataPointUtil.encode(mappedId, lastY - y, y + 1 - chunkWrapper.getMinBuildHeight(), light)); + + chunkData.setSingleColumn(longs.toArray(new long[0]), x, z); + } + } + if (!canGenerateLodFromChunk(chunkWrapper)) return null; + LodUtil.assertTrue(chunkData.emptyCount() == 0); + return chunkData; + } + + public static boolean canGenerateLodFromChunk(IChunkWrapper chunk) + { + //return true; + return chunk != null && chunk.isLightCorrect(); // TODO client only chunks return chunks with bad lighting, preventing chunk building (or transparent only chunks) + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/ModAccessorInjector.java b/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/ModAccessorInjector.java index 9dafd6523..e0e86c34a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/ModAccessorInjector.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/ModAccessorInjector.java @@ -30,10 +30,10 @@ import java.lang.invoke.MethodHandles; /** * This class takes care of dependency injection for mod accessors. (for mod compatibility * support).

- * + * * If a IModAccessor returns null either that means the mod isn't loaded in the game * or an Accessor hasn't been implemented for the given Minecraft version. - * + * * @author James Seibel * @author Leetom * @version 2022-7-18 @@ -62,6 +62,6 @@ public class ModAccessorInjector extends DependencyInjector super.bind(interfaceClass, modAccessor); LOGGER.info("Registered mod compatibility accessor for: [" + modAccessor.getModName() + "]."); } - - + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/SingletonInjector.java b/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/SingletonInjector.java index 67387cfdf..9a82e17fe 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/SingletonInjector.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dependencyInjection/SingletonInjector.java @@ -25,7 +25,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab /** * This class takes care of dependency injection * for singletons. - * + * * @author James Seibel * @version 2022-7-16 */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java b/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java index 6a7f920a0..2104bc13b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.enums; import java.util.Arrays; @@ -52,35 +52,35 @@ public enum EDhDirection /** * Up, Down, West, East, North, South
- * Similar to {@link EDhDirection#OPPOSITE_DIRECTIONS}, just with a different order + * Similar to {@link EDhDirection#OPPOSITE_DIRECTIONS}, just with a different order */ - public static final EDhDirection[] CARDINAL_DIRECTIONS = new EDhDirection[] { + public static final EDhDirection[] CARDINAL_DIRECTIONS = new EDhDirection[]{ EDhDirection.UP, EDhDirection.DOWN, EDhDirection.WEST, EDhDirection.EAST, EDhDirection.NORTH, - EDhDirection.SOUTH }; + EDhDirection.SOUTH}; - /** + /** * Up, Down, South, North, East, West
- * Similar to {@link EDhDirection#CARDINAL_DIRECTIONS}, just with a different order + * Similar to {@link EDhDirection#CARDINAL_DIRECTIONS}, just with a different order */ - public static final EDhDirection[] OPPOSITE_DIRECTIONS = new EDhDirection[] { + public static final EDhDirection[] OPPOSITE_DIRECTIONS = new EDhDirection[]{ EDhDirection.UP, EDhDirection.DOWN, EDhDirection.SOUTH, EDhDirection.NORTH, EDhDirection.EAST, - EDhDirection.WEST }; + EDhDirection.WEST}; /** North, South, East, West */ // TODO rename to state this is just X/Z or flat directions - public static final EDhDirection[] ADJ_DIRECTIONS = new EDhDirection[] { + public static final EDhDirection[] ADJ_DIRECTIONS = new EDhDirection[]{ EDhDirection.EAST, EDhDirection.WEST, EDhDirection.SOUTH, - EDhDirection.NORTH }; - + EDhDirection.NORTH}; + // private final int data3d; // private final int oppositeIndex; // private final int data2d; @@ -95,7 +95,7 @@ public enum EDhDirection { return p_199787_0_; })); - + // private static final LodDirection[] BY_3D_DATA = Arrays.stream(VALUES).sorted(Comparator.comparingInt((p_199790_0_) -> // { // return p_199790_0_.data3d; @@ -114,7 +114,7 @@ public enum EDhDirection // { // return new LodDirection[p_199791_0_]; // }); - + // private static final Long2ObjectMap BY_NORMAL = Arrays.stream(VALUES).collect(Collectors.toMap((p_218385_0_) -> // { // return (new BlockPos(p_218385_0_.getNormal())).asLong(); @@ -138,10 +138,10 @@ public enum EDhDirection this.axisDirection = p_i46016_7_; this.normal = p_i46016_9_; } - - - - + + + + // public static LodDirection[] orderedByNearest(Entity p_196054_0_) // { // float f = p_196054_0_.getViewXRot(1.0F) * ((float) Math.PI / 180F); @@ -181,12 +181,12 @@ public enum EDhDirection // return f9 > f7 ? makeDirectionArray(direction2, lodDirection, direction1) : makeDirectionArray(direction2, direction1, lodDirection); // } // } - + // private static LodDirection[] makeDirectionArray(LodDirection p_196053_0_, LodDirection p_196053_1_, LodDirection p_196053_2_) // { // return new LodDirection[] { p_196053_0_, p_196053_1_, p_196053_2_, p_196053_2_.getOpposite(), p_196053_1_.getOpposite(), p_196053_0_.getOpposite() }; // } - + // public static LodDirection rotate(Mat4f p_229385_0_, LodDirection p_229385_1_) // { // Vec3i Vec3i = p_229385_1_.getNormal(); @@ -194,7 +194,7 @@ public enum EDhDirection // vector4f.transform(p_229385_0_); // return getNearest(vector4f.x(), vector4f.y(), vector4f.z()); // } - + // public Quaternion getRotation() // { // Quaternion quaternion = Vector3f.XP.rotationDegrees(90.0F); @@ -218,7 +218,7 @@ public enum EDhDirection // return quaternion; // } // } - + // public int get3DDataValue() // { // return this.data3d; @@ -233,7 +233,7 @@ public enum EDhDirection { return this.axisDirection; } - + // public LodDirection getOpposite() // { // return from3DDataValue(this.oppositeIndex); @@ -243,16 +243,16 @@ public enum EDhDirection { switch (this) { - case NORTH: - return EAST; - case SOUTH: - return WEST; - case WEST: - return NORTH; - case EAST: - return SOUTH; - default: - throw new IllegalStateException("Unable to get Y-rotated facing of " + this); + case NORTH: + return EAST; + case SOUTH: + return WEST; + case WEST: + return NORTH; + case EAST: + return SOUTH; + default: + throw new IllegalStateException("Unable to get Y-rotated facing of " + this); } } @@ -260,16 +260,16 @@ public enum EDhDirection { switch (this) { - case NORTH: - return WEST; - case SOUTH: - return EAST; - case WEST: - return SOUTH; - case EAST: - return NORTH; - default: - throw new IllegalStateException("Unable to get CCW facing of " + this); + case NORTH: + return WEST; + case SOUTH: + return EAST; + case WEST: + return SOUTH; + case EAST: + return NORTH; + default: + throw new IllegalStateException("Unable to get CCW facing of " + this); } } @@ -282,12 +282,12 @@ public enum EDhDirection { return this.axis; } - + public static EDhDirection byName(String name) { return name == null ? null : BY_NAME.get(name.toLowerCase(Locale.ROOT)); } - + // public static LodDirection from3DDataValue(int p_82600_0_) // { // return BY_3D_DATA[MathHelper.abs(p_82600_0_ % BY_3D_DATA.length)]; @@ -297,13 +297,13 @@ public enum EDhDirection // { // return BY_2D_DATA[MathHelper.abs(p_176731_0_ % BY_2D_DATA.length)]; // } - + // @Nullable // public static LodDirection fromNormal(int p_218383_0_, int p_218383_1_, int p_218383_2_) // { // return BY_NORMAL.get(BlockPos.asLong(p_218383_0_, p_218383_1_, p_218383_2_)); // } - + // public static LodDirection fromYRot(double p_176733_0_) // { // return from2DDataValue(MathHelper.floor(p_176733_0_ / 90.0D + 0.5D) & 3); @@ -313,31 +313,31 @@ public enum EDhDirection { switch (p_211699_0_) { - case X: - return p_211699_1_ == EDhDirection.AxisDirection.POSITIVE ? EAST : WEST; - case Y: - return p_211699_1_ == EDhDirection.AxisDirection.POSITIVE ? UP : DOWN; - case Z: - default: - return p_211699_1_ == EDhDirection.AxisDirection.POSITIVE ? SOUTH : NORTH; + case X: + return p_211699_1_ == EDhDirection.AxisDirection.POSITIVE ? EAST : WEST; + case Y: + return p_211699_1_ == EDhDirection.AxisDirection.POSITIVE ? UP : DOWN; + case Z: + default: + return p_211699_1_ == EDhDirection.AxisDirection.POSITIVE ? SOUTH : NORTH; } } - + // public float toYRot() // { // return (this.data2d & 3) * 90; // } - + // public static LodDirection getRandom(Random p_239631_0_) // { // return Util.getRandom(VALUES, p_239631_0_); // } - + // public static LodDirection getNearest(double p_210769_0_, double p_210769_2_, double p_210769_4_) // { // return getNearest((float) p_210769_0_, (float) p_210769_2_, (float) p_210769_4_); // } - + // public static LodDirection getNearest(float p_176737_0_, float p_176737_1_, float p_176737_2_) // { // LodDirection lodDirection = NORTH; @@ -373,7 +373,7 @@ public enum EDhDirection { return this.normal; } - + // public boolean isFacingAngle(float p_243532_1_) // { // float f = p_243532_1_ * ((float) Math.PI / 180F); @@ -385,47 +385,47 @@ public enum EDhDirection public enum Axis implements Predicate { X("x") - { - @Override - public int choose(int x, int y, int z) - { - return x; - } - - @Override - public double choose(double x, double y, double z) - { - return x; - } - }, + { + @Override + public int choose(int x, int y, int z) + { + return x; + } + + @Override + public double choose(double x, double y, double z) + { + return x; + } + }, Y("y") - { - @Override - public int choose(int x, int y, int z) - { - return y; - } - - @Override - public double choose(double x, double y, double z) - { - return y; - } - }, + { + @Override + public int choose(int x, int y, int z) + { + return y; + } + + @Override + public double choose(double x, double y, double z) + { + return y; + } + }, Z("z") - { - @Override - public int choose(int x, int y, int z) - { - return z; - } - - @Override - public double choose(double x, double y, double z) - { - return z; - } - }; + { + @Override + public int choose(int x, int y, int z) + { + return z; + } + + @Override + public double choose(double x, double y, double z) + { + return z; + } + }; private static final EDhDirection.Axis[] VALUES = values(); @@ -439,7 +439,7 @@ public enum EDhDirection { this.name = name; } - + public static EDhDirection.Axis byName(String name) { return BY_NAME.get(name.toLowerCase(Locale.ROOT)); @@ -465,7 +465,7 @@ public enum EDhDirection { return this.name; } - + // public static LodDirection.Axis getRandom(Random p_239634_0_) // { // return Util.getRandom(VALUES, p_239634_0_); @@ -476,7 +476,7 @@ public enum EDhDirection { return p_test_1_ != null && p_test_1_.getAxis() == this; } - + // public LodDirection.Plane getPlane() // { // switch (this) @@ -526,7 +526,7 @@ public enum EDhDirection return this == POSITIVE ? NEGATIVE : POSITIVE; } } - + // public static enum Plane implements Iterable, Predicate // { // HORIZONTAL(new LodDirection[] { LodDirection.NORTH, LodDirection.EAST, LodDirection.SOUTH, LodDirection.WEST }, new LodDirection.Axis[] { LodDirection.Axis.X, LodDirection.Axis.Z }), diff --git a/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java b/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java index 610ea5ef3..f3bdaf01e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java @@ -24,7 +24,7 @@ package com.seibel.distanthorizons.core.enums; * Lod_Builder,
* Proxy_Worker,
* None
- * + * * @author James Seibel * @version 10-1-2021 */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java index b1ddbda49..f6eaf83b6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java @@ -34,8 +34,8 @@ import static com.seibel.distanthorizons.core.util.FileScanUtil.LOD_FILE_POSTFIX public class FullDataFileHandler implements IFullDataSourceProvider { public static final boolean USE_LAZY_LOADING = true; - - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); protected static ExecutorService fileHandlerThreadPool; protected static ConfigChangeListener configListener; @@ -56,136 +56,143 @@ public class FullDataFileHandler implements IFullDataSourceProvider // constructor // //=============// - public FullDataFileHandler(IDhLevel level, AbstractSaveStructure saveStructure) + public FullDataFileHandler(IDhLevel level, AbstractSaveStructure saveStructure) { this.level = level; - this.saveDir = saveStructure.getFullDataFolder(level.getLevelWrapper()); + this.saveDir = saveStructure.getFullDataFolder(level.getLevelWrapper()); if (!this.saveDir.exists() && !this.saveDir.mkdirs()) { LOGGER.warn("Unable to create full data folder, file saving may fail."); } FileScanUtil.scanFiles(saveStructure, level.getLevelWrapper(), this, null); - } + } // constructor helpers // /** * Caller must ensure that this method is called only once, - * and that the {@link FullDataFileHandler} is not used before this method is called. + * and that the {@link FullDataFileHandler} is not used before this method is called. */ @Override public void addScannedFile(Collection detectedFiles) { - if (USE_LAZY_LOADING) { + if (USE_LAZY_LOADING) + { lazyAddScannedFile(detectedFiles); } - else { + else + { immediateAddScannedFile(detectedFiles); } } - - private void lazyAddScannedFile(Collection detectedFiles) { - for (File file : detectedFiles) { - try { + + private void lazyAddScannedFile(Collection detectedFiles) + { + for (File file : detectedFiles) + { + try + { DhSectionPos pos = decodePositionByFile(file); - if (pos != null) { + if (pos != null) + { unloadedFiles.put(pos, file); this.topDetailLevel.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel)); } } - catch (Exception e) { + catch (Exception e) + { LOGGER.error("Failed to read data meta file at " + file + ": ", e); FileUtil.renameCorruptedFile(file); } } } - + private void immediateAddScannedFile(Collection detectedFiles) { - HashMultimap filesByPos = HashMultimap.create(); - { // Sort files by pos. - for (File file : detectedFiles) + HashMultimap filesByPos = HashMultimap.create(); + { // Sort files by pos. + for (File file : detectedFiles) { - try + try { - FullDataMetaFile metaFile = new FullDataMetaFile(this, this.level, file); - filesByPos.put(metaFile.pos, metaFile); - } + FullDataMetaFile metaFile = new FullDataMetaFile(this, this.level, file); + filesByPos.put(metaFile.pos, metaFile); + } catch (IOException e) { - LOGGER.error("Failed to read data meta file at "+file+": ", e); - FileUtil.renameCorruptedFile(file); - } - } - } - - // Warn for multiple files with the same pos, and then select the one with the latest timestamp. - for (DhSectionPos pos : filesByPos.keySet()) + LOGGER.error("Failed to read data meta file at " + file + ": ", e); + FileUtil.renameCorruptedFile(file); + } + } + } + + // Warn for multiple files with the same pos, and then select the one with the latest timestamp. + for (DhSectionPos pos : filesByPos.keySet()) { - Collection metaFiles = filesByPos.get(pos); - FullDataMetaFile fileToUse; - if (metaFiles.size() > 1) + Collection metaFiles = filesByPos.get(pos); + FullDataMetaFile fileToUse; + if (metaFiles.size() > 1) { // fileToUse = Collections.max(metaFiles, Comparator.comparingLong(a -> a.metaData.dataVersion.get())); - fileToUse = Collections.max(metaFiles, Comparator.comparingLong(fullDataMetaFile -> fullDataMetaFile.file.lastModified())); - { - StringBuilder sb = new StringBuilder(); - sb.append("Multiple files with the same pos: "); - sb.append(pos); - sb.append("\n"); - for (FullDataMetaFile metaFile : metaFiles) + fileToUse = Collections.max(metaFiles, Comparator.comparingLong(fullDataMetaFile -> fullDataMetaFile.file.lastModified())); + { + StringBuilder sb = new StringBuilder(); + sb.append("Multiple files with the same pos: "); + sb.append(pos); + sb.append("\n"); + for (FullDataMetaFile metaFile : metaFiles) { - sb.append("\t"); - sb.append(metaFile.file); - sb.append("\n"); - } - sb.append("\tUsing: "); - sb.append(fileToUse.file); - sb.append("\n"); - sb.append("(Other files will be renamed by appending \".old\" to their name.)"); - LOGGER.warn(sb.toString()); - - // Rename all other files with the same pos to .old - for (FullDataMetaFile metaFile : metaFiles) + sb.append("\t"); + sb.append(metaFile.file); + sb.append("\n"); + } + sb.append("\tUsing: "); + sb.append(fileToUse.file); + sb.append("\n"); + sb.append("(Other files will be renamed by appending \".old\" to their name.)"); + LOGGER.warn(sb.toString()); + + // Rename all other files with the same pos to .old + for (FullDataMetaFile metaFile : metaFiles) { - if (metaFile == fileToUse) + if (metaFile == fileToUse) { continue; } - File oldFile = new File(metaFile.file + ".old"); - try + File oldFile = new File(metaFile.file + ".old"); + try { - if (!metaFile.file.renameTo(oldFile)) + if (!metaFile.file.renameTo(oldFile)) { throw new RuntimeException("Renaming failed"); } - } + } catch (Exception e) { - LOGGER.error("Failed to rename file: " + metaFile.file + " to " + oldFile, e); - } - } - } - } + LOGGER.error("Failed to rename file: " + metaFile.file + " to " + oldFile, e); + } + } + } + } else { - fileToUse = metaFiles.iterator().next(); - } - // Add file to the list of files. + fileToUse = metaFiles.iterator().next(); + } + // Add file to the list of files. this.topDetailLevel.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, fileToUse.pos.sectionDetailLevel)); this.fileBySectionPos.put(pos, fileToUse); - } - } + } + } - protected FullDataMetaFile getLoadOrMakeFile(DhSectionPos pos, boolean allowCreateFile) + protected FullDataMetaFile getLoadOrMakeFile(DhSectionPos pos, boolean allowCreateFile) { - FullDataMetaFile metaFile = this.fileBySectionPos.get(pos); + FullDataMetaFile metaFile = this.fileBySectionPos.get(pos); if (metaFile != null) return metaFile; - + File fileToLoad = this.unloadedFiles.get(pos); // File does exist, but not loaded yet. if (fileToLoad != null) @@ -244,37 +251,38 @@ public class FullDataFileHandler implements IFullDataSourceProvider // This is a CAS with expected null value. FullDataMetaFile metaFileCas = this.fileBySectionPos.putIfAbsent(pos, metaFile); return metaFileCas == null ? metaFile : metaFileCas; - } + } /** * Populates the preexistingFiles and missingFilePositions ArrayLists. - * + * * @param preexistingFiles the list of {@link FullDataMetaFile}'s that have been created for the given position. * @param missingFilePositions the list of {@link DhSectionPos}'s that don't have {@link FullDataMetaFile} created for them yet. */ - protected void getDataFilesForPosition(DhSectionPos effectivePos, DhSectionPos posAreaToGet, + protected void getDataFilesForPosition( + DhSectionPos effectivePos, DhSectionPos posAreaToGet, ArrayList preexistingFiles, ArrayList missingFilePositions) { - byte sectionDetail = posAreaToGet.sectionDetailLevel; - boolean allEmpty = true; + byte sectionDetail = posAreaToGet.sectionDetailLevel; + boolean allEmpty = true; // get all existing files for this position - outerLoop: - while (--sectionDetail >= this.minDetailLevel) + outerLoop: + while (--sectionDetail >= this.minDetailLevel) { - DhLodPos minPos = posAreaToGet.getCorner().getCornerLodPos(sectionDetail); - int count = posAreaToGet.getSectionBBoxPos().getWidthAtDetail(sectionDetail); + DhLodPos minPos = posAreaToGet.getCorner().getCornerLodPos(sectionDetail); + int count = posAreaToGet.getSectionBBoxPos().getWidthAtDetail(sectionDetail); - for (int xOffset = 0; xOffset < count; xOffset++) + for (int xOffset = 0; xOffset < count; xOffset++) { - for (int zOffset = 0; zOffset < count; zOffset++) + for (int zOffset = 0; zOffset < count; zOffset++) { - DhSectionPos subPos = new DhSectionPos(sectionDetail, xOffset+minPos.x, zOffset+minPos.z); - LodUtil.assertTrue(posAreaToGet.overlaps(effectivePos) && subPos.overlaps(posAreaToGet)); - - //TODO: The following check is temporary as we only sample corner points, which means - // on a very different level, we may not need the entire section at all. - if (!CompleteFullDataSource.firstDataPosCanAffectSecond(effectivePos, subPos)) + DhSectionPos subPos = new DhSectionPos(sectionDetail, xOffset + minPos.x, zOffset + minPos.z); + LodUtil.assertTrue(posAreaToGet.overlaps(effectivePos) && subPos.overlaps(posAreaToGet)); + + //TODO: The following check is temporary as we only sample corner points, which means + // on a very different level, we may not need the entire section at all. + if (!CompleteFullDataSource.firstDataPosCanAffectSecond(effectivePos, subPos)) { continue; } @@ -282,28 +290,28 @@ public class FullDataFileHandler implements IFullDataSourceProvider // check if a file for this pos exists, either loaded and unloaded if (this.fileBySectionPos.containsKey(subPos) || this.unloadedFiles.containsKey(subPos)) { - allEmpty = false; - break outerLoop; - } - } - } - } + allEmpty = false; + break outerLoop; + } + } + } + } - if (allEmpty) + if (allEmpty) { // there are no children to this quad tree, // add this leaf's position - missingFilePositions.add(posAreaToGet); - } - else + missingFilePositions.add(posAreaToGet); + } + else { // there are children in this quad tree, search them this.recursiveGetDataFilesForPosition(0, effectivePos, posAreaToGet, preexistingFiles, missingFilePositions); this.recursiveGetDataFilesForPosition(1, effectivePos, posAreaToGet, preexistingFiles, missingFilePositions); this.recursiveGetDataFilesForPosition(2, effectivePos, posAreaToGet, preexistingFiles, missingFilePositions); this.recursiveGetDataFilesForPosition(3, effectivePos, posAreaToGet, preexistingFiles, missingFilePositions); - } - } + } + } private void recursiveGetDataFilesForPosition(int childIndex, DhSectionPos basePos, DhSectionPos pos, ArrayList preexistingFiles, ArrayList missingFilePositions) { DhSectionPos childPos = pos.getChildByIndex(childIndex); @@ -345,11 +353,11 @@ public class FullDataFileHandler implements IFullDataSourceProvider * This call is concurrent. I.e. it supports being called by multiple threads at the same time. */ @Override - public CompletableFuture read(DhSectionPos pos) + public CompletableFuture read(DhSectionPos pos) { this.topDetailLevel.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel)); - FullDataMetaFile metaFile = this.getLoadOrMakeFile(pos, true); - if (metaFile == null) + FullDataMetaFile metaFile = this.getLoadOrMakeFile(pos, true); + if (metaFile == null) { return CompletableFuture.completedFuture(null); } @@ -358,58 +366,58 @@ public class FullDataFileHandler implements IFullDataSourceProvider // future wrapper necessary in order to handle file read errors CompletableFuture futureWrapper = new CompletableFuture<>(); metaFile.loadOrGetCachedDataSourceAsync().exceptionally((e) -> - { - FullDataMetaFile newMetaFile = this.removeCorruptedFile(pos, metaFile, e); - - futureWrapper.completeExceptionally(e); - return null; // return value doesn't matter - }) - .whenComplete((dataSource, e) -> - { - futureWrapper.complete(dataSource); - }); + { + FullDataMetaFile newMetaFile = this.removeCorruptedFile(pos, metaFile, e); + + futureWrapper.completeExceptionally(e); + return null; // return value doesn't matter + }) + .whenComplete((dataSource, e) -> + { + futureWrapper.complete(dataSource); + }); return futureWrapper; - } + } - /** This call is concurrent. I.e. it supports being called by multiple threads at the same time. */ - @Override - public void write(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView) + /** This call is concurrent. I.e. it supports being called by multiple threads at the same time. */ + @Override + public void write(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView) { - DhLodPos chunkPos = chunkDataView.getLodPos(); - LodUtil.assertTrue(chunkPos.overlapsExactly(sectionPos.getSectionBBoxPos()), "Chunk "+chunkPos+" does not overlap section "+sectionPos); + DhLodPos chunkPos = chunkDataView.getLodPos(); + LodUtil.assertTrue(chunkPos.overlapsExactly(sectionPos.getSectionBBoxPos()), "Chunk " + chunkPos + " does not overlap section " + sectionPos); - chunkPos = chunkPos.convertToDetailLevel((byte) this.minDetailLevel); + chunkPos = chunkPos.convertToDetailLevel((byte) this.minDetailLevel); this.writeChunkDataToMetaFile(new DhSectionPos(chunkPos.detailLevel, chunkPos.x, chunkPos.z), chunkDataView); - } - private void writeChunkDataToMetaFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData) + } + private void writeChunkDataToMetaFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData) { - FullDataMetaFile metaFile = this.fileBySectionPos.get(sectionPos); - if (metaFile != null) - { + FullDataMetaFile metaFile = this.fileBySectionPos.get(sectionPos); + if (metaFile != null) + { // there is a file for this position - metaFile.addToWriteQueue(chunkData); - } + metaFile.addToWriteQueue(chunkData); + } - if (sectionPos.sectionDetailLevel <= this.topDetailLevel.get()) + if (sectionPos.sectionDetailLevel <= this.topDetailLevel.get()) { // recursively attempt to get the meta file for this position this.writeChunkDataToMetaFile(sectionPos.getParentPos(), chunkData); - } - } + } + } - /** This call is concurrent. I.e. it supports multiple threads calling this method at the same time. */ - @Override - public CompletableFuture flushAndSave() + /** This call is concurrent. I.e. it supports multiple threads calling this method at the same time. */ + @Override + public CompletableFuture flushAndSave() { - ArrayList> futures = new ArrayList<>(); - for (FullDataMetaFile metaFile : this.fileBySectionPos.values()) + ArrayList> futures = new ArrayList<>(); + for (FullDataMetaFile metaFile : this.fileBySectionPos.values()) { - futures.add(metaFile.flushAndSaveAsync()); - } - return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); - } - + futures.add(metaFile.flushAndSaveAsync()); + } + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + } + @Override public CompletableFuture flushAndSave(DhSectionPos sectionPos) { @@ -431,7 +439,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider protected IIncompleteFullDataSource makeEmptyDataSource(DhSectionPos pos) { return pos.sectionDetailLevel <= HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL ? - HighDetailIncompleteFullDataSource.createEmpty(pos) : + HighDetailIncompleteFullDataSource.createEmpty(pos) : LowDetailIncompleteFullDataSource.createEmpty(pos); } @@ -443,22 +451,22 @@ public class FullDataFileHandler implements IFullDataSourceProvider for (FullDataMetaFile existingFile : existingFiles) { loadDataFutures.add(existingFile.loadOrGetCachedDataSourceAsync() - .exceptionally((ex) -> /*Ignore file read errors*/null) - .thenAccept((existingFullDataSource) -> - { - if (existingFullDataSource == null) + .exceptionally((ex) -> /*Ignore file read errors*/null) + .thenAccept((existingFullDataSource) -> { - return; - } - - //LOGGER.info("Merging data from {} into {}", data.getSectionPos(), pos); - recipientFullDataSource.sampleFrom(existingFullDataSource); - }) + if (existingFullDataSource == null) + { + return; + } + + //LOGGER.info("Merging data from {} into {}", data.getSectionPos(), pos); + recipientFullDataSource.sampleFrom(existingFullDataSource); + }) ); } return CompletableFuture.allOf(loadDataFutures.toArray(new CompletableFuture[0])).thenApply(voidObj -> recipientFullDataSource); } - + protected void makeFiles(ArrayList posList, ArrayList output) { for (DhSectionPos missingPos : posList) @@ -470,35 +478,35 @@ public class FullDataFileHandler implements IFullDataSourceProvider } } } - - @Override - public CompletableFuture onCreateDataFile(FullDataMetaFile file) + + @Override + public CompletableFuture onCreateDataFile(FullDataMetaFile file) { - DhSectionPos pos = file.pos; + DhSectionPos pos = file.pos; IIncompleteFullDataSource source = this.makeEmptyDataSource(pos); - ArrayList existFiles = new ArrayList<>(); - ArrayList missing = new ArrayList<>(); + ArrayList existFiles = new ArrayList<>(); + ArrayList missing = new ArrayList<>(); this.getDataFilesForPosition(pos, pos, existFiles, missing); - LodUtil.assertTrue(!missing.isEmpty() || !existFiles.isEmpty()); - if (missing.size() == 1 && existFiles.isEmpty() && missing.get(0).equals(pos)) + LodUtil.assertTrue(!missing.isEmpty() || !existFiles.isEmpty()); + if (missing.size() == 1 && existFiles.isEmpty() && missing.get(0).equals(pos)) { - // None exist. + // None exist. return CompletableFuture.completedFuture(source); - } + } else { this.makeFiles(missing, existFiles); return this.sampleFromFileArray(source, existFiles).thenApply(IIncompleteFullDataSource::tryPromotingToCompleteDataSource) - .exceptionally((e) -> - { - FullDataMetaFile newMetaFile = this.removeCorruptedFile(pos, file, e); - return null; - }); - } - } + .exceptionally((e) -> + { + FullDataMetaFile newMetaFile = this.removeCorruptedFile(pos, file, e); + return null; + }); + } + } protected FullDataMetaFile removeCorruptedFile(DhSectionPos pos, FullDataMetaFile metaFile, Throwable exception) { - LOGGER.error("Error reading Data file ["+pos+"]", exception); + LOGGER.error("Error reading Data file [" + pos + "]", exception); FileUtil.renameCorruptedFile(metaFile.file); // remove the FullDataMetaFile since the old one was corrupted @@ -508,32 +516,33 @@ public class FullDataFileHandler implements IFullDataSourceProvider } @Override - public CompletableFuture onDataFileUpdate(IFullDataSource source, FullDataMetaFile file, - Consumer onUpdated, Function updater) + public CompletableFuture onDataFileUpdate( + IFullDataSource source, FullDataMetaFile file, + Consumer onUpdated, Function updater) { - boolean changed = updater.apply(source); + boolean changed = updater.apply(source); // if (changed) // { // metaData.dataVersion.incrementAndGet(); // } - if (source instanceof IIncompleteFullDataSource) + if (source instanceof IIncompleteFullDataSource) { - IFullDataSource newSource = ((IIncompleteFullDataSource) source).tryPromotingToCompleteDataSource(); - changed |= newSource != source; - source = newSource; - } + IFullDataSource newSource = ((IIncompleteFullDataSource) source).tryPromotingToCompleteDataSource(); + changed |= newSource != source; + source = newSource; + } - if (changed) + if (changed) { onUpdated.accept(source); } - return CompletableFuture.completedFuture(source); - } + return CompletableFuture.completedFuture(source); + } + + @Override + public File computeDataFilePath(DhSectionPos pos) { return new File(this.saveDir, pos.serialize() + LOD_FILE_POSTFIX); } - @Override - public File computeDataFilePath(DhSectionPos pos) { return new File(this.saveDir, pos.serialize() + LOD_FILE_POSTFIX); } - @Nullable public DhSectionPos decodePositionByFile(File file) { @@ -563,11 +572,11 @@ public class FullDataFileHandler implements IFullDataSourceProvider if (fileHandlerThreadPool == null || fileHandlerThreadPool.isTerminated()) { - LOGGER.info("Starting "+FullDataFileHandler.class.getSimpleName()); + LOGGER.info("Starting " + FullDataFileHandler.class.getSimpleName()); setThreadPoolSize(Config.Client.Advanced.MultiThreading.numberOfFileHandlerThreads.get()); } } - public static void setThreadPoolSize(int threadPoolSize) + public static void setThreadPoolSize(int threadPoolSize) { if (fileHandlerThreadPool != null) { @@ -575,7 +584,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider fileHandlerThreadPool.shutdown(); } - fileHandlerThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, FullDataFileHandler.class.getSimpleName()+"Thread", Config.Client.Advanced.MultiThreading.runTimeRatioForFileHandlerThreads); + fileHandlerThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, FullDataFileHandler.class.getSimpleName() + "Thread", Config.Client.Advanced.MultiThreading.runTimeRatioForFileHandlerThreads); } /** @@ -586,7 +595,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider { if (fileHandlerThreadPool != null) { - LOGGER.info("Stopping "+ FullDataFileHandler.class.getSimpleName()); + LOGGER.info("Stopping " + FullDataFileHandler.class.getSimpleName()); fileHandlerThreadPool.shutdownNow(); } } @@ -600,9 +609,10 @@ public class FullDataFileHandler implements IFullDataSourceProvider // cleanup // //=========// - @Override - public void close() + @Override + public void close() { - FullDataMetaFile.debugPhantomLifeCycleCheck(); - } + FullDataMetaFile.debugPhantomLifeCycleCheck(); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java index bf7b6f91a..a229b309c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantReadWriteLock; + import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource; import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource; @@ -32,68 +33,81 @@ import org.apache.logging.log4j.Logger; public class FullDataMetaFile extends AbstractMetaDataContainerFile implements IDebugRenderable { private static final Logger LOGGER = DhLoggerBuilder.getLogger(FullDataMetaFile.class.getSimpleName()); - + private final IDhLevel level; private final IFullDataSourceProvider fullDataSourceProvider; public boolean doesFileExist; - + //TODO: Atm can't find a better way to store when genQueue is checked. public boolean genQueueChecked = false; - + private volatile boolean markedNeedUpdate = false; - + public AbstractFullDataSourceLoader fullDataSourceLoader; public Class dataType; /** * Can be cleared if the garbage collector determines there isn't enough space.

- * - * When clearing, don't set to null, instead create a SoftReference containing null. + * + * When clearing, don't set to null, instead create a SoftReference containing null. * This will make null checks simpler. */ private SoftReference cachedFullDataSource = new SoftReference<>(null); private final AtomicReference> dataSourceLoadFutureRef = new AtomicReference<>(null); - - private static final class CacheQueryResult { + + private static final class CacheQueryResult + { public final CompletableFuture future; public final boolean needsLoad; - public CacheQueryResult(CompletableFuture future, boolean needsLoad) { + public CacheQueryResult(CompletableFuture future, boolean needsLoad) + { this.future = future; this.needsLoad = needsLoad; } + } - + @Override - public void debugRender(DebugRenderer r) { + public void debugRender(DebugRenderer r) + { if (pos.sectionDetailLevel > DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) return; - + IFullDataSource cached = cachedFullDataSource.get(); if (markedNeedUpdate) r.renderBox(new DebugRenderer.Box(pos, 80f, 96f, 0.05f, Color.red)); - + Color c = Color.black; - if (cached != null) { - if (cached instanceof CompleteFullDataSource) { + if (cached != null) + { + if (cached instanceof CompleteFullDataSource) + { c = Color.GREEN; - } else { + } + else + { c = Color.YELLOW; } - - } else if (dataSourceLoadFutureRef.get() != null) { + + } + else if (dataSourceLoadFutureRef.get() != null) + { c = Color.BLUE; - } else if (doesFileExist) { + } + else if (doesFileExist) + { c = Color.RED; } boolean needUpdate = !this.writeQueueRef.get().queue.isEmpty() || markedNeedUpdate; if (needUpdate) c = c.darker().darker(); r.renderBox(new DebugRenderer.Box(pos, 80f, 96f, 0.05f, c)); } - + //TODO: use ConcurrentAppendSingleSwapContainer instead of below: private static class GuardedMultiAppendQueue { ReentrantReadWriteLock appendLock = new ReentrantReadWriteLock(); ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); + } @@ -101,12 +115,13 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I private final AtomicReference writeQueueRef = new AtomicReference<>(new GuardedMultiAppendQueue()); private GuardedMultiAppendQueue backWriteQueue = new GuardedMultiAppendQueue(); // =========================== - + // ===Object lifetime stuff=== private static final ReferenceQueue lifeCycleDebugQueue = new ReferenceQueue<>(); private static final ReferenceQueue softRefDebugQueue = new ReferenceQueue<>(); private static final Set lifeCycleDebugSet = ConcurrentHashMap.newKeySet(); private static final Set softRefDebugSet = ConcurrentHashMap.newKeySet(); + private static class DataObjTracker extends PhantomReference implements Closeable { public final DhSectionPos pos; @@ -119,8 +134,9 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I } @Override public void close() { lifeCycleDebugSet.remove(this); } + } - + private static class DataObjSoftTracker extends SoftReference implements Closeable { public final FullDataMetaFile file; @@ -132,8 +148,9 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I } @Override public void close() { softRefDebugSet.remove(this); } + } - // =========================== + // =========================== @@ -141,9 +158,10 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I // constructors // //==============// - /** - * Creates a new file. - * @throws FileAlreadyExistsException if a file already exists. + /** + * Creates a new file. + * + * @throws FileAlreadyExistsException if a file already exists. */ public FullDataMetaFile(IFullDataSourceProvider fullDataSourceProvider, IDhLevel level, DhSectionPos pos) throws FileAlreadyExistsException { @@ -157,8 +175,9 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I DebugRenderer.register(this); } - /** + /** * Uses an existing file. + * * @throws IOException if the file was formatted incorrectly * @throws FileNotFoundException if no file exists for the given path */ @@ -176,7 +195,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I if (this.fullDataSourceLoader == null) { // TODO add a hard coded dictionary of known ID name combos so we can easily see in the log if the ID is valid or if the data was corrupted/old - throw new IOException("Invalid file: Data type loader not found: "+this.baseMetaData.dataTypeId+"(v"+this.baseMetaData.binaryDataFormatVersion +")"); + throw new IOException("Invalid file: Data type loader not found: " + this.baseMetaData.dataTypeId + "(v" + this.baseMetaData.binaryDataFormatVersion + ")"); } this.dataType = this.fullDataSourceLoader.clazz; @@ -188,7 +207,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I //==========// // get data // //==========// - + // Try get cached data source. Used for temp impl for re-queueing world gen tasks. // (Read-only access! As writes should always be done async) public IFullDataSource getCachedDataSourceNowOrNull() @@ -196,54 +215,55 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I debugPhantomLifeCycleCheck(); return this.cachedFullDataSource.get(); } - + private void makeUpdateCompletionStage(CompletableFuture completer, CompletableFuture currentStage) { currentStage.thenCompose( - (fullDataSource) -> { - markedNeedUpdate = false; - return this.fullDataSourceProvider.onDataFileUpdate(fullDataSource, this, this::_updateAndWriteDataSource, this::_applyWriteQueueToFullDataSource); - }) - .whenComplete((fullDataSource, ex) -> - { - if (ex != null && !LodUtil.isInterruptOrReject(ex)) + (fullDataSource) -> { + markedNeedUpdate = false; + return this.fullDataSourceProvider.onDataFileUpdate(fullDataSource, this, this::_updateAndWriteDataSource, this::_applyWriteQueueToFullDataSource); + }) + .whenComplete((fullDataSource, ex) -> { - LOGGER.error("Error updating file ["+this.file+"]: ", ex); - } - - if (fullDataSource != null) { - new DataObjTracker(fullDataSource); - new DataObjSoftTracker(this, fullDataSource); - } - //LOGGER.info("Updated file "+this.file); - if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) - DebugRenderer.makeParticle( - new DebugRenderer.BoxParticle( - new DebugRenderer.Box(this.pos, 64f, 72f, 0.03f, Color.green.darker()), - 0.2, 32f - ) - ); - - this.cachedFullDataSource = new SoftReference<>(fullDataSource); - inCrit = false; - dataSourceLoadFutureRef.set(null); - completer.complete(fullDataSource); - - if (this.markedNeedUpdate) - { - // trigger another update - this.loadOrGetCachedDataSourceAsync(); - } - }); + if (ex != null && !LodUtil.isInterruptOrReject(ex)) + { + LOGGER.error("Error updating file [" + this.file + "]: ", ex); + } + + if (fullDataSource != null) + { + new DataObjTracker(fullDataSource); + new DataObjSoftTracker(this, fullDataSource); + } + //LOGGER.info("Updated file "+this.file); + if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) + DebugRenderer.makeParticle( + new DebugRenderer.BoxParticle( + new DebugRenderer.Box(this.pos, 64f, 72f, 0.03f, Color.green.darker()), + 0.2, 32f + ) + ); + + this.cachedFullDataSource = new SoftReference<>(fullDataSource); + inCrit = false; + dataSourceLoadFutureRef.set(null); + completer.complete(fullDataSource); + + if (this.markedNeedUpdate) + { + // trigger another update + this.loadOrGetCachedDataSourceAsync(); + } + }); } - + private void makeLoadCompletionStage(ExecutorService executorService, CompletableFuture completer) { makeUpdateCompletionStage(completer, CompletableFuture.supplyAsync(() -> { // Load the file. IFullDataSource fullDataSource; try (FileInputStream fileInputStream = this.getFileInputStream(); - DhDataInputStream compressedStream = new DhDataInputStream(fileInputStream)) + DhDataInputStream compressedStream = new DhDataInputStream(fileInputStream)) { fullDataSource = this.fullDataSourceLoader.loadData(this, compressedStream, this.level); } @@ -255,31 +275,31 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I return fullDataSource; }, executorService)); } - + private void makeCreateCompletionStage(CompletableFuture completer) { this.makeUpdateCompletionStage(completer, this.fullDataSourceProvider.onCreateDataFile(this) - .thenApply((fullDataSource) -> - { - this.baseMetaData = this._makeBaseMetaData(fullDataSource); - return fullDataSource; - })); + .thenApply((fullDataSource) -> + { + this.baseMetaData = this._makeBaseMetaData(fullDataSource); + return fullDataSource; + })); } - + private volatile boolean inCrit = false; // Cause: Generic Type runtime casting cannot safety check it. // However, the Union type ensures the 'data' should only contain the listed type. public CompletableFuture loadOrGetCachedDataSourceAsync() { debugPhantomLifeCycleCheck(); - + CacheQueryResult result = this.getCachedDataSourceAsync(); - + if (result.needsLoad) { LodUtil.assertTrue(!this.inCrit); this.inCrit = true; - + CompletableFuture future = result.future; // don't continue if the provider has been shut down ExecutorService executorService = this.fullDataSourceProvider.getIOExecutor(); @@ -290,13 +310,13 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I future.complete(null); return future; } - + // create a new Meta file - if (!this.doesFileExist) + if (!this.doesFileExist) { this.makeCreateCompletionStage(future); } - else + else { // Otherwise, load and update file if (this.baseMetaData == null) @@ -310,7 +330,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I return result.future; } - + /** @return a stream for the data contained in this file, skips the metadata from {@link AbstractMetaDataContainerFile}. */ private FileInputStream getFileInputStream() throws IOException { @@ -340,29 +360,34 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I return new BaseMetaData(data.getSectionPos(), -1, data.getDataDetailLevel(), data.getWorldGenStep(), (loader == null ? 0 : loader.datatypeId), data.getBinaryDataFormatVersion()); } - + /** * @return one of the following: - * the cached {@link IFullDataSource}, - * a future that will complete once the {@link FullDataMetaFile#writeQueueRef} has been written, - * or null if nothing has been cached and nothing is being loaded + * the cached {@link IFullDataSource}, + * a future that will complete once the {@link FullDataMetaFile#writeQueueRef} has been written, + * or null if nothing has been cached and nothing is being loaded */ private CacheQueryResult getCachedDataSourceAsync() { // this data source is being written to, use the existing future CompletableFuture dataSourceLoadFuture = this.dataSourceLoadFutureRef.get(); - if (dataSourceLoadFuture != null) { + if (dataSourceLoadFuture != null) + { return new CacheQueryResult(dataSourceLoadFuture, false); } // attempt to get the cached data source IFullDataSource cachedFullDataSource = this.cachedFullDataSource.get(); - if (cachedFullDataSource == null) { + if (cachedFullDataSource == null) + { // Make a new future, and CAS it into the dataSourceLoadFutureRef, or return the existing future CompletableFuture newFuture = new CompletableFuture<>(); CompletableFuture cas = AtomicsUtil.compareAndExchange(dataSourceLoadFutureRef, null, newFuture); - if (cas == null) { + if (cas == null) + { return new CacheQueryResult(newFuture, true); - } else { + } + else + { return new CacheQueryResult(cas, false); } } @@ -370,7 +395,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I { // The file is cached in RAM boolean needUpdate = !this.writeQueueRef.get().queue.isEmpty() || markedNeedUpdate; - + if (!needUpdate) { // return the cached data @@ -401,7 +426,8 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I dataSourceLoadFutureRef.set(null); future.complete(null); } - else { + else + { // write the queue to the data source by triggering an update makeUpdateCompletionStage(future, CompletableFuture.supplyAsync(() -> cachedFullDataSource, executorService)); } @@ -417,7 +443,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I // data updating // //===============// - /** + /** * Adds the given {@link ChunkSizedFullDataAccessor} to the write queue, * which will be applied to the object at some undefined time in the future. */ @@ -427,7 +453,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I DhLodPos chunkLodPos = new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkAccessor.pos.x, chunkAccessor.pos.z); - LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkLodPos), "Chunk pos "+chunkLodPos+" doesn't exactly overlap with section "+this.pos); + LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkLodPos), "Chunk pos " + chunkLodPos + " doesn't exactly overlap with section " + this.pos); //LOGGER.info("Write Chunk {} to file {}", chunkPos, pos); GuardedMultiAppendQueue writeQueue = this.writeQueueRef.get(); @@ -444,7 +470,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I { appendLock.unlock(); } - + this.flushAndSaveAsync(); //LOGGER.info("write queue length for pos "+this.pos+": " + writeQueue.queue.size()); } @@ -458,7 +484,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I if (!isEmpty) { // This will flush the data to disk. - return this.loadOrGetCachedDataSourceAsync().thenApply((fullDataSource) -> null /* ignore the result, just wait for the load to finish*/); + return this.loadOrGetCachedDataSourceAsync().thenApply((fullDataSource) -> null /* ignore the result, just wait for the load to finish*/ ); } else { @@ -475,7 +501,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I // delete the empty data source if (this.file.exists() && !this.file.delete()) { - LOGGER.warn("Failed to delete data file at "+this.file); + LOGGER.warn("Failed to delete data file at " + this.file); } this.doesFileExist = false; } @@ -491,7 +517,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I this.baseMetaData.dataLevel = fullDataSource.getDataDetailLevel(); this.fullDataSourceLoader = AbstractFullDataSourceLoader.getLoader(fullDataSource.getClass(), fullDataSource.getBinaryDataFormatVersion()); - LodUtil.assertTrue(this.fullDataSourceLoader != null, "No loader for "+fullDataSource.getClass()+" (v"+fullDataSource.getBinaryDataFormatVersion()+")"); + LodUtil.assertTrue(this.fullDataSourceLoader != null, "No loader for " + fullDataSource.getClass() + " (v" + fullDataSource.getBinaryDataFormatVersion() + ")"); this.dataType = fullDataSource.getClass(); this.baseMetaData.dataTypeId = (this.fullDataSourceLoader == null) ? 0 : this.fullDataSourceLoader.datatypeId; @@ -507,7 +533,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I } catch (IOException e) { - LOGGER.error("Failed to save updated data file at "+this.file+" for section "+this.pos, e); + LOGGER.error("Failed to save updated data file at " + this.file + " for section " + this.pos, e); } } } @@ -562,7 +588,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I phantom.close(); phantom = (DataObjTracker) lifeCycleDebugQueue.poll(); } - + DataObjSoftTracker soft = (DataObjSoftTracker) softRefDebugQueue.poll(); while (soft != null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java index 5e9c3d96e..99e45dd5f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java @@ -31,7 +31,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler private final AtomicReference worldGenQueueRef = new AtomicReference<>(null); private final ArrayList onWorldGenTaskCompleteListeners = new ArrayList<>(); - + // Use to hold onto incomplete data sources that are waiting for generation, so that they don't get GC'd before they are generated private final ConcurrentHashMap incompleteDataSources = new ConcurrentHashMap<>(); @@ -65,22 +65,26 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler IFullDataSource data = metaFile.getCachedDataSourceNowOrNull(); if (data instanceof CompleteFullDataSource) return; metaFile.genQueueChecked = false; // unset it so it can be checked again - if (data != null) { + if (data != null) + { metaFile.markNeedUpdate(); } }); flushAndSave(); // Trigger an update to the meta files } - public void clearGenerationQueue() { + public void clearGenerationQueue() + { this.worldGenQueueRef.set(null); incompleteDataSources.clear(); // clear the incomplete data sources } - - public void removeGenRequestIf(Function removeIf) { + + public void removeGenRequestIf(Function removeIf) + { this.incompleteDataSources.forEach((pos, dataSource) -> { - if (removeIf.apply(pos)) { + if (removeIf.apply(pos)) + { this.incompleteDataSources.remove(pos); } }); @@ -94,9 +98,11 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler public void removeWorldGenCompleteListener(IOnWorldGenCompleteListener listener) { this.onWorldGenTaskCompleteListeners.remove(listener); } - private IFullDataSource tryPromoteDataSource(IIncompleteFullDataSource source) { + private IFullDataSource tryPromoteDataSource(IIncompleteFullDataSource source) + { IFullDataSource newSource = source.tryPromotingToCompleteDataSource(); - if (newSource instanceof CompleteFullDataSource) { + if (newSource instanceof CompleteFullDataSource) + { incompleteDataSources.remove(source.getSectionPos()); } return newSource; @@ -105,18 +111,21 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler //========// // events // //========// - + @Nullable - private CompletableFuture tryStartGenTask(FullDataMetaFile file, IIncompleteFullDataSource dataSource) { + private CompletableFuture tryStartGenTask(FullDataMetaFile file, IIncompleteFullDataSource dataSource) + { WorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get(); // breaks down the missing positions into the desired detail level that the gen queue could accept - if (worldGenQueue != null && !file.genQueueChecked) { + if (worldGenQueue != null && !file.genQueueChecked) + { DhSectionPos pos = file.pos; file.genQueueChecked = true; byte maxSectDataDetailLevel = worldGenQueue.largestDataDetail; byte targetDataDetailLevel = dataSource.getDataDetailLevel(); - - if (targetDataDetailLevel > maxSectDataDetailLevel) { + + if (targetDataDetailLevel > maxSectDataDetailLevel) + { ArrayList existingFiles = new ArrayList<>(); byte sectDetailLevel = (byte) (DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + maxSectDataDetailLevel); pos.forEachChildAtLevel(sectDetailLevel, p -> existingFiles.add(getLoadOrMakeFile(p, true))); @@ -127,18 +136,21 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler return null; }); } - else { + else + { this.incompleteDataSources.put(pos, dataSource); // queue this section to be generated GenTask genTask = new GenTask(pos, new WeakReference<>(dataSource)); worldGenQueue.submitGenTask(new DhLodPos(pos), dataSource.getDataDetailLevel(), genTask) .whenComplete((genTaskResult, ex) -> { - if (genTaskResult.success) { + if (genTaskResult.success) + { this.onWorldGenTaskComplete(genTaskResult, ex, genTask, pos); this.fireOnGenPosSuccessListeners(pos); } - else { + else + { file.genQueueChecked = false; } this.incompleteDataSources.remove(pos); @@ -149,7 +161,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler } return null; } - + // Try update the gen queue on this data source. If null, then nothing was done. @Nullable private CompletableFuture updateFromExistingDataSources(FullDataMetaFile file, IIncompleteFullDataSource data) @@ -176,7 +188,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler }); } } - + @Override public CompletableFuture onCreateDataFile(FullDataMetaFile file) { @@ -186,27 +198,28 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler // Cant start gen task, so return the data return future == null ? CompletableFuture.completedFuture(data) : future; } - + @Override - public CompletableFuture onDataFileUpdate(IFullDataSource source, FullDataMetaFile file, - Consumer onUpdated, Function updater) + public CompletableFuture onDataFileUpdate( + IFullDataSource source, FullDataMetaFile file, + Consumer onUpdated, Function updater) { boolean changed = updater.apply(source); LodUtil.assertTrue(file.doesFileExist || changed); - + if (source instanceof IIncompleteFullDataSource) { IFullDataSource newSource = tryPromoteDataSource((IIncompleteFullDataSource) source); changed |= newSource != source; source = newSource; } - + if (source instanceof CompleteFullDataSource) { this.fireOnGenPosSuccessListeners(source.getSectionPos()); } this.fireOnGenPosSuccessListeners(source.getSectionPos()); - + if (source instanceof IIncompleteFullDataSource && !file.genQueueChecked) { WorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get(); @@ -223,14 +236,14 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler } } } - + if (changed) { onUpdated.accept(source); } return CompletableFuture.completedFuture(source); } - + private void onWorldGenTaskComplete(WorldGenResult genTaskResult, Throwable exception, GenTask genTask, DhSectionPos pos) { if (exception != null) @@ -324,9 +337,10 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler @Override - public boolean isMemoryAddressValid() { + public boolean isMemoryAddressValid() + { IFullDataSource ref = this.targetFullDataSourceRef.get(); - return ref != null && !((IIncompleteFullDataSource)ref).hasBeenPromoted(); + return ref != null && !((IIncompleteFullDataSource) ref).hasBeenPromoted(); } @Override @@ -346,12 +360,12 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler { if (chunkSizedFullDataSource.getLodPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos().getSectionBBoxPos())) { - ((DhLevel)level).saveWrites(chunkSizedFullDataSource); + ((DhLevel) level).saveWrites(chunkSizedFullDataSource); //GeneratedFullDataFileHandler.this.write(this.loadedTargetFullDataSource.getSectionPos(), chunkSizedFullDataSource); } }; } - + public void releaseStrongReference() { this.loadedTargetFullDataSource = null; } } @@ -365,6 +379,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler { /** Fired whenever a section has completed generating */ void onWorldGenTaskComplete(DhSectionPos pos); + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/IFullDataSourceProvider.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/IFullDataSourceProvider.java index 5c7a846a7..c3de08a84 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/IFullDataSourceProvider.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/IFullDataSourceProvider.java @@ -14,21 +14,21 @@ import java.util.function.Function; public interface IFullDataSourceProvider extends AutoCloseable { - void addScannedFile(Collection detectedFiles); - - CompletableFuture read(DhSectionPos pos); - void write(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData); - CompletableFuture flushAndSave(); - CompletableFuture flushAndSave(DhSectionPos sectionPos); - - void addOnUpdatedListener(Consumer listener); - - //long getCacheVersion(DhSectionPos sectionPos); - //boolean isCacheVersionValid(DhSectionPos sectionPos, long cacheVersion); - - CompletableFuture onCreateDataFile(FullDataMetaFile file); - CompletableFuture onDataFileUpdate(IFullDataSource source, FullDataMetaFile file, Consumer onUpdated, Function updater); - File computeDataFilePath(DhSectionPos pos); - ExecutorService getIOExecutor(); - + void addScannedFile(Collection detectedFiles); + + CompletableFuture read(DhSectionPos pos); + void write(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData); + CompletableFuture flushAndSave(); + CompletableFuture flushAndSave(DhSectionPos sectionPos); + + void addOnUpdatedListener(Consumer listener); + + //long getCacheVersion(DhSectionPos sectionPos); + //boolean isCacheVersionValid(DhSectionPos sectionPos, long cacheVersion); + + CompletableFuture onCreateDataFile(FullDataMetaFile file); + CompletableFuture onDataFileUpdate(IFullDataSource source, FullDataMetaFile file, Consumer onUpdated, Function updater); + File computeDataFilePath(DhSectionPos pos); + ExecutorService getIOExecutor(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java index 575dd2666..54b22366a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java @@ -7,6 +7,6 @@ import java.io.File; public class RemoteFullDataFileHandler extends FullDataFileHandler { - public RemoteFullDataFileHandler(IDhLevel level, AbstractSaveStructure saveStructure) { super(level, saveStructure); } + public RemoteFullDataFileHandler(IDhLevel level, AbstractSaveStructure saveStructure) { super(level, saveStructure); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java index aabe2bcf7..c19cb3116 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java @@ -20,63 +20,63 @@ import org.apache.logging.log4j.Logger; /** * This represents the data appended to any file we write.
* Contains a {@link BaseMetaData} which holds most of the necessary values written to the file.

- * + * * Used size: 40 bytes
* Remaining space: 24 bytes
* Total size: 64 bytes


- * - * + * + * * Metadata format:

* * 4 bytes: metadata identifier bytes: "DHv0" (in ascii: 0x44 48 76 30) this signals the file is in the metadata format
* 4 bytes: section X position
* 4 bytes: section Y position (Unused, for future proofing)
* 4 bytes: section Z position

- * + * * 4 bytes: data checksum
//TODO: Implement checksum * 1 byte: section detail level
* 1 byte: data detail level // Note: not sure if this is needed
* 1 byte: loader version
* 1 byte: unused

- * + * * 8 bytes: datatype identifier

- * + * * 8 bytes: data version *
*/ public abstract class AbstractMetaDataContainerFile { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - - public static final int METADATA_SIZE_IN_BYTES = 64; -// public static final int BUFFER_SIZE = 8192; - public static final int METADATA_RESERVED_SIZE = 24; + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + public static final int METADATA_SIZE_IN_BYTES = 64; + // public static final int BUFFER_SIZE = 8192; + public static final int METADATA_RESERVED_SIZE = 24; /** equivalent to "DHv0" */ - public static final int METADATA_IDENTITY_BYTES = 0x44_48_76_30; + public static final int METADATA_IDENTITY_BYTES = 0x44_48_76_30; - /** + /** * James tested this on windows (2023-02-18) and didn't have any issues, - * so it will be turned on for now. If there turns out to be issues + * so it will be turned on for now. If there turns out to be issues * we can always turn it off.

- * + * * original comment:
- * Currently set to false because for some reason - * Window is throwing PermissionDeniedException when trying to atomic replace a file... + * Currently set to false because for some reason + * Window is throwing PermissionDeniedException when trying to atomic replace a file... */ - public static final boolean USE_ATOMIC_MOVE_REPLACE = true; + public static final boolean USE_ATOMIC_MOVE_REPLACE = true; - /** + /** * Will be null if no file exists for this object.
- * NOTE: Only use {@link BaseMetaData#pos} when initially setting up this object, afterwards the standalone {@link AbstractMetaDataContainerFile#pos} should be used. + * NOTE: Only use {@link BaseMetaData#pos} when initially setting up this object, afterwards the standalone {@link AbstractMetaDataContainerFile#pos} should be used. */ public volatile BaseMetaData baseMetaData = null; /** Should be used instead of the position inside {@link AbstractMetaDataContainerFile#baseMetaData} */ - public final DhSectionPos pos; + public final DhSectionPos pos; + + public File file; - public File file; - private volatile boolean DebugThreadCheck = false; @@ -85,8 +85,9 @@ public abstract class AbstractMetaDataContainerFile // constructors // //==============// - /** - * Create a metaFile in this path. + /** + * Create a metaFile in this path. + * * @throws FileAlreadyExistsException If the path already has a file. */ protected AbstractMetaDataContainerFile(File file, DhSectionPos pos) throws FileAlreadyExistsException @@ -99,8 +100,9 @@ public abstract class AbstractMetaDataContainerFile } } - /** - * Creates an {@link AbstractMetaDataContainerFile} with the file at the given path. + /** + * Creates an {@link AbstractMetaDataContainerFile} with the file at the given path. + * * @throws IOException if the file was formatted incorrectly * @throws FileNotFoundException if no file exists for the given path */ @@ -109,7 +111,7 @@ public abstract class AbstractMetaDataContainerFile this.file = file; if (!file.exists()) { - throw new FileNotFoundException("File not found at ["+file+"]"); + throw new FileNotFoundException("File not found at [" + file + "]"); } validateMetaDataFile(this.file); @@ -117,48 +119,49 @@ public abstract class AbstractMetaDataContainerFile this.pos = this.baseMetaData.pos; } /** - * Attempts to create a new {@link AbstractMetaDataContainerFile} from the given file. + * Attempts to create a new {@link AbstractMetaDataContainerFile} from the given file. + * * @throws IOException if the file was formatted incorrectly */ private static BaseMetaData readMetaDataFromFile(File file) throws IOException { - try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ)) + try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ)) { - ByteBuffer byteBuffer = ByteBuffer.allocate(METADATA_SIZE_IN_BYTES); - channel.read(byteBuffer, 0); - channel.close(); - byteBuffer.flip(); - - int idBytes = byteBuffer.getInt(); - if (idBytes != METADATA_IDENTITY_BYTES) + ByteBuffer byteBuffer = ByteBuffer.allocate(METADATA_SIZE_IN_BYTES); + channel.read(byteBuffer, 0); + channel.close(); + byteBuffer.flip(); + + int idBytes = byteBuffer.getInt(); + if (idBytes != METADATA_IDENTITY_BYTES) { if (file.exists()) { FileUtil.renameCorruptedFile(file); - throw new IOException("Invalid file format: Metadata Identity byte check failed. Expected: ["+METADATA_IDENTITY_BYTES+"], Actual: ["+idBytes+"]."); + throw new IOException("Invalid file format: Metadata Identity byte check failed. Expected: [" + METADATA_IDENTITY_BYTES + "], Actual: [" + idBytes + "]."); } else { - throw new IOException("No file found for meta data. Expected file path: "+file.getPath()); + throw new IOException("No file found for meta data. Expected file path: " + file.getPath()); } - } + } - int x = byteBuffer.getInt(); - int y = byteBuffer.getInt(); // Unused - int z = byteBuffer.getInt(); - int checksum = byteBuffer.getInt(); - byte detailLevel = byteBuffer.get(); - byte dataLevel = byteBuffer.get(); - byte loaderVersion = byteBuffer.get(); + int x = byteBuffer.getInt(); + int y = byteBuffer.getInt(); // Unused + int z = byteBuffer.getInt(); + int checksum = byteBuffer.getInt(); + byte detailLevel = byteBuffer.get(); + byte dataLevel = byteBuffer.get(); + byte loaderVersion = byteBuffer.get(); EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.fromValue(byteBuffer.get()); - long dataTypeId = byteBuffer.getLong(); - long unusedTimestamp = byteBuffer.getLong(); // not currently implemented - LodUtil.assertTrue(byteBuffer.remaining() == METADATA_RESERVED_SIZE); - DhSectionPos dataPos = new DhSectionPos(detailLevel, x, z); + long dataTypeId = byteBuffer.getLong(); + long unusedTimestamp = byteBuffer.getLong(); // not currently implemented + LodUtil.assertTrue(byteBuffer.remaining() == METADATA_RESERVED_SIZE); + DhSectionPos dataPos = new DhSectionPos(detailLevel, x, z); - return new BaseMetaData(dataPos, checksum, dataLevel, worldGenStep, dataTypeId, loaderVersion); - } - } + return new BaseMetaData(dataPos, checksum, dataLevel, worldGenStep, dataTypeId, loaderVersion); + } + } @@ -182,7 +185,7 @@ public abstract class AbstractMetaDataContainerFile this.baseMetaData = readMetaDataFromFile(this.file); if (!this.baseMetaData.pos.equals(this.pos)) { - LOGGER.warn("The file is from a different location than expected! Expected: ["+this.pos+"] but got ["+this.baseMetaData.pos+"]. Ignoring file tag."); + LOGGER.warn("The file is from a different location than expected! Expected: [" + this.pos + "] but got [" + this.baseMetaData.pos + "]. Ignoring file tag."); this.baseMetaData.pos = this.pos; } } @@ -213,8 +216,8 @@ public abstract class AbstractMetaDataContainerFile fileChannel.position(METADATA_SIZE_IN_BYTES); int checksum; - try(DhDataOutputStream compressedOut = new DhDataOutputStream(Channels.newOutputStream(fileChannel)); - CheckedOutputStream checkedOut = new CheckedOutputStream(compressedOut, new Adler32())) // TODO: Is Adler32 ok? + try (DhDataOutputStream compressedOut = new DhDataOutputStream(Channels.newOutputStream(fileChannel)); + CheckedOutputStream checkedOut = new CheckedOutputStream(compressedOut, new Adler32())) // TODO: Is Adler32 ok? { dataWriterFunc.writeBufferToFile(compressedOut); checksum = (int) checkedOut.getChecksum().getValue(); @@ -270,13 +273,13 @@ public abstract class AbstractMetaDataContainerFile boolean fileRemoved = tempFile.delete(); if (!fileRemoved) { - tempDeleteErrorMessage = "Unable to remove Temporary file at: "+tempFile.getPath(); + tempDeleteErrorMessage = "Unable to remove Temporary file at: " + tempFile.getPath(); } } } - catch (SecurityException exception) + catch (SecurityException exception) { - tempDeleteErrorMessage = "Security error: ["+exception.getMessage()+"] when attempting to remove Temporary file at: "+tempFile.getPath(); + tempDeleteErrorMessage = "Security error: [" + exception.getMessage() + "] when attempting to remove Temporary file at: " + tempFile.getPath(); } if (tempDeleteErrorMessage != null) @@ -297,6 +300,7 @@ public abstract class AbstractMetaDataContainerFile public interface IMetaDataWriterFunc { void writeBufferToFile(T t) throws IOException; + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/BaseMetaData.java b/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/BaseMetaData.java index e70d814d9..fefbcc5ef 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/BaseMetaData.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/BaseMetaData.java @@ -5,8 +5,8 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.I import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource; -/** - * Contains and represents the meta information ({@link DhSectionPos}, {@link BaseMetaData#dataLevel}, etc.) +/** + * Contains and represents the meta information ({@link DhSectionPos}, {@link BaseMetaData#dataLevel}, etc.) * stored at the beginning of files that use the {@link AbstractMetaDataContainerFile}.
* Which, as of the time of writing, includes: {@link IFullDataSource} and {@link ColumnRenderSource} files. */ @@ -14,7 +14,7 @@ public class BaseMetaData { public DhSectionPos pos; public int checksum; -// public AtomicLong dataVersion; // currently broken + // public AtomicLong dataVersion; // currently broken public byte dataLevel; // TODO what does this represent? public EDhApiWorldGenerationStep worldGenStep; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/ILodRenderSourceProvider.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/ILodRenderSourceProvider.java index 96e5e829a..f2aa0a5a2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/ILodRenderSourceProvider.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/ILodRenderSourceProvider.java @@ -11,18 +11,18 @@ import java.util.concurrent.CompletableFuture; /** * This represents LOD data that is stored in long term storage (IE LOD files stored on the hard drive)
* Example: {@link RenderSourceFileHandler RenderSourceFileHandler}

- * - * This is used to create {@link ColumnRenderSource}'s + * + * This is used to create {@link ColumnRenderSource}'s */ public interface ILodRenderSourceProvider extends AutoCloseable { - CompletableFuture readAsync(DhSectionPos pos); - void addScannedFile(Collection detectedFiles); - void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData); - CompletableFuture flushAndSaveAsync(); + CompletableFuture readAsync(DhSectionPos pos); + void addScannedFile(Collection detectedFiles); + void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData); + CompletableFuture flushAndSaveAsync(); /** Returns true if the data was refreshed, false otherwise */ - //boolean refreshRenderSource(ColumnRenderSource source); + //boolean refreshRenderSource(ColumnRenderSource source); /** Deletes any data stored in the render cache so it can be re-created */ void deleteRenderCache(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java index 16b15d04d..e7dc376e9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java @@ -35,7 +35,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements /** * Can be cleared if the garbage collector determines there isn't enough space.

* - * When clearing, don't set to null, instead create a SoftReference containing null. + * When clearing, don't set to null, instead create a SoftReference containing null. * This will make null checks simpler. */ private SoftReference cachedRenderDataSource = new SoftReference<>(null); @@ -43,37 +43,47 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements private final RenderSourceFileHandler fileHandler; private boolean doesFileExist; - - private static final class CacheQueryResult { + + private static final class CacheQueryResult + { public final CompletableFuture future; public final boolean needsLoad; - public CacheQueryResult(CompletableFuture future, boolean needsLoad) { + public CacheQueryResult(CompletableFuture future, boolean needsLoad) + { this.future = future; this.needsLoad = needsLoad; } + } - + @Override - public void debugRender(DebugRenderer r) { + public void debugRender(DebugRenderer r) + { ColumnRenderSource cached = cachedRenderDataSource.get(); Color c = Color.black; - if (cached != null) { + if (cached != null) + { c = Color.GREEN; - } else if (renderSourceLoadFutureRef.get() != null) { + } + else if (renderSourceLoadFutureRef.get() != null) + { c = Color.BLUE; - } else if (doesFileExist) { + } + else if (doesFileExist) + { c = Color.RED; } r.renderBox(new DebugRenderer.Box(pos, 64, 72, 0.05f, c)); } - + //=============// // constructor // //=============// /** * NOTE: should only be used if there is NOT an existing file. - * @throws IOException if a file already exists for this position + * + * @throws IOException if a file already exists for this position */ public static RenderMetaDataFile createNewFileForPos(RenderSourceFileHandler fileHandler, DhSectionPos pos) throws IOException { @@ -90,13 +100,14 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements /** * NOTE: should only be used if there IS an existing file. - * @throws IOException if no file exists for this position + * + * @throws IOException if no file exists for this position */ public static RenderMetaDataFile createFromExistingFile(RenderSourceFileHandler fileHandler, File path) throws IOException { return new RenderMetaDataFile(fileHandler, path); } - + private RenderMetaDataFile(RenderSourceFileHandler fileHandler, File path) throws IOException { super(path); @@ -104,36 +115,36 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements LodUtil.assertTrue(this.baseMetaData != null); this.doesFileExist = this.file.exists(); - + DebugRenderer.register(this); } - + public void updateChunkIfSourceExists(ChunkSizedFullDataAccessor chunkDataView, IDhClientLevel level) { DhLodPos chunkPos = chunkDataView.getLodPos(); - LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkPos), "Chunk pos "+chunkPos+" doesn't overlap with section "+this.pos); + LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkPos), "Chunk pos " + chunkPos + " doesn't overlap with section " + this.pos); // update the render source if one exists CompletableFuture renderSourceLoadFuture = getCachedDataSourceAsync(false); if (renderSourceLoadFuture == null) return; - + renderSourceLoadFuture.thenAccept((renderSource) -> { boolean worked = renderSource.fastWrite(chunkDataView, level); - + //if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL+5) { - float offset = new Random(System.nanoTime() ^ Thread.currentThread().getId()).nextFloat() * 16f; - Color c = worked ? Color.blue : Color.red; - DebugRenderer.makeParticle( - new DebugRenderer.BoxParticle( - new DebugRenderer.Box(chunkDataView.getLodPos(), 32f, 64f + offset, 0.07f, c), - 2.0, 16f - ) - ); + float offset = new Random(System.nanoTime() ^ Thread.currentThread().getId()).nextFloat() * 16f; + Color c = worked ? Color.blue : Color.red; + DebugRenderer.makeParticle( + new DebugRenderer.BoxParticle( + new DebugRenderer.Box(chunkDataView.getLodPos(), 32f, 64f + offset, 0.07f, c), + 2.0, 16f + ) + ); //} }); } - public CompletableFuture flushAndSaveAsync(ExecutorService renderCacheThread) + public CompletableFuture flushAndSaveAsync(ExecutorService renderCacheThread) { if (!this.file.exists()) { @@ -148,7 +159,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements } return source.handle((columnRenderSource, ex) -> { if (ex != null && !LodUtil.isInterruptOrReject(ex)) - LOGGER.error("Failed to load render source for "+this.pos+" for flush and saving", ex); + LOGGER.error("Failed to load render source for " + this.pos + " for flush and saving", ex); return null; }); // Otherwise, wait for the data to be read (which also flushes changes to the file). } @@ -156,44 +167,54 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements { // use the existing future CompletableFuture renderSourceLoadFuture = getCachedDataSourceAsync(true); - if (renderSourceLoadFuture == null) { + if (renderSourceLoadFuture == null) + { // Make a new future, and CAS it, or return the existing future CompletableFuture newFuture = new CompletableFuture<>(); CompletableFuture cas = AtomicsUtil.compareAndExchange(renderSourceLoadFutureRef, null, newFuture); - if (cas == null) { + if (cas == null) + { return new CacheQueryResult(newFuture, true); - } else { + } + else + { return new CacheQueryResult(cas, false); } } - else { + else + { return new CacheQueryResult(renderSourceLoadFuture, false); } } - + @Nullable private CompletableFuture getCachedDataSourceAsync(boolean doTriggerUpdate) { // use the existing future CompletableFuture renderSourceLoadFuture = renderSourceLoadFutureRef.get(); - if (renderSourceLoadFuture != null) { + if (renderSourceLoadFuture != null) + { return renderSourceLoadFuture; } // attempt to get the cached render source ColumnRenderSource cachedRenderDataSource = this.cachedRenderDataSource.get(); - if (cachedRenderDataSource == null) { + if (cachedRenderDataSource == null) + { return null; } - else { + else + { if (!doTriggerUpdate) return CompletableFuture.completedFuture(cachedRenderDataSource); // Make a new future, and CAS it, or return the existing future CompletableFuture newFuture = new CompletableFuture<>(); CompletableFuture cas = AtomicsUtil.compareAndExchange(renderSourceLoadFutureRef, null, newFuture); - if (cas == null) { + if (cas == null) + { this.fileHandler.onReadRenderSourceLoadedFromCacheAsync(this, cachedRenderDataSource) // wait for the handler to finish before returning the renderSource .handle((voidObj, ex) -> { - if (ex != null) { + if (ex != null) + { LOGGER.error("Error while updating render source from cache", ex); } newFuture.complete(cachedRenderDataSource); @@ -202,7 +223,8 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements }); return newFuture; } - else { + else + { return cas; } } @@ -215,89 +237,89 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements { return getCachedFuture.future; } - + CompletableFuture future = getCachedFuture.future; // load or create the render source if (!this.doesFileExist) { // create a new Meta file this.fileHandler.onCreateRenderFileAsync(this) - .thenApply((renderSource) -> - { - this.baseMetaData = this.makeMetaData(renderSource); - return renderSource; - }) - .thenCompose((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this)) - .whenComplete((renderSource, ex) -> - { - if (ex != null) + .thenApply((renderSource) -> { - if (!LodUtil.isInterruptOrReject(ex)) - LOGGER.error("Uncaught error on creation {}: ", this.file, ex); - cachedRenderDataSource = new SoftReference<>(null); - renderSourceLoadFutureRef.set(null); - future.complete(null); - } - else + this.baseMetaData = this.makeMetaData(renderSource); + return renderSource; + }) + .thenCompose((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this)) + .whenComplete((renderSource, ex) -> { - cachedRenderDataSource = new SoftReference<>(renderSource); - renderSourceLoadFutureRef.set(null); - future.complete(renderSource); - } - }); + if (ex != null) + { + if (!LodUtil.isInterruptOrReject(ex)) + LOGGER.error("Uncaught error on creation {}: ", this.file, ex); + cachedRenderDataSource = new SoftReference<>(null); + renderSourceLoadFutureRef.set(null); + future.complete(null); + } + else + { + cachedRenderDataSource = new SoftReference<>(renderSource); + renderSourceLoadFutureRef.set(null); + future.complete(renderSource); + } + }); } else { CompletableFuture.supplyAsync(() -> - { - if (this.baseMetaData == null) { - throw new IllegalStateException("Meta data not loaded!"); - } - - // Load the file. - ColumnRenderSource renderSource; - try (FileInputStream fileInputStream = this.getFileInputStream(); - DhDataInputStream compressedStream = new DhDataInputStream(fileInputStream)) - { - renderSource = ColumnRenderLoader.INSTANCE.loadRenderSource(this, compressedStream, level); - } - catch (IOException ex) - { - throw new CompletionException(ex); - } - return renderSource; - }, fileReaderThreads) + if (this.baseMetaData == null) + { + throw new IllegalStateException("Meta data not loaded!"); + } + + // Load the file. + ColumnRenderSource renderSource; + try (FileInputStream fileInputStream = this.getFileInputStream(); + DhDataInputStream compressedStream = new DhDataInputStream(fileInputStream)) + { + renderSource = ColumnRenderLoader.INSTANCE.loadRenderSource(this, compressedStream, level); + } + catch (IOException ex) + { + throw new CompletionException(ex); + } + return renderSource; + }, fileReaderThreads) // TODO: Check for file version and only update if needed. - .thenCompose((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this)) - .whenComplete((renderSource, ex) -> - { - if (ex != null) + .thenCompose((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this)) + .whenComplete((renderSource, ex) -> { - if (!LodUtil.isInterruptOrReject(ex)) - LOGGER.error("Error loading file {}: ", this.file, ex); - cachedRenderDataSource = new SoftReference<>(null); - renderSourceLoadFutureRef.set(null); - future.complete(null); - } - else - { - cachedRenderDataSource = new SoftReference<>(renderSource); - renderSourceLoadFutureRef.set(null); - future.complete(renderSource); - } - }); + if (ex != null) + { + if (!LodUtil.isInterruptOrReject(ex)) + LOGGER.error("Error loading file {}: ", this.file, ex); + cachedRenderDataSource = new SoftReference<>(null); + renderSourceLoadFutureRef.set(null); + future.complete(null); + } + else + { + cachedRenderDataSource = new SoftReference<>(renderSource); + renderSourceLoadFutureRef.set(null); + future.complete(renderSource); + } + }); } return future; } - private BaseMetaData makeMetaData(ColumnRenderSource renderSource) + private BaseMetaData makeMetaData(ColumnRenderSource renderSource) { return new BaseMetaData(renderSource.getSectionPos(), -1, renderSource.getDataDetail(), renderSource.worldGenStep, RenderSourceFileHandler.RENDER_SOURCE_TYPE_ID, renderSource.getRenderDataFormatVersion()); } - private FileInputStream getFileInputStream() throws IOException + private FileInputStream getFileInputStream() throws IOException { FileInputStream fin = new FileInputStream(this.file); int toSkip = METADATA_SIZE_IN_BYTES; @@ -317,11 +339,11 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements } else { - return fin; + return fin; } } - public void save(ColumnRenderSource renderSource) + public void save(ColumnRenderSource renderSource) { if (renderSource.isEmpty()) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java index 75aa3f46e..5f6e7feb1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java @@ -37,11 +37,11 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider public static final boolean USE_LAZY_LOADING = true; public static final long RENDER_SOURCE_TYPE_ID = ColumnRenderSource.TYPE_ID; - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private final ThreadPoolExecutor fileHandlerThreadPool; private final F3Screen.NestedMessage threadPoolMsg; - + private final ConcurrentHashMap unloadedFiles = new ConcurrentHashMap<>(); private final ConcurrentHashMap filesBySectionPos = new ConcurrentHashMap<>(); @@ -50,11 +50,12 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider /** This is the lowest (highest numeric) detail level that this {@link RenderSourceFileHandler} is keeping track of. */ AtomicInteger topDetailLevel = new AtomicInteger(DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); private final IFullDataSourceProvider fullDataSourceProvider; - - enum TaskType { + + enum TaskType + { Read, UpdateReadData, Update, OnLoaded, } - + private final WeakHashMap, TaskType> taskTracker = new WeakHashMap<>(); @@ -65,29 +66,29 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider public RenderSourceFileHandler(IFullDataSourceProvider sourceProvider, IDhClientLevel level, AbstractSaveStructure saveStructure) { - this.fullDataSourceProvider = sourceProvider; - this.level = level; - this.saveDir = saveStructure.getRenderCacheFolder(level.getLevelWrapper()); + this.fullDataSourceProvider = sourceProvider; + this.level = level; + this.saveDir = saveStructure.getRenderCacheFolder(level.getLevelWrapper()); if (!this.saveDir.exists() && !this.saveDir.mkdirs()) { LOGGER.warn("Unable to create render data folder, file saving may fail."); } - this.fileHandlerThreadPool = ThreadUtil.makeSingleThreadPool("Render Source File Handler ["+this.level.getLevelWrapper().getDimensionType().getDimensionName()+"]"); - - + this.fileHandlerThreadPool = ThreadUtil.makeSingleThreadPool("Render Source File Handler [" + this.level.getLevelWrapper().getDimensionType().getDimensionName() + "]"); + + this.threadPoolMsg = new F3Screen.NestedMessage(this::f3Log); FileScanUtil.scanFiles(saveStructure, level.getLevelWrapper(), null, this); - } - + } + /** Returns what should be displayed in Minecraft's F3 debug menu */ private String[] f3Log() { ArrayList lines = new ArrayList<>(); - lines.add("Render Source File Handler ["+this.level.getClientLevelWrapper().getDimensionType().getDimensionName()+"]"); - lines.add(" Loaded files: "+this.filesBySectionPos.size() + " / " + (this.unloadedFiles.size() + this.filesBySectionPos.size())); - lines.add(" Thread pool tasks: "+fileHandlerThreadPool.getQueue().size() + " (completed: " + fileHandlerThreadPool.getCompletedTaskCount() + ")"); - + lines.add("Render Source File Handler [" + this.level.getClientLevelWrapper().getDimensionType().getDimensionName() + "]"); + lines.add(" Loaded files: " + this.filesBySectionPos.size() + " / " + (this.unloadedFiles.size() + this.filesBySectionPos.size())); + lines.add(" Thread pool tasks: " + fileHandlerThreadPool.getQueue().size() + " (completed: " + fileHandlerThreadPool.getCompletedTaskCount() + ")"); + int totalFutures = taskTracker.size(); EnumMap tasksOutstanding = new EnumMap<>(TaskType.class); EnumMap tasksCompleted = new EnumMap<>(TaskType.class); @@ -96,18 +97,23 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider tasksOutstanding.put(type, 0); tasksCompleted.put(type, 0); } - - synchronized (taskTracker) { - for (Map.Entry, TaskType> entry : taskTracker.entrySet()) { - if (entry.getKey().isDone()) { + + synchronized (taskTracker) + { + for (Map.Entry, TaskType> entry : taskTracker.entrySet()) + { + if (entry.getKey().isDone()) + { tasksCompleted.put(entry.getValue(), tasksCompleted.get(entry.getValue()) + 1); - } else { + } + else + { tasksOutstanding.put(entry.getValue(), tasksOutstanding.get(entry.getValue()) + 1); } } } int totalOutstanding = tasksOutstanding.values().stream().mapToInt(Integer::intValue).sum(); - lines.add(" Futures: "+totalFutures + " (outstanding: " + totalOutstanding + ")"); + lines.add(" Futures: " + totalFutures + " (outstanding: " + totalOutstanding + ")"); for (TaskType type : TaskType.values()) { lines.add(" " + type + ": " + tasksOutstanding.get(type) + " / " + (tasksOutstanding.get(type) + tasksCompleted.get(type))); @@ -136,7 +142,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider this.immediateAddScannedFile(detectedFiles); } } - + private void lazyAddScannedFile(Collection detectedFiles) { for (File file : detectedFiles) @@ -160,12 +166,12 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider } catch (Exception e) { - LOGGER.error("Failed to read data meta file at "+file+": ", e); + LOGGER.error("Failed to read data meta file at " + file + ": ", e); FileUtil.renameCorruptedFile(file); } } } - + private void immediateAddScannedFile(Collection newRenderFiles) { HashMultimap filesByPos = HashMultimap.create(); @@ -180,7 +186,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider } catch (IOException e) { - LOGGER.error("Failed to read render meta file at ["+file+"]. Error: ", e); + LOGGER.error("Failed to read render meta file at [" + file + "]. Error: ", e); FileUtil.renameCorruptedFile(file); } } @@ -197,7 +203,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider // use the file's last modified date fileToUse = Collections.max(metaFiles, Comparator.comparingLong(renderMetaDataFile -> renderMetaDataFile.file.lastModified())); - + // fileToUse = Collections.max(metaFiles, Comparator.comparingLong(renderMetaDataFile -> // renderMetaDataFile.metaData.dataVersion.get())); { @@ -248,7 +254,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider this.topDetailLevel.updateAndGet(v -> Math.max(v, pos.sectionDetailLevel)); } } - + protected RenderMetaDataFile getLoadOrMakeFile(DhSectionPos pos, boolean allowCreateFile) { RenderMetaDataFile metaFile = this.filesBySectionPos.get(pos); @@ -257,7 +263,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider return metaFile; } - + File fileToLoad = this.unloadedFiles.get(pos); if (fileToLoad != null && !fileToLoad.exists()) { @@ -322,10 +328,10 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider RenderMetaDataFile metaFileCas = this.filesBySectionPos.putIfAbsent(pos, metaFile); return metaFileCas == null ? metaFile : metaFileCas; } - + /** This call is concurrent. I.e. it supports multiple threads calling this method at the same time. */ - @Override - public CompletableFuture readAsync(DhSectionPos pos) + @Override + public CompletableFuture readAsync(DhSectionPos pos) { // don't continue if the handler has been shut down if (this.fileHandlerThreadPool.isTerminated()) @@ -333,31 +339,31 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider return CompletableFuture.completedFuture(null); } - RenderMetaDataFile metaFile = this.getLoadOrMakeFile(pos, true); - + RenderMetaDataFile metaFile = this.getLoadOrMakeFile(pos, true); + // On error, (when it returns null,) return an empty render source if (metaFile == null) { return CompletableFuture.completedFuture(ColumnRenderSource.createEmptyRenderSource(pos)); } - - CompletableFuture future = metaFile.loadOrGetCachedDataSourceAsync(this.fileHandlerThreadPool, this.level).handle( - (renderSource, exception) -> - { - if (exception != null) - { - LOGGER.error("Uncaught error on "+pos+":", exception); - } - - return (renderSource != null) ? renderSource : ColumnRenderSource.createEmptyRenderSource(pos); - }); - synchronized (this.taskTracker) + CompletableFuture future = metaFile.loadOrGetCachedDataSourceAsync(this.fileHandlerThreadPool, this.level).handle( + (renderSource, exception) -> + { + if (exception != null) + { + LOGGER.error("Uncaught error on " + pos + ":", exception); + } + + return (renderSource != null) ? renderSource : ColumnRenderSource.createEmptyRenderSource(pos); + }); + + synchronized (this.taskTracker) { this.taskTracker.put(future, TaskType.Read); } return future; - } + } public CompletableFuture onCreateRenderFileAsync(RenderMetaDataFile file) { @@ -374,25 +380,27 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider // data saving // //=============// - /** + /** * This call is concurrent. I.e. it supports multiple threads calling this method at the same time.
* This allows fast writes of new data to the render source, without having to wait for the data to be written to disk. */ - @Override - public void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView) + @Override + public void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView) { // convert to the lowest detail level so all detail levels are updated this.fastWriteDataToSourceRecursively(chunkDataView, DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); this.fullDataSourceProvider.write(sectionPos, chunkDataView); - } - + } + private void fastWriteDataToSourceRecursively(ChunkSizedFullDataAccessor chunk, byte sectionDetailLevel) { DhLodPos boundingPos = chunk.getLodPos(); DhLodPos sectPosMin = boundingPos.convertToDetailLevel(sectionDetailLevel); int width = sectionDetailLevel > boundingPos.detailLevel ? 1 : boundingPos.getWidthAtDetail(sectionDetailLevel); - for (int ox = 0; ox < width; ox++) { - for (int oz = 0; oz < width; oz++) { + for (int ox = 0; ox < width; ox++) + { + for (int oz = 0; oz < width; oz++) + { DhSectionPos sectPos = new DhSectionPos(sectionDetailLevel, sectPosMin.x + ox, sectPosMin.z + oz); RenderMetaDataFile metaFile = this.filesBySectionPos.get(sectPos); // bypass the getLoadOrMakeFile(), as we only want in-cache files. if (metaFile != null) @@ -401,17 +409,18 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider } } } - if (sectionDetailLevel < topDetailLevel.get()) { + if (sectionDetailLevel < topDetailLevel.get()) + { fastWriteDataToSourceRecursively(chunk, (byte) (sectionDetailLevel + 1)); } } - - /** This call is concurrent. I.e. it supports multiple threads calling this method at the same time. */ - @Override + + /** This call is concurrent. I.e. it supports multiple threads calling this method at the same time. */ + @Override public CompletableFuture flushAndSaveAsync() { - LOGGER.info("Shutting down "+ RenderSourceFileHandler.class.getSimpleName()+"..."); + LOGGER.info("Shutting down " + RenderSourceFileHandler.class.getSimpleName() + "..."); ArrayList> futures = new ArrayList<>(); for (RenderMetaDataFile metaFile : this.filesBySectionPos.values()) @@ -420,7 +429,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider } return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) - .whenComplete((voidObj, exception) -> LOGGER.info("Finished shutting down "+ RenderSourceFileHandler.class.getSimpleName()) ); + .whenComplete((voidObj, exception) -> LOGGER.info("Finished shutting down " + RenderSourceFileHandler.class.getSimpleName())); } @@ -428,28 +437,29 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider //================// // cache updating // //================// - - private CompletableFuture updateCacheAsync(ColumnRenderSource renderSource, RenderMetaDataFile file) + + private CompletableFuture updateCacheAsync(ColumnRenderSource renderSource, RenderMetaDataFile file) { DebugRenderer.BoxWithLife box = new DebugRenderer.BoxWithLife(new DebugRenderer.Box(renderSource.sectionPos, 74f, 86f, 0.1f, Color.red), 1.0, 32f, Color.green.darker()); - + // get the full data source loading future CompletableFuture fullDataSourceFuture = this.fullDataSourceProvider.read(renderSource.getSectionPos()) - .thenApply((fullDataSource) -> { - // the fullDataSource can be null if the thread this was running on was interrupted - box.box.color = Color.yellow.darker(); - return fullDataSource; - }).exceptionally((ex) -> - { - LOGGER.error("Exception when getting data for updateCache()", ex); - return null; - }); - - synchronized (taskTracker) { + .thenApply((fullDataSource) -> { + // the fullDataSource can be null if the thread this was running on was interrupted + box.box.color = Color.yellow.darker(); + return fullDataSource; + }).exceptionally((ex) -> + { + LOGGER.error("Exception when getting data for updateCache()", ex); + return null; + }); + + synchronized (taskTracker) + { taskTracker.put(fullDataSourceFuture, TaskType.UpdateReadData); } - + // convert the full data source into a render source //LOGGER.info("Recreating cache for {}", data.getSectionPos()); CompletableFuture transformFuture = DataRenderTransformer.transformDataSourceAsync(fullDataSourceFuture, this.level) @@ -457,9 +467,12 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider { if (ex == null) { - try { + try + { this.writeRenderSourceToFile(renderSource, file, newRenderSource); - } catch (Throwable e) { + } + catch (Throwable e) + { LOGGER.error("Exception when writing render data to file: ", e); } } @@ -467,52 +480,57 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider { LOGGER.error("Exception when updating render file using data source: ", ex); } - else { + else + { //LOGGER.info("Interrupted update of render file using data source: ", ex); } box.close(); return null; }); - synchronized (taskTracker) { + synchronized (taskTracker) + { taskTracker.put(transformFuture, TaskType.Update); } return transformFuture; } - - public CompletableFuture onRenderFileLoaded(ColumnRenderSource renderSource, RenderMetaDataFile file) + + public CompletableFuture onRenderFileLoaded(ColumnRenderSource renderSource, RenderMetaDataFile file) { CompletableFuture future = this.updateCacheAsync(renderSource, file).handle((voidObj, ex) -> { - if (ex != null && !LodUtil.isInterruptOrReject(ex)) { + if (ex != null && !LodUtil.isInterruptOrReject(ex)) + { LOGGER.error("Exception when updating render file using data source: ", ex); } return renderSource; }); - synchronized (taskTracker) { + synchronized (taskTracker) + { taskTracker.put(future, TaskType.OnLoaded); } return future; - } + } - public CompletableFuture onReadRenderSourceLoadedFromCacheAsync(RenderMetaDataFile file, ColumnRenderSource data) { + public CompletableFuture onReadRenderSourceLoadedFromCacheAsync(RenderMetaDataFile file, ColumnRenderSource data) + { return this.updateCacheAsync(data, file); } - private void writeRenderSourceToFile(ColumnRenderSource currentRenderSource, RenderMetaDataFile file, ColumnRenderSource newRenderSource) + private void writeRenderSourceToFile(ColumnRenderSource currentRenderSource, RenderMetaDataFile file, ColumnRenderSource newRenderSource) { - if (currentRenderSource == null || newRenderSource == null) + if (currentRenderSource == null || newRenderSource == null) { return; } - currentRenderSource.updateFromRenderSource(newRenderSource); + currentRenderSource.updateFromRenderSource(newRenderSource); currentRenderSource.localVersion.incrementAndGet(); - //file.metaData.dataVersion.set(newDataVersion); - file.baseMetaData.dataLevel = currentRenderSource.getDataDetail(); - file.baseMetaData.dataTypeId = RENDER_SOURCE_TYPE_ID; - file.baseMetaData.binaryDataFormatVersion = currentRenderSource.getRenderDataFormatVersion(); - file.save(currentRenderSource); - } + //file.metaData.dataVersion.set(newDataVersion); + file.baseMetaData.dataLevel = currentRenderSource.getDataDetail(); + file.baseMetaData.dataTypeId = RENDER_SOURCE_TYPE_ID; + file.baseMetaData.binaryDataFormatVersion = currentRenderSource.getRenderDataFormatVersion(); + file.save(currentRenderSource); + } /* public boolean refreshRenderSource(ColumnRenderSource renderSource) { @@ -541,13 +559,13 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider //=====================// // clearing / shutdown // //=====================// - + //private static CompletableFuture cleanupTask; - + @Override public void close() { - LOGGER.info("Closing "+this.getClass().getSimpleName()+" with ["+this.filesBySectionPos.size()+"] files..."); + LOGGER.info("Closing " + this.getClass().getSimpleName() + " with [" + this.filesBySectionPos.size() + "] files..."); /* // queue the file save futures ArrayList> futures = new ArrayList<>(); @@ -580,8 +598,8 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider }); } else {*/ - fileHandlerThreadPool.shutdown(); - threadPoolMsg.close(); + fileHandlerThreadPool.shutdown(); + threadPoolMsg.close(); //} } @@ -611,8 +629,8 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider // helper methods // //================// - public File computeRenderFilePath(DhSectionPos pos) { return new File(this.saveDir, pos.serialize() + RENDER_FILE_POSTFIX);} - + public File computeRenderFilePath(DhSectionPos pos) { return new File(this.saveDir, pos.serialize() + RENDER_FILE_POSTFIX); } + @Nullable public DhSectionPos decodePositionByFile(File file) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/AbstractSaveStructure.java b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/AbstractSaveStructure.java index b8231cf3b..7dd4df934 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/AbstractSaveStructure.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/AbstractSaveStructure.java @@ -8,29 +8,29 @@ import java.io.File; /** * Abstract class for determining where LOD data should be saved to. - * + * * @version 2022-12-17 */ public abstract class AbstractSaveStructure implements AutoCloseable { - public static final String RENDER_CACHE_FOLDER = "renderCache"; - public static final String DATA_FOLDER = "data"; + public static final String RENDER_CACHE_FOLDER = "renderCache"; + public static final String DATA_FOLDER = "data"; - protected static final Logger LOGGER = DhLoggerBuilder.getLogger(); + protected static final Logger LOGGER = DhLoggerBuilder.getLogger(); - /** + /** * Attempts to return the folder that contains LOD data for the given {@link ILevelWrapper}. * If no appropriate folder exists, one will be created.

- * + * * This will always return a folder, however that folder may not be the best match * if multiverse support is enabled. - * */ - public abstract File getLevelFolder(ILevelWrapper wrapper); + */ + public abstract File getLevelFolder(ILevelWrapper wrapper); - /** Will return null if no parent folder exists for the given {@link ILevelWrapper}.*/ - public abstract File getRenderCacheFolder(ILevelWrapper world); - /** Will return null if no parent folder exists for the given {@link ILevelWrapper}.*/ - public abstract File getFullDataFolder(ILevelWrapper world); + /** Will return null if no parent folder exists for the given {@link ILevelWrapper}. */ + public abstract File getRenderCacheFolder(ILevelWrapper world); + /** Will return null if no parent folder exists for the given {@link ILevelWrapper}. */ + public abstract File getFullDataFolder(ILevelWrapper world); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java index e1b9028f6..2b0ec913a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java @@ -29,32 +29,32 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftSharedWrapper MC_SHARED = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class); public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]"; - + SubDimensionLevelMatcher subDimMatcher = null; final HashMap levelWrapperToFileMap = new HashMap<>(); - - - + + + public ClientOnlySaveStructure() { this.folder = new File(getSaveStructureFolderPath()); - + if (!this.folder.exists()) { if (!this.folder.mkdirs()) { - LOGGER.warn("Unable to create folder [" + this.folder.getPath() + "]"); + LOGGER.warn("Unable to create folder [" + this.folder.getPath() + "]"); //TODO: Deal with errors } } } - - - + + + //================// // folder methods // //================// - + @Override public File getLevelFolder(ILevelWrapper levelWrapper) { @@ -64,7 +64,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure if (newLevelWrapper instanceof IServerKeyedClientLevel) { IServerKeyedClientLevel keyedClientLevel = (IServerKeyedClientLevel) newLevelWrapper; - LOGGER.info("Loading level "+newLevelWrapper.getDimensionType().getDimensionName()+" with key: "+keyedClientLevel.getServerLevelKey()); + LOGGER.info("Loading level " + newLevelWrapper.getDimensionType().getDimensionName() + " with key: " + keyedClientLevel.getServerLevelKey()); // This world was identified by the server directly, so we can know for sure which folder to use. return new File(getSaveStructureFolderPath() + File.separatorChar + keyedClientLevel.getServerLevelKey()); } @@ -78,7 +78,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure { LOGGER.info("Loading level " + newLevelWrapper.getDimensionType().getDimensionName()); this.subDimMatcher = new SubDimensionLevelMatcher(newLevelWrapper, this.folder, - this.getMatchingLevelFolders(newLevelWrapper).toArray(new File[0] /* surprisingly we don't need to create an array of any specific size for this to work */)); + this.getMatchingLevelFolders(newLevelWrapper).toArray(new File[0] /* surprisingly we don't need to create an array of any specific size for this to work */ )); } File levelFile = this.subDimMatcher.tryGetLevel(); @@ -103,7 +103,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure return this.getLevelFolderWithoutSimilarityMatching(newLevelWrapper); }); } - + private File getLevelFolderWithoutSimilarityMatching(ILevelWrapper level) { List folders = this.getMatchingLevelFolders(level); @@ -120,7 +120,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure return new File(this.folder, level.getDimensionType().getDimensionName()); } } - + public List getMatchingLevelFolders(@Nullable ILevelWrapper level) { File[] folders = this.folder.listFiles(); @@ -128,7 +128,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure { return new ArrayList<>(0); } - + Stream fileStream = Arrays.stream(folders).filter( (folder) -> { @@ -142,10 +142,10 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure } } ).sorted(); - + return fileStream.collect(Collectors.toList()); } - + @Override public File getRenderCacheFolder(ILevelWrapper level) { @@ -154,10 +154,10 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure { return null; } - + return new File(levelFolder, RENDER_CACHE_FOLDER); } - + @Override public File getFullDataFolder(ILevelWrapper level) { @@ -166,16 +166,16 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure { return null; } - + return new File(levelFolder, DATA_FOLDER); } - - - + + + //================// // helper methods // //================// - + /** Returns true if the given folder holds valid Lod Dimension data */ private static boolean isValidLevelFolder(File potentialFolder) { @@ -184,12 +184,12 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure // a valid level folder needs to be a folder return false; } - + // filter out any non-DH folders File[] files = potentialFolder.listFiles((file) -> file.isDirectory() && (file.getName().equalsIgnoreCase(RENDER_CACHE_FOLDER) || file.getName().equalsIgnoreCase(DATA_FOLDER))); - + // a valid level folder needs to have DH specific folders in it return files != null && files.length != 0; } @@ -210,14 +210,14 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure ParsedIp parsedIp = new ParsedIp(MC_CLIENT.getCurrentServerIp()); String serverIpCleaned = parsedIp.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, ""); String serverPortCleaned = parsedIp.port != null ? parsedIp.port.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "") : ""; - - + + // determine the auto folder name format EServerFolderNameMode folderNameMode = Config.Client.Advanced.Multiplayer.serverFolderNameMode.get(); String serverName = MC_CLIENT.getCurrentServerName().replaceAll(INVALID_FILE_CHARACTERS_REGEX, ""); String serverMcVersion = MC_CLIENT.getCurrentServerVersion().replaceAll(INVALID_FILE_CHARACTERS_REGEX, ""); - - + + // generate the folder name String folderName; switch (folderNameMode) @@ -226,7 +226,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure case NAME_ONLY: folderName = serverName; break; - + case NAME_IP: folderName = serverName + ", IP " + serverIpCleaned; break; @@ -237,7 +237,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure folderName = serverName + ", IP " + serverIpCleaned + (serverPortCleaned.length() != 0 ? ("-" + serverPortCleaned) : "") + ", GameVersion " + serverMcVersion; break; } - + // PercentEscaper makes the characters all part of the standard alphameric character set // This fixes some issues when the server is named something in other languages return new PercentEscaper("", true).escape(folderName); @@ -248,11 +248,11 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure //==================// // override methods // //==================// - + @Override public void close() { this.subDimMatcher.close(); } - + @Override public String toString() { return "[" + this.getClass().getSimpleName() + "@" + this.folder.getName() + "]"; } - + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/LocalSaveStructure.java b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/LocalSaveStructure.java index 8f89d5d5c..5ff366067 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/LocalSaveStructure.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/LocalSaveStructure.java @@ -7,18 +7,18 @@ import java.io.File; /** * Designed for Client_Server & Server_Only environments. - * + * * @version 2022-12-17 */ public class LocalSaveStructure extends AbstractSaveStructure { public static final String SERVER_FOLDER_NAME = "Distant_Horizons"; - private File debugPath = new File(""); - + private File debugPath = new File(""); - public LocalSaveStructure() { } + + public LocalSaveStructure() { } @@ -27,28 +27,28 @@ public class LocalSaveStructure extends AbstractSaveStructure //================// @Override - public File getLevelFolder(ILevelWrapper wrapper) + public File getLevelFolder(ILevelWrapper wrapper) { - IServerLevelWrapper serverSide = (IServerLevelWrapper) wrapper; - this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons"); - return new File(serverSide.getSaveFolder(), "Distant_Horizons"); - } - - @Override - public File getRenderCacheFolder(ILevelWrapper level) + IServerLevelWrapper serverSide = (IServerLevelWrapper) wrapper; + this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons"); + return new File(serverSide.getSaveFolder(), "Distant_Horizons"); + } + + @Override + public File getRenderCacheFolder(ILevelWrapper level) { - IServerLevelWrapper serverSide = (IServerLevelWrapper) level; - this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons"); - return new File(new File(serverSide.getSaveFolder(), "Distant_Horizons"), RENDER_CACHE_FOLDER); - } - - @Override - public File getFullDataFolder(ILevelWrapper level) + IServerLevelWrapper serverSide = (IServerLevelWrapper) level; + this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons"); + return new File(new File(serverSide.getSaveFolder(), "Distant_Horizons"), RENDER_CACHE_FOLDER); + } + + @Override + public File getFullDataFolder(ILevelWrapper level) { - IServerLevelWrapper serverLevelWrapper = (IServerLevelWrapper) level; - this.debugPath = new File(serverLevelWrapper.getSaveFolder(), SERVER_FOLDER_NAME); - return new File(new File(serverLevelWrapper.getSaveFolder(), SERVER_FOLDER_NAME), DATA_FOLDER); - } + IServerLevelWrapper serverLevelWrapper = (IServerLevelWrapper) level; + this.debugPath = new File(serverLevelWrapper.getSaveFolder(), SERVER_FOLDER_NAME); + return new File(new File(serverLevelWrapper.getSaveFolder(), SERVER_FOLDER_NAME), DATA_FOLDER); + } @@ -57,9 +57,9 @@ public class LocalSaveStructure extends AbstractSaveStructure //==================// @Override - public void close() throws Exception { } + public void close() throws Exception { } - @Override + @Override public String toString() { return "[" + this.getClass().getSimpleName() + "@" + this.debugPath + "]"; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimCompare.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimCompare.java index 304257d17..83db53754 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimCompare.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimCompare.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.file.subDimMatching; import com.seibel.distanthorizons.core.config.Config; @@ -35,7 +35,7 @@ import java.io.File; */ public class SubDimCompare implements Comparable { - /** + /** * the maximum distance in blocks a player can be away from the * given dimension and still be considered in the same place. */ @@ -79,7 +79,8 @@ public class SubDimCompare implements Comparable public boolean isValidSubDim() { double minimumSimilarityRequired = Config.Client.Advanced.Multiplayer.multiverseSimilarityRequiredPercent.get(); - return this.getPercentEqual() >= minimumSimilarityRequired + return this.getPercentEqual() >= minimumSimilarityRequired || this.playerPosDist <= MAX_SIMILAR_PLAYER_POS_DISTANCE_IN_BLOCKS; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java index e99c91f13..4ef8698fd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * Used to allow multiple levels using the same dimension type.
* This is specifically needed for servers running the Multiverse plugin (or similar). - * + * * @author James Seibel * @version 12-17-2022 */ @@ -124,6 +124,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable * Currently this method checks a single chunk (where the player is) * and compares it against the same chunk position in the other dimension worlds to * guess which world the player is in. + * * @throws IOException if the folder doesn't exist or can't be accessed */ public File attemptToDetermineSubDimensionFolder() throws IOException @@ -154,17 +155,17 @@ public class SubDimensionLevelMatcher implements AutoCloseable } //TODO: Compute a ChunkData from current chunk. - - // generate a LOD to test against - boolean lodGenerated = LodDataBuilder.canGenerateLodFromChunk(newlyLoadedChunk); - if (!lodGenerated) - return null; - - // log the start of this attempt - LOGGER.info("Attempting to determine sub-dimension for [" + MC_CLIENT.getWrappedClientWorld().getDimensionType().getDimensionName() + "]"); - LOGGER.info("Player block pos in dimension: [" + playerData.playerBlockPos.getX() + "," + playerData.playerBlockPos.getY() + "," + playerData.playerBlockPos.getZ() + "]"); - - // new chunk data + + // generate a LOD to test against + boolean lodGenerated = LodDataBuilder.canGenerateLodFromChunk(newlyLoadedChunk); + if (!lodGenerated) + return null; + + // log the start of this attempt + LOGGER.info("Attempting to determine sub-dimension for [" + MC_CLIENT.getWrappedClientWorld().getDimensionType().getDimensionName() + "]"); + LOGGER.info("Player block pos in dimension: [" + playerData.playerBlockPos.getX() + "," + playerData.playerBlockPos.getY() + "," + playerData.playerBlockPos.getZ() + "]"); + + // new chunk data ChunkSizedFullDataAccessor newChunkSizedFullDataView = LodDataBuilder.createChunkData(newlyLoadedChunk); long[][][] newChunkData = new long[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH][]; if (newChunkSizedFullDataView != null) @@ -178,25 +179,25 @@ public class SubDimensionLevelMatcher implements AutoCloseable } } } - boolean newChunkHasData = newChunkSizedFullDataView != null && newChunkSizedFullDataView.nonEmptyCount() != 0; - - // check if the chunk is actually empty - if (!newChunkHasData) - { - if (newlyLoadedChunk.getHeight() != 0) - { - // the chunk isn't empty but the LOD is... - - String message = "Error: the chunk at (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") has a height of [" + newlyLoadedChunk.getHeight() + "] but the LOD generated is empty!"; - LOGGER.error(message); - } - else - { - String message = "Warning: The chunk at (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") is empty."; - LOGGER.warn(message); - } - return null; - } + boolean newChunkHasData = newChunkSizedFullDataView != null && newChunkSizedFullDataView.nonEmptyCount() != 0; + + // check if the chunk is actually empty + if (!newChunkHasData) + { + if (newlyLoadedChunk.getHeight() != 0) + { + // the chunk isn't empty but the LOD is... + + String message = "Error: the chunk at (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") has a height of [" + newlyLoadedChunk.getHeight() + "] but the LOD generated is empty!"; + LOGGER.error(message); + } + else + { + String message = "Warning: The chunk at (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") is empty."; + LOGGER.warn(message); + } + return null; + } // compare each world with the newly loaded one @@ -223,7 +224,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable IDhLevel tempLevel = new DhClientLevel(new ClientOnlySaveStructure(), clientLevelWrapper); IFullDataSourceProvider fileHandler = new FullDataFileHandler(tempLevel, tempLevel.getSaveStructure()); CompletableFuture testDataSource = fileHandler.read(new DhSectionPos(playerChunkPos)); - IFullDataSource lodDataSource = testDataSource.get(); + IFullDataSource lodDataSource = testDataSource.get(); // convert the data source into a raw LOD data array diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java index efe6f9856..00de5b236 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionPlayerData.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.file.subDimMatching; @@ -86,9 +86,10 @@ public class SubDimensionPlayerData public SubDimensionPlayerData(File dimensionFolder) { File file = getFileForDimensionFolder(dimensionFolder); - try (CommentedFileConfig toml = CommentedFileConfig.builder(file).build()) { + try (CommentedFileConfig toml = CommentedFileConfig.builder(file).build()) + { toml.load(); - + // get the player block pos if it is specified if (toml.contains(PLAYER_BLOCK_POS_X_PATH) && toml.contains(PLAYER_BLOCK_POS_Y_PATH) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/BatchGenerator.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/BatchGenerator.java index b63d3a012..85e263254 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/BatchGenerator.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/BatchGenerator.java @@ -47,11 +47,11 @@ public class BatchGenerator implements IDhApiWorldGenerator private static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class); private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - /** + /** * Defines how many tasks can be queued per thread.

- * - * TODO the multiplier here should change dynamically based on how fast the generator is vs the queuing thread, - * if this is too high it may cause issues when moving, + * + * TODO the multiplier here should change dynamically based on how fast the generator is vs the queuing thread, + * if this is too high it may cause issues when moving, * but if it is too low the generator threads won't have enough tasks to work on */ private static final int MAX_QUEUED_TASKS = 3; @@ -137,11 +137,13 @@ public class BatchGenerator implements IDhApiWorldGenerator int genChunkSize = BitShiftUtil.powerOfTwo(granularity - 4); // minus 4 is equal to dividing by 16 to convert to chunk scale // the consumer needs to be wrapped like this because the API can't use DH core objects (and IChunkWrapper can't be easily put into the API project) - Consumer consumerWrapper = (chunkWrapper) -> resultConsumer.accept(new Object[]{ chunkWrapper }); - try { + Consumer consumerWrapper = (chunkWrapper) -> resultConsumer.accept(new Object[]{chunkWrapper}); + try + { return this.generationEnvironment.generateChunks(chunkPosMinX, chunkPosMinZ, genChunkSize, targetStep, worldGeneratorThreadPool, consumerWrapper); } - catch (Exception e) { + catch (Exception e) + { if (!LodUtil.isInterruptOrReject(e)) LOGGER.error("Error starting future for chunk generation", e); CompletableFuture future = new CompletableFuture<>(); future.completeExceptionally(e); @@ -155,7 +157,7 @@ public class BatchGenerator implements IDhApiWorldGenerator @Override public boolean isBusy() { - return this.generationEnvironment.getEventCount() > Math.max(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads.get().intValue(), 1) * MAX_QUEUED_TASKS; + return this.generationEnvironment.getEventCount() > Math.max(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads.get().intValue(), 1) * MAX_QUEUED_TASKS; } @@ -167,7 +169,7 @@ public class BatchGenerator implements IDhApiWorldGenerator @Override public void close() { - LOGGER.info(BatchGenerator.class.getSimpleName()+" shutting down..."); + LOGGER.info(BatchGenerator.class.getSimpleName() + " shutting down..."); this.generationEnvironment.stop(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java index 42ba358e4..badb0ff95 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java @@ -23,7 +23,7 @@ public class DhLightingEngine public static final DhLightingEngine INSTANCE = new DhLightingEngine(); - private DhLightingEngine() { } + private DhLightingEngine() { } @@ -31,7 +31,7 @@ public class DhLightingEngine * Note: depending on the implementation of {@link IChunkWrapper#setDhBlockLight(int, int, int, int)} and {@link IChunkWrapper#setDhSkyLight(int, int, int, int)} * the light values may be stored in the wrapper itself instead of the wrapped chunk object. * If that is the case unwrapping the chunk will undo any work this method did. - * + * * @param centerChunk the chunk we want to apply lighting to * @param nearbyChunkList should also contain centerChunk * @param maxSkyLight should be a value between 0 and 15 @@ -56,9 +56,9 @@ public class DhLightingEngine { for (int zOffset = -1; zOffset <= 1; zOffset++) { - DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x+xOffset, centerChunkPos.z+zOffset); + DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x + xOffset, centerChunkPos.z + zOffset); requestedAdjacentPositions.add(adjacentPos); - } + } } @@ -125,7 +125,7 @@ public class DhLightingEngine // validate that at least 1 chunk was found if (chunksByChunkPos.size() == 0) { - LOGGER.warn("Attempted to generate lighting for position ["+centerChunkPos+"], but neither that chunk nor any adjacent chunks were found. No chunk lighting was performed."); + LOGGER.warn("Attempted to generate lighting for position [" + centerChunkPos + "], but neither that chunk nor any adjacent chunks were found. No chunk lighting was performed."); return; } @@ -142,7 +142,7 @@ public class DhLightingEngine (neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue)); - LOGGER.trace("Finished generating lighting for chunk: ["+centerChunkPos+"]"); + LOGGER.trace("Finished generating lighting for chunk: [" + centerChunkPos + "]"); } /** Applies each {@link LightPos} from the queue to the given set of {@link IChunkWrapper}'s. */ @@ -221,9 +221,18 @@ public class DhLightingEngine //================// @FunctionalInterface - interface IGetLightFunc { int getLight(IChunkWrapper chunk, DhBlockPos pos); } + interface IGetLightFunc + { + int getLight(IChunkWrapper chunk, DhBlockPos pos); + + } + @FunctionalInterface - interface ISetLightFunc { void setLight(IChunkWrapper chunk, DhBlockPos pos, int lightValue); } + interface ISetLightFunc + { + void setLight(IChunkWrapper chunk, DhBlockPos pos, int lightValue); + + } private static class LightPos { @@ -235,6 +244,7 @@ public class DhLightingEngine this.pos = pos; this.lightValue = lightValue; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java index 228990d6c..bacf45bcb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java @@ -87,7 +87,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable this.minGranularity = generator.getMinGenerationGranularity(); this.largestDataDetail = generator.getLargestDataDetailLevel(); this.smallestDataDetail = generator.getSmallestDataDetailLevel(); - + //FIXME: Currently resizing view dist doesn't update this, causing some gen task to fail. int treeWidth = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH * 2; // TODO the *2 is to allow for generation edge cases, and should probably be removed at some point byte treeMinDetailLevel = LodUtil.CHUNK_DETAIL_LEVEL; // The min level should be at least fill in 1 ChunkSizedFullDataAccessor. @@ -131,13 +131,13 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable { requiredDataDetail = this.largestDataDetail; } - + // Assert that the data at least can fill in 1 single ChunkSizedFullDataAccessor LodUtil.assertTrue(pos.detailLevel > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL); - + DhSectionPos requestPos = new DhSectionPos(pos.detailLevel, pos.x, pos.z); - - + + //if (this.waitingTaskQuadTree.isSectionPosInBounds(requestPos)) { CompletableFuture future = new CompletableFuture<>(); @@ -147,7 +147,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } //else //{ - //return CompletableFuture.completedFuture(WorldGenResult.CreateFail()); + //return CompletableFuture.completedFuture(WorldGenResult.CreateFail()); //} } @@ -210,8 +210,8 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable int debugPointOne = 0; } } - - + + // LOGGER.info("after task count: " + this.numberOfTasksQueued); // if there aren't any new tasks, wait a second before checking again // TODO replace with a listener instead @@ -224,12 +224,12 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } catch (Exception e) { - LOGGER.error("queueing exception: "+e.getMessage(), e); + LOGGER.error("queueing exception: " + e.getMessage(), e); this.generationQueueStarted = false; } }); } - + // /** Removes all {@link WorldGenTask}'s and {@link WorldGenTaskGroup}'s that have been garbage collected. */ // private void removeGarbageCollectedTasks() // TODO remove, potential mystery errors caused by garbage collection isn't worth it (and may not be necessary any more now that we are using a quad tree to hold the tasks). // also this is very slow with the curent quad tree impelmentation // { @@ -249,20 +249,23 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable // } // } // } - + private final Set CheckingTasks = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - private static class Mapper { + + private static class Mapper + { public final WorldGenTask task; public final int dist; - public Mapper(WorldGenTask task, int dist) { + public Mapper(WorldGenTask task, int dist) + { this.task = task; this.dist = dist; } + } - - /** - * @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 */ private boolean startNextWorldGenTask(DhBlockPos2D targetPos) @@ -301,22 +304,24 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } } }*/ - + waitingTasks.forEach((pos, task) -> { - if (!task.StillValid()) { + if (!task.StillValid()) + { waitingTasks.remove(pos); task.future.complete(WorldGenResult.CreateFail()); } }); - - if (waitingTasks.size() == 0) { + + if (waitingTasks.size() == 0) + { return false; } - + Mapper closestTaskMap = waitingTasks.reduceEntries(1024, v -> new Mapper(v.getValue(), v.getValue().pos.getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())), (a, b) -> a.dist < b.dist ? a : b); - + closestTask = closestTaskMap.task; // remove the task we found, we are going to start it and don't want to run it multiple times @@ -324,7 +329,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable waitingTasks.remove(closestTask.pos, closestTask); // do we need to modify this task to generate it? - if(this.canGeneratePos((byte) 0, closestTask.pos)) // TODO should detail level 0 be replaced? + if (this.canGeneratePos((byte) 0, closestTask.pos)) // TODO should detail level 0 be replaced? { // detail level is correct for generation, start generation @@ -336,7 +341,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable if (previousInProgressTask == null) { // no task exists for this position, start one - this.startWorldGenTaskGroup(newInProgressTask); + this.startWorldGenTaskGroup(newInProgressTask); } else { @@ -344,7 +349,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable // Note: Due to concurrency reasons, even if the currently running task is compatible with // the newly selected task, we cannot use it, // as some chunks may have already been written into. - + LOGGER.warn("A task already exists for this position, todo: {}", closestTask.pos); } @@ -372,13 +377,13 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable //boolean valueAdded = this.waitingTaskQuadTree.getValue(new DhSectionPos(childDhSectionPos.sectionDetailLevel, childDhSectionPos.sectionX, childDhSectionPos.sectionZ)) != null; //LodUtil.assertTrue(valueAdded); // failed to add world gen task to quad tree, this means the quad tree was the wrong size - + // LOGGER.info("split feature "+sectionPos+" into "+childDhSectionPos+" "+(valueAdded ? "added" : "notAdded")); }); // send the child futures to the future recipient, to notify them of the new tasks closestTask.future.complete(WorldGenResult.CreateSplit(childFutures)); - + // return true so we attempt to generate again return true; } @@ -398,9 +403,9 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable { // temporary solution to prevent generating the same section multiple times LOGGER.warn("Duplicate generation section " + taskPos + " with granularity [" + granularity + "] at " + chunkPosMin + ". Skipping..."); - + //StackTraceElement[] stackTrace = this.alreadyGeneratedPosHashSet.get(inProgressTaskGroup.group.pos); - + // sending a success result is necessary to make sure the render sections are reloaded correctly inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos)))); return; @@ -428,7 +433,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable // don't log the shutdown exceptions if (!LodUtil.isInterruptOrReject(exception)) { - LOGGER.error("Error generating data for section "+taskPos, exception); + LOGGER.error("Error generating data for section " + taskPos, exception); } inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateFail())); @@ -444,24 +449,24 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } /** * The chunkPos is always aligned to the granularity. - * For example: if the granularity is 4 (chunk sized) with a data detail level of 0 (block sized), + * For example: if the granularity is 4 (chunk sized) with a data detail level of 0 (block sized), * the chunkPos will be aligned to 16x16 blocks.

- * - * + * + * * Full Granularity definition (as of 2023-6-21):

- * + * * world gen actually supports (in theory) generating stuff with a data detail that's higher than the per-block.

* * Granularity basically means, on a single generation task, how big such group should be, in terms of the data points it will make.

* - * For example, a granularity of 4 means the task will generate a 16 by 16 data points. + * For example, a granularity of 4 means the task will generate a 16 by 16 data points. * Now, those data points might be per block, or per 4 by 4 blocks. Granularity doesn't say what detail those would be.

* - * Note: currently the core system sends data via the chunk sized container, + * Note: currently the core system sends data via the chunk sized container, * which has the locked granularity of 4 (16 by 16 data columns), and thus generators should at least have min granularity of 4. - * (Gen chunk width in that context means how many 'chunk sized containers' it will fill up. - * Again, note that a 'chunk sized container' isn't necessary 16 by 16 Minecraft blocks wide. - * It only has to contain 16 by 16 columns of data points, in whatever data detail it might be in.) + * (Gen chunk width in that context means how many 'chunk sized containers' it will fill up. + * Again, note that a 'chunk sized container' isn't necessary 16 by 16 Minecraft blocks wide. + * It only has to contain 16 by 16 columns of data points, in whatever data detail it might be in.) * (So, with a generator whose only gen data detail is 0, it is the same as a MC chunk.) */ private CompletableFuture startGenerationEvent( @@ -479,7 +484,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } catch (ClassCastException e) { - DhLoggerBuilder.getLogger().error("World generator return type incorrect. Error: ["+e.getMessage()+"]. World generator disabled.", e); + DhLoggerBuilder.getLogger().error("World generator return type incorrect. Error: [" + e.getMessage() + "]. World generator disabled.", e); Config.Client.Advanced.WorldGenerator.enableDistantGeneration.set(false); } }); @@ -506,11 +511,11 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable if (worldGeneratorThreadPool == null || worldGeneratorThreadPool.isTerminated()) { - LOGGER.info("Starting "+ FullDataFileHandler.class.getSimpleName()); + LOGGER.info("Starting " + FullDataFileHandler.class.getSimpleName()); setThreadPoolSize(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads.get()); } } - public static void setThreadPoolSize(int threadPoolSize) + public static void setThreadPoolSize(int threadPoolSize) { if (worldGeneratorThreadPool != null) { @@ -518,7 +523,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable worldGeneratorThreadPool.shutdown(); } - worldGeneratorThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, "DH-Gen-Worker-Thread", Thread.MIN_PRIORITY, Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads); + worldGeneratorThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, "DH-Gen-Worker-Thread", Thread.MIN_PRIORITY, Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads); } /** @@ -529,7 +534,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable { if (worldGeneratorThreadPool != null) { - LOGGER.info("Stopping "+ FullDataFileHandler.class.getSimpleName()); + LOGGER.info("Stopping " + FullDataFileHandler.class.getSimpleName()); worldGeneratorThreadPool.shutdownNow(); } } @@ -549,35 +554,35 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable // stop and remove any in progress tasks ArrayList> inProgressTasksCancelingFutures = new ArrayList<>(this.inProgressGenTasksByLodPos.size()); this.inProgressGenTasksByLodPos.values().forEach(runningTaskGroup -> + { + CompletableFuture genFuture = runningTaskGroup.genFuture; // Do this to prevent it getting swapped out + if (genFuture == null) { - CompletableFuture genFuture = runningTaskGroup.genFuture; // Do this to prevent it getting swapped out - if (genFuture == null) + // genFuture's shouldn't be null, but sometimes they are... + return; + } + + + if (cancelCurrentGeneration) + { + genFuture.cancel(alsoInterruptRunning); + } + + inProgressTasksCancelingFutures.add(genFuture.handle((voidObj, exception) -> + { + if (exception instanceof CompletionException) { - // genFuture's shouldn't be null, but sometimes they are... - return; + exception = exception.getCause(); } - - if (cancelCurrentGeneration) + if (!UncheckedInterruptedException.isInterrupt(exception) && !(exception instanceof CancellationException)) { - genFuture.cancel(alsoInterruptRunning); + LOGGER.error("Error when terminating data generation for section " + runningTaskGroup.group.pos, exception); } - inProgressTasksCancelingFutures.add(genFuture.handle((voidObj, exception) -> - { - if (exception instanceof CompletionException) - { - exception = exception.getCause(); - } - - if (!UncheckedInterruptedException.isInterrupt(exception) && !(exception instanceof CancellationException)) - { - LOGGER.error("Error when terminating data generation for section "+runningTaskGroup.group.pos, exception); - } - - return null; - })); - }); + return null; + })); + }); this.generatorClosingFuture = CompletableFuture.allOf(inProgressTasksCancelingFutures.toArray(new CompletableFuture[0])); return this.generatorClosingFuture; @@ -586,7 +591,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable @Override public void close() { - LOGGER.info("Closing "+WorldGenerationQueue.class.getSimpleName()+"..."); + LOGGER.info("Closing " + WorldGenerationQueue.class.getSimpleName() + "..."); if (this.generatorClosingFuture == null) { @@ -603,7 +608,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable int waitTimeInSeconds = 3; if (!worldGeneratorThreadPool.awaitTermination(waitTimeInSeconds, TimeUnit.SECONDS)) { - LOGGER.warn("World generator thread pool shutdown didn't complete after ["+waitTimeInSeconds+"] seconds. Some world generator requests may still be running."); + LOGGER.warn("World generator thread pool shutdown didn't complete after [" + waitTimeInSeconds + "] seconds. Some world generator requests may still be running."); } } catch (InterruptedException e) @@ -625,7 +630,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable { LOGGER.warn("Failed to close generation queue: ", e); } - LOGGER.info("Finished closing "+WorldGenerationQueue.class.getSimpleName()); + LOGGER.info("Finished closing " + WorldGenerationQueue.class.getSimpleName()); DebugRenderer.unregister(this); } @@ -635,7 +640,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable // helper methods // //================// - private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/, DhLodPos taskPos) + private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/ , DhLodPos taskPos) { byte granularity = (byte) (taskPos.detailLevel - worldGenTaskGroupDetailLevel); return (granularity >= this.minGranularity && granularity <= this.maxGranularity); @@ -665,10 +670,11 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable return index; } - - + + @Override - public void debugRender(DebugRenderer r) { + public void debugRender(DebugRenderer r) + { //if (true) return; waitingTasks.keySet().forEach((pos) -> { //DhLodPos pos = t.pos; @@ -678,4 +684,5 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable r.renderBox(new DebugRenderer.Box(pos, -32f, 64f, 0.05f, Color.red)); }); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/IWorldGenTaskTracker.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/IWorldGenTaskTracker.java index d8704cc83..c9553b312 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/IWorldGenTaskTracker.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/IWorldGenTaskTracker.java @@ -10,8 +10,9 @@ import java.util.function.Consumer; */ public interface IWorldGenTaskTracker { - /** Returns true if the task hasn't been garbage collected. */ + /** Returns true if the task hasn't been garbage collected. */ boolean isMemoryAddressValid(); Consumer getChunkDataConsumer(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java index c0f4b03b6..427bd7396 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java @@ -24,8 +24,10 @@ public final class WorldGenTask this.taskTracker = taskTracker; this.future = future; } - - public boolean StillValid() { + + public boolean StillValid() + { return taskTracker.isMemoryAddressValid(); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java index 6fff92cde..3eda6d9b7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java @@ -25,7 +25,7 @@ public final class WorldGenTaskGroup this.pos = pos; this.dataDetail = dataDetail; } - + public void consumeChunkData(ChunkSizedFullDataAccessor chunkSizedFullDataView) { Iterator tasks = this.worldGenTasks.iterator(); @@ -44,4 +44,5 @@ public final class WorldGenTaskGroup } } } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/DarkModeDetector.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/DarkModeDetector.java index 25e3eea91..bb690e039 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/DarkModeDetector.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/DarkModeDetector.java @@ -13,129 +13,156 @@ import java.util.regex.Pattern; * @author IMS * @author coolGi2007 */ -public class DarkModeDetector { - private static final String REGQUERY_UTIL = "reg query "; - private static final String REGDWORD_TOKEN = "REG_DWORD"; - private static final String DARK_THEME_CMD = REGQUERY_UTIL + "\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\"" + " /v AppsUseLightTheme"; - - public static boolean isDarkMode() { - switch (Platform.get()) { - case WINDOWS: - return isWindowsDarkMode(); - case MACOS: - return isMacOsDarkMode(); - case LINUX: - // Most Unix(-like) distros also use a lot of the same things as Linux (like desktop environments and window managers) - case BSD: - case UNIX: - return checkLinuxDark(); - default: - return false; - } - } - - // Needs checking as I dont use Mac - public static boolean isMacOsDarkMode() { - boolean isDarkMode = false; - String line = query("defaults read -g AppleInterfaceStyle"); - if (line.equals("Dark")) { - isDarkMode = true; - } - return isDarkMode; - } - - // Needs checking as I don't use Windows - public static boolean isWindowsDarkMode() { - try { - String result = query(DARK_THEME_CMD); - int p = result.indexOf(REGDWORD_TOKEN); - - if (p == -1) { - return false; - } - - // 1 == Light Mode, 0 == Dark Mode - String temp = result.substring(p + REGDWORD_TOKEN.length()).trim(); - return ((Integer.parseInt(temp.substring("0x".length()), 16))) == 0; - } catch (Exception e) { - return false; - } - } - - - // On Linux there are 2 popular formats for theming - // They are qt and gtk. We check the desktop environment and use that to pick which one to use (if none work then use GTK) - public static boolean checkLinuxDark() { - // Checks "/usr/bin" as "echo $XDG_CURRENT_DESKTOP" dosnt work in java and dosnt detect window managers - File de_location = new File("/usr/bin"); +public class DarkModeDetector +{ + private static final String REGQUERY_UTIL = "reg query "; + private static final String REGDWORD_TOKEN = "REG_DWORD"; + private static final String DARK_THEME_CMD = REGQUERY_UTIL + "\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\"" + " /v AppsUseLightTheme"; + + public static boolean isDarkMode() + { + switch (Platform.get()) + { + case WINDOWS: + return isWindowsDarkMode(); + case MACOS: + return isMacOsDarkMode(); + case LINUX: + // Most Unix(-like) distros also use a lot of the same things as Linux (like desktop environments and window managers) + case BSD: + case UNIX: + return checkLinuxDark(); + default: + return false; + } + } + + // Needs checking as I dont use Mac + public static boolean isMacOsDarkMode() + { + boolean isDarkMode = false; + String line = query("defaults read -g AppleInterfaceStyle"); + if (line.equals("Dark")) + { + isDarkMode = true; + } + return isDarkMode; + } + + // Needs checking as I don't use Windows + public static boolean isWindowsDarkMode() + { + try + { + String result = query(DARK_THEME_CMD); + int p = result.indexOf(REGDWORD_TOKEN); + + if (p == -1) + { + return false; + } + + // 1 == Light Mode, 0 == Dark Mode + String temp = result.substring(p + REGDWORD_TOKEN.length()).trim(); + return ((Integer.parseInt(temp.substring("0x".length()), 16))) == 0; + } + catch (Exception e) + { + return false; + } + } + + + // On Linux there are 2 popular formats for theming + // They are qt and gtk. We check the desktop environment and use that to pick which one to use (if none work then use GTK) + public static boolean checkLinuxDark() + { + // Checks "/usr/bin" as "echo $XDG_CURRENT_DESKTOP" dosnt work in java and dosnt detect window managers + File de_location = new File("/usr/bin"); // System.out.println(de_location.list()); - for (String de : de_location.list()) { + for (String de : de_location.list()) + { // System.out.println(de); - if (de.contains("gnome-session")) // Gnome uses GTK - return GTKChecker(); - if (de.contains("plasma_session")) // KDE plasma uses QT - return QTChecker(); - } - return GTKChecker(); // GTK works best with non plasma desktops (desktops includes window managers) - } - - public static boolean GTKChecker() { - // Checks if the return to "gsettings get org.gnome.desktop.interface color-scheme" in terminal is 'prefer-dark' or contains the word dark in it - final Pattern darkThemeNamePattern = Pattern.compile(".*dark.*", Pattern.CASE_INSENSITIVE); - return darkThemeNamePattern.matcher(query("gsettings get org.gnome.desktop.interface color-scheme")).matches(); - } - - public static boolean QTChecker() { - // Get the contents of "~/.config/Trolltech.conf" then check "KWinPalette\activeBackground" - // With that you grayscale the rgb and check if it is over/under 128 - - // If there is a better way of doing this then please let me know - // This seems like the best way as qt dosnt have a dark/light preference and just stores pure color values - - try { - File themeFile = new File(System.getProperty("user.home") + "/.config/Trolltech.conf"); - - BufferedReader reader = new BufferedReader(new FileReader(themeFile)); - String themeLine = reader.readLine(); - while (themeLine != null) { // Go through each line till you find "KWinPalette\activeBackground" - if (themeLine.contains("KWinPalette\\activeBackground")) - break; - themeLine = reader.readLine(); - } - reader.close(); - - // Get where the # is then read the hex numbers after it - short index = (short) themeLine.indexOf("#"); - short r = (short) Integer.parseInt(""+themeLine.charAt(index+1)+themeLine.charAt(index+2), 16); - short g = (short) Integer.parseInt(""+themeLine.charAt(index+3)+themeLine.charAt(index+4), 16); - short b = (short) Integer.parseInt(""+themeLine.charAt(index+5)+themeLine.charAt(index+6), 16); - if ((r+g+b)/2 >= 128) - return false; - else - return true; - } catch (Exception e) { e.printStackTrace(); return false;} - } - - - - /** Runs a command trough command line */ - private static String query(String cmd) { - try { - Process process = Runtime.getRuntime().exec(cmd); - StringBuilder stringBuilder = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String actualReadLine; - while ((actualReadLine = reader.readLine()) != null) { - if (stringBuilder.length() != 0) - stringBuilder.append('\n'); - stringBuilder.append(actualReadLine); - } - } - return stringBuilder.toString(); - } catch (IOException e) { - System.out.println("Exception caught while querying the OS:"); - e.printStackTrace(); - return ""; - } - } + if (de.contains("gnome-session")) // Gnome uses GTK + return GTKChecker(); + if (de.contains("plasma_session")) // KDE plasma uses QT + return QTChecker(); + } + return GTKChecker(); // GTK works best with non plasma desktops (desktops includes window managers) + } + + public static boolean GTKChecker() + { + // Checks if the return to "gsettings get org.gnome.desktop.interface color-scheme" in terminal is 'prefer-dark' or contains the word dark in it + final Pattern darkThemeNamePattern = Pattern.compile(".*dark.*", Pattern.CASE_INSENSITIVE); + return darkThemeNamePattern.matcher(query("gsettings get org.gnome.desktop.interface color-scheme")).matches(); + } + + public static boolean QTChecker() + { + // Get the contents of "~/.config/Trolltech.conf" then check "KWinPalette\activeBackground" + // With that you grayscale the rgb and check if it is over/under 128 + + // If there is a better way of doing this then please let me know + // This seems like the best way as qt dosnt have a dark/light preference and just stores pure color values + + try + { + File themeFile = new File(System.getProperty("user.home") + "/.config/Trolltech.conf"); + + BufferedReader reader = new BufferedReader(new FileReader(themeFile)); + String themeLine = reader.readLine(); + while (themeLine != null) + { // Go through each line till you find "KWinPalette\activeBackground" + if (themeLine.contains("KWinPalette\\activeBackground")) + break; + themeLine = reader.readLine(); + } + reader.close(); + + // Get where the # is then read the hex numbers after it + short index = (short) themeLine.indexOf("#"); + short r = (short) Integer.parseInt("" + themeLine.charAt(index + 1) + themeLine.charAt(index + 2), 16); + short g = (short) Integer.parseInt("" + themeLine.charAt(index + 3) + themeLine.charAt(index + 4), 16); + short b = (short) Integer.parseInt("" + themeLine.charAt(index + 5) + themeLine.charAt(index + 6), 16); + if ((r + g + b) / 2 >= 128) + return false; + else + return true; + } + catch (Exception e) + { + e.printStackTrace(); return false; + } + } + + + + /** Runs a command trough command line */ + private static String query(String cmd) + { + try + { + Process process = Runtime.getRuntime().exec(cmd); + StringBuilder stringBuilder = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) + { + String actualReadLine; + while ((actualReadLine = reader.readLine()) != null) + { + if (stringBuilder.length() != 0) + stringBuilder.append('\n'); + stringBuilder.append(actualReadLine); + } + } + return stringBuilder.toString(); + } + catch (IOException e) + { + System.out.println("Exception caught while querying the OS:"); + e.printStackTrace(); + return ""; + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarDependencySetup.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarDependencySetup.java index fc4172b98..eb7afa46f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarDependencySetup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarDependencySetup.java @@ -4,9 +4,12 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.jar.wrapperInterfaces.config.LangWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; -public class JarDependencySetup { - public static void createInitialBindings() { - SingletonInjector.INSTANCE.bind(ILangWrapper.class, LangWrapper.INSTANCE); - LangWrapper.init(); - } +public class JarDependencySetup +{ + public static void createInitialBindings() + { + SingletonInjector.INSTANCE.bind(ILangWrapper.class, LangWrapper.INSTANCE); + LangWrapper.init(); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java index f96ac1147..be95d2c29 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java @@ -23,253 +23,274 @@ import java.util.concurrent.atomic.AtomicReference; * @author coolGi */ // Once built it would be in core/build/libs/DistantHorizons--dev-all.jar -public class JarMain { - public static final Logger logger = LogManager.getLogger(JarMain.class.getSimpleName()); - public static List programArgs; - public static final boolean isDarkTheme = DarkModeDetector.isDarkMode(); - public static boolean isOffline = WebDownloader.netIsAvailable(); - - // TODO: Rewrite the standalone jar - // Previous version here https://gitlab.com/jeseibel/distant-horizons-core/-/blob/333dc4d0e079777b712c0fff246837104ae9a2b6/core/src/main/java/com/seibel/lod/core/jar/JarMain.java - - - public static void main(String[] args) { - programArgs = Arrays.asList(args); - - if (!programArgs.contains("--no-custom-logger")) { - LoggerContext context = (LoggerContext) LogManager.getContext(false); - try { - context.setConfigLocation(JarUtils.accessFileURI("/log4jConfig.xml")); - } catch (Exception e) { - logger.error("Failed to set log4j config. Try running with the \"--no-custom-logger\" argument"); - e.printStackTrace(); - } - } - - logger.debug("Running "+ModInfo.READABLE_NAME+" standalone jar"); - logger.warn("The standalone jar is still a massive WIP, expect bugs"); - logger.debug("Java version "+System.getProperty("java.version")); +public class JarMain +{ + public static final Logger logger = LogManager.getLogger(JarMain.class.getSimpleName()); + public static List programArgs; + public static final boolean isDarkTheme = DarkModeDetector.isDarkMode(); + public static boolean isOffline = WebDownloader.netIsAvailable(); + + // TODO: Rewrite the standalone jar + // Previous version here https://gitlab.com/jeseibel/distant-horizons-core/-/blob/333dc4d0e079777b712c0fff246837104ae9a2b6/core/src/main/java/com/seibel/lod/core/jar/JarMain.java + + + public static void main(String[] args) + { + programArgs = Arrays.asList(args); + + if (!programArgs.contains("--no-custom-logger")) + { + LoggerContext context = (LoggerContext) LogManager.getContext(false); + try + { + context.setConfigLocation(JarUtils.accessFileURI("/log4jConfig.xml")); + } + catch (Exception e) + { + logger.error("Failed to set log4j config. Try running with the \"--no-custom-logger\" argument"); + e.printStackTrace(); + } + } + + logger.debug("Running " + ModInfo.READABLE_NAME + " standalone jar"); + logger.warn("The standalone jar is still a massive WIP, expect bugs"); + logger.debug("Java version " + System.getProperty("java.version")); // logger.debug(programArgs); - - // Sets up the local - if (JarUtils.accessFile("assets/lod/lang/" + Locale.getDefault().toString().toLowerCase() + ".json") == null) { - logger.warn("The language setting [" + Locale.getDefault().toString().toLowerCase() + "] isn't allowed yet. Defaulting to [" + Locale.US.toString().toLowerCase() + "]."); - Locale.setDefault(Locale.US); - } - JarDependencySetup.createInitialBindings(); - - if (args.length == 0 || Arrays.asList(args).contains("--gui")) { - startGUI(); - return; - } - } - - - - public static void startGUI() { - // Set up the theme + + // Sets up the local + if (JarUtils.accessFile("assets/lod/lang/" + Locale.getDefault().toString().toLowerCase() + ".json") == null) + { + logger.warn("The language setting [" + Locale.getDefault().toString().toLowerCase() + "] isn't allowed yet. Defaulting to [" + Locale.US.toString().toLowerCase() + "]."); + Locale.setDefault(Locale.US); + } + JarDependencySetup.createInitialBindings(); + + if (args.length == 0 || Arrays.asList(args).contains("--gui")) + { + startGUI(); + return; + } + } + + + + public static void startGUI() + { + // Set up the theme // System.setProperty("apple.awt.application.appearance", "system"); // if (isDarkTheme) // FlatDarkLaf.setup(); // else // FlatLightLaf.setup(); - // This is done in BaseJFrame now + // This is done in BaseJFrame now // GitlabGetter.init(); - ModrinthGetter.init(); - System.out.println("WARNING: The standalone jar still work in progress"); + ModrinthGetter.init(); + System.out.println("WARNING: The standalone jar still work in progress"); // JOptionPane.showMessageDialog(null, "The GUI for the standalone jar isn't made yet\nIf you want to use the mod then put it in your mods folder", "Distant Horizons", JOptionPane.WARNING_MESSAGE); // if (getOperatingSystem().equals(OperatingSystem.MACOS)) { // System.out.println("If you want the installer then please use Linux or Windows for the time being.\nMacOS support/testing will come later on"); // } - - // Code will be changed later on to allow resizing and work better - - - - BaseJFrame frame = new BaseJFrame(false, true); - frame.addExtraButtons(frame.getWidth(), 0, true, false); - - // Buttons which you want to be stacked vertically should be added with this (`frame.add(obj, this);`) - GridBagConstraints verticalLayout = new GridBagConstraints(); - verticalLayout.gridy = GridBagConstraints.RELATIVE; - verticalLayout.gridx = 0; - verticalLayout.fill = GridBagConstraints.HORIZONTAL; - verticalLayout.weightx = 1.0; - verticalLayout.anchor = GridBagConstraints.NORTH; - - - // Selected download - AtomicReference downloadID = new AtomicReference(""); - - - // This is for the panel to show the update description - JPanel modVersionDescriptionPanel = new JPanel(new GridBagLayout()); - JScrollPane modVersionDescriptionScroll = new JScrollPane(modVersionDescriptionPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - // Sets all the layout stuff for it - int modDescriptionWidth = 275; - modVersionDescriptionScroll.setBounds(frame.getWidth()-modDescriptionWidth, 225, modDescriptionWidth, frame.getHeight()-255); - modVersionDescriptionScroll.setBorder(null); // Disables the border - modVersionDescriptionScroll.setWheelScrollingEnabled(true); - // The label - JLabel modVersionDescriptionLabel = new JLabel(); - modVersionDescriptionPanel.add(modVersionDescriptionLabel, verticalLayout); - // Finally add it - frame.add(modVersionDescriptionScroll); - - - - // This is for the pannel to select MinecraftVersion - JPanel modMinecraftVersionsPannel = new JPanel(new GridBagLayout()); - JScrollPane modMinecraftVersionsScroll = new JScrollPane(modMinecraftVersionsPannel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - // Sets all the layout stuff for it - modMinecraftVersionsScroll.setBounds(0, 225, 125, frame.getHeight()-255); - modMinecraftVersionsScroll.setBorder(null); // Disables the border - modMinecraftVersionsScroll.setWheelScrollingEnabled(true); - // List to store all the buttons - ArrayList modMinecraftReleaseButtons = new ArrayList<>(); - frame.add(modMinecraftVersionsScroll); - - - // This is for selecting the mod version - JPanel modVersionsPannel = new JPanel(new GridBagLayout()); - JScrollPane modVersionsScroll = new JScrollPane(modVersionsPannel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - // Sets all the layout stuff for it - modVersionsScroll.setBounds(125, 225, 100, frame.getHeight()-255); - modVersionsScroll.setBorder(null); // Disables the border - modVersionsScroll.setWheelScrollingEnabled(true); - // List to store all the buttons - ArrayList modReleaseButtons = new ArrayList<>(); - frame.add(modVersionsScroll); - - // Add all the buttons - for (String mcVer : ModrinthGetter.mcVersions) { - JButton btn = new JButton(mcVer); - btn.setBackground(UIManager.getColor("Panel.background")); // Does the same thing as removing the background - btn.setBorderPainted(false); // Removes the borders + + // Code will be changed later on to allow resizing and work better + + + + BaseJFrame frame = new BaseJFrame(false, true); + frame.addExtraButtons(frame.getWidth(), 0, true, false); + + // Buttons which you want to be stacked vertically should be added with this (`frame.add(obj, this);`) + GridBagConstraints verticalLayout = new GridBagConstraints(); + verticalLayout.gridy = GridBagConstraints.RELATIVE; + verticalLayout.gridx = 0; + verticalLayout.fill = GridBagConstraints.HORIZONTAL; + verticalLayout.weightx = 1.0; + verticalLayout.anchor = GridBagConstraints.NORTH; + + + // Selected download + AtomicReference downloadID = new AtomicReference(""); + + + // This is for the panel to show the update description + JPanel modVersionDescriptionPanel = new JPanel(new GridBagLayout()); + JScrollPane modVersionDescriptionScroll = new JScrollPane(modVersionDescriptionPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + // Sets all the layout stuff for it + int modDescriptionWidth = 275; + modVersionDescriptionScroll.setBounds(frame.getWidth() - modDescriptionWidth, 225, modDescriptionWidth, frame.getHeight() - 255); + modVersionDescriptionScroll.setBorder(null); // Disables the border + modVersionDescriptionScroll.setWheelScrollingEnabled(true); + // The label + JLabel modVersionDescriptionLabel = new JLabel(); + modVersionDescriptionPanel.add(modVersionDescriptionLabel, verticalLayout); + // Finally add it + frame.add(modVersionDescriptionScroll); + + + + // This is for the pannel to select MinecraftVersion + JPanel modMinecraftVersionsPannel = new JPanel(new GridBagLayout()); + JScrollPane modMinecraftVersionsScroll = new JScrollPane(modMinecraftVersionsPannel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + // Sets all the layout stuff for it + modMinecraftVersionsScroll.setBounds(0, 225, 125, frame.getHeight() - 255); + modMinecraftVersionsScroll.setBorder(null); // Disables the border + modMinecraftVersionsScroll.setWheelScrollingEnabled(true); + // List to store all the buttons + ArrayList modMinecraftReleaseButtons = new ArrayList<>(); + frame.add(modMinecraftVersionsScroll); + + + // This is for selecting the mod version + JPanel modVersionsPannel = new JPanel(new GridBagLayout()); + JScrollPane modVersionsScroll = new JScrollPane(modVersionsPannel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + // Sets all the layout stuff for it + modVersionsScroll.setBounds(125, 225, 100, frame.getHeight() - 255); + modVersionsScroll.setBorder(null); // Disables the border + modVersionsScroll.setWheelScrollingEnabled(true); + // List to store all the buttons + ArrayList modReleaseButtons = new ArrayList<>(); + frame.add(modVersionsScroll); + + // Add all the buttons + for (String mcVer : ModrinthGetter.mcVersions) + { + JButton btn = new JButton(mcVer); + btn.setBackground(UIManager.getColor("Panel.background")); // Does the same thing as removing the background + btn.setBorderPainted(false); // Removes the borders // btn.setHorizontalAlignment(SwingConstants.LEFT); // Sets the text to be on the left side rather than the center - - btn.addActionListener(e -> { - // Clears the selected colors for the rest of the buttons - for (JButton currentBtn : modMinecraftReleaseButtons) - currentBtn.setBackground(UIManager.getColor("Panel.background")); - btn.setBackground(UIManager.getColor("Button.background")); // Sets this to the selected color - - // Clears the minecraft version panel - modVersionsPannel.removeAll(); - modReleaseButtons.clear(); - - - // Adds all the buttons for the minecraft panel - for (String modID : ModrinthGetter.mcVerToReleaseID.get(mcVer)) { - // No need to comment most of these as it is the same this as before - JButton btnDownload = new JButton(ModrinthGetter.releaseNames.get(modID)); - btnDownload.setBackground(UIManager.getColor("Panel.background")); - btnDownload.setBorderPainted(false); - btnDownload.setHorizontalAlignment(SwingConstants.LEFT); - - btnDownload.addActionListener(f -> { - downloadID.set(modID); - - for (JButton currentBtn : modReleaseButtons) - currentBtn.setBackground(UIManager.getColor("Panel.background")); - btnDownload.setBackground(UIManager.getColor("Button.background")); - - - modVersionDescriptionLabel.setText( - WebDownloader.formatMarkdownToHtml( - ModrinthGetter.changeLogs.get(modID), modDescriptionWidth-75) - ); - modVersionDescriptionPanel.repaint(); - }); - modVersionsPannel.add(btnDownload, verticalLayout); - modReleaseButtons.add(btnDownload); - } - - modVersionsScroll.getVerticalScrollBar().setValue(0); // Reset the scroll bar back to the top - - modVersionsPannel.repaint(); // Update the version pannel - frame.validate(); // Update the frame - }); - - modMinecraftVersionsPannel.add(btn, verticalLayout); - modMinecraftReleaseButtons.add(btn); - } - - - - // Bar at the top - frame.add(new JBox(UIManager.getColor("Separator.foreground"), 0, 220, frame.getWidth(), 5)); - // Minecraft version text - JLabel textMcVersionHeader = new JLabel("Minecraft version"); - textMcVersionHeader.setBounds(0, 200, 125, 20); - frame.add(textMcVersionHeader); - // Version text - JLabel textVersionHeader = new JLabel("Mod version"); - textVersionHeader.setBounds(125, 200, 150, 20); - frame.add(textVersionHeader); - - - - - // Stuff for setting the file install path - JFileChooser minecraftDirPop = new JFileChooser(); - switch (Platform.get()) { - case WINDOWS: - minecraftDirPop.setCurrentDirectory(new File(System.getenv("APPDATA") + "/.minecraft/mods")); - case LINUX: - minecraftDirPop.setCurrentDirectory(new File(System.getProperty("user.home") + "/.minecraft/mods")); - } - minecraftDirPop.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - JButton minecraftDirBtn = new JButton("Click to select install path"); - minecraftDirBtn.addActionListener(e -> { - if (minecraftDirPop.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) - minecraftDirBtn.setText(minecraftDirPop.getSelectedFile().toString()); - }); - minecraftDirBtn.setBounds(230, frame.getHeight()-100, 200, 20); - frame.add(minecraftDirBtn); - - // Button for the install button - JButton installMod = new JButton("Install " + ModInfo.READABLE_NAME); - installMod.setBounds(230, frame.getHeight()-70, 200, 20); - installMod.addActionListener(e -> { - if (minecraftDirPop.getSelectedFile() == null) { - JOptionPane.showMessageDialog(frame, "Please select your install directory", ModInfo.READABLE_NAME, JOptionPane.WARNING_MESSAGE); - return; - } - - URL downloadPath = ModrinthGetter.downloadUrl.get(downloadID.get()); - - try { - WebDownloader.downloadAsFile( - downloadPath, - minecraftDirPop.getSelectedFile().toPath().resolve( - ModInfo.NAME + "-" + ModrinthGetter.releaseNames.get(downloadID.get()) + ".jar" - ).toFile()); - - JOptionPane.showMessageDialog(frame, "Installation done. \nYou can now close the installer", ModInfo.READABLE_NAME, JOptionPane.INFORMATION_MESSAGE); - } catch (Exception f) { - JOptionPane.showMessageDialog(frame, "Download failed. Check your internet connection \nStacktrace: " + f.getMessage(), ModInfo.READABLE_NAME, JOptionPane.ERROR_MESSAGE); - } - }); - frame.add(installMod); - - - // Fabric installer + + btn.addActionListener(e -> { + // Clears the selected colors for the rest of the buttons + for (JButton currentBtn : modMinecraftReleaseButtons) + { + currentBtn.setBackground(UIManager.getColor("Panel.background")); + } + btn.setBackground(UIManager.getColor("Button.background")); // Sets this to the selected color + + // Clears the minecraft version panel + modVersionsPannel.removeAll(); + modReleaseButtons.clear(); + + + // Adds all the buttons for the minecraft panel + for (String modID : ModrinthGetter.mcVerToReleaseID.get(mcVer)) + { + // No need to comment most of these as it is the same this as before + JButton btnDownload = new JButton(ModrinthGetter.releaseNames.get(modID)); + btnDownload.setBackground(UIManager.getColor("Panel.background")); + btnDownload.setBorderPainted(false); + btnDownload.setHorizontalAlignment(SwingConstants.LEFT); + + btnDownload.addActionListener(f -> { + downloadID.set(modID); + + for (JButton currentBtn : modReleaseButtons) + { + currentBtn.setBackground(UIManager.getColor("Panel.background")); + } + btnDownload.setBackground(UIManager.getColor("Button.background")); + + + modVersionDescriptionLabel.setText( + WebDownloader.formatMarkdownToHtml( + ModrinthGetter.changeLogs.get(modID), modDescriptionWidth - 75) + ); + modVersionDescriptionPanel.repaint(); + }); + modVersionsPannel.add(btnDownload, verticalLayout); + modReleaseButtons.add(btnDownload); + } + + modVersionsScroll.getVerticalScrollBar().setValue(0); // Reset the scroll bar back to the top + + modVersionsPannel.repaint(); // Update the version pannel + frame.validate(); // Update the frame + }); + + modMinecraftVersionsPannel.add(btn, verticalLayout); + modMinecraftReleaseButtons.add(btn); + } + + + + // Bar at the top + frame.add(new JBox(UIManager.getColor("Separator.foreground"), 0, 220, frame.getWidth(), 5)); + // Minecraft version text + JLabel textMcVersionHeader = new JLabel("Minecraft version"); + textMcVersionHeader.setBounds(0, 200, 125, 20); + frame.add(textMcVersionHeader); + // Version text + JLabel textVersionHeader = new JLabel("Mod version"); + textVersionHeader.setBounds(125, 200, 150, 20); + frame.add(textVersionHeader); + + + + + // Stuff for setting the file install path + JFileChooser minecraftDirPop = new JFileChooser(); + switch (Platform.get()) + { + case WINDOWS: + minecraftDirPop.setCurrentDirectory(new File(System.getenv("APPDATA") + "/.minecraft/mods")); + case LINUX: + minecraftDirPop.setCurrentDirectory(new File(System.getProperty("user.home") + "/.minecraft/mods")); + } + minecraftDirPop.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + JButton minecraftDirBtn = new JButton("Click to select install path"); + minecraftDirBtn.addActionListener(e -> { + if (minecraftDirPop.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) + minecraftDirBtn.setText(minecraftDirPop.getSelectedFile().toString()); + }); + minecraftDirBtn.setBounds(230, frame.getHeight() - 100, 200, 20); + frame.add(minecraftDirBtn); + + // Button for the install button + JButton installMod = new JButton("Install " + ModInfo.READABLE_NAME); + installMod.setBounds(230, frame.getHeight() - 70, 200, 20); + installMod.addActionListener(e -> { + if (minecraftDirPop.getSelectedFile() == null) + { + JOptionPane.showMessageDialog(frame, "Please select your install directory", ModInfo.READABLE_NAME, JOptionPane.WARNING_MESSAGE); + return; + } + + URL downloadPath = ModrinthGetter.downloadUrl.get(downloadID.get()); + + try + { + WebDownloader.downloadAsFile( + downloadPath, + minecraftDirPop.getSelectedFile().toPath().resolve( + ModInfo.NAME + "-" + ModrinthGetter.releaseNames.get(downloadID.get()) + ".jar" + ).toFile()); + + JOptionPane.showMessageDialog(frame, "Installation done. \nYou can now close the installer", ModInfo.READABLE_NAME, JOptionPane.INFORMATION_MESSAGE); + } + catch (Exception f) + { + JOptionPane.showMessageDialog(frame, "Download failed. Check your internet connection \nStacktrace: " + f.getMessage(), ModInfo.READABLE_NAME, JOptionPane.ERROR_MESSAGE); + } + }); + frame.add(installMod); + + + // Fabric installer // try { // WebDownloader.downloadAsFile(new URL("https://maven.fabricmc.net/net/fabricmc/fabric-installer/0.11.0/fabric-installer-0.11.0.jar"), new File(System.getProperty("java.io.tmpdir") + "/fabricInstaller.jar")); // Runtime.getRuntime().exec("java -jar " + System.getProperty("java.io.tmpdir") + "/fabricInstaller.jar"); // } catch (Exception e) {e.printStackTrace();} - - - - - frame.addLogo(); // Has to be run at the end cus of a bug with java swing (it may not be a bug but idk how to fix it so I'll call it a bug) - - frame.validate(); // Update to add the widgets - frame.setVisible(true); // Start the ui - } + + + + + frame.addLogo(); // Has to be run at the end cus of a bug with java swing (it may not be a bug but idk how to fix it so I'll call it a bug) + + frame.validate(); // Update to add the widgets + frame.setVisible(true); // Start the ui + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java index b22095187..ccf6ecfb5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarUtils.java @@ -13,109 +13,130 @@ import java.util.Objects; * * @author coolGi */ -public class JarUtils { - public static final File jarFile = new File(JarUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()); - - - /** - * Gets the URI of a resource - * @param resource Resource location - * @return The URI of that file - * @throws URISyntaxException If the file doesnt exist - */ - public static URI accessFileURI(String resource) throws URISyntaxException { - return Objects.requireNonNull(JarUtils.class.getResource(resource)).toURI(); - } - - /** - * Get a file within the mods resources - * @param resource Location of the file you want to get - * @return InputStream - */ - public static InputStream accessFile(String resource) { - final ClassLoader loader = Thread.currentThread().getContextClassLoader(); - // this is the path within the jar file - InputStream input = loader.getResourceAsStream(resource); - if (input == null) { - // this is how we load file within editor - input = loader.getResourceAsStream(resource); - } - - return input; - } - - /** Convert inputStream to String. Useful for reading .txt or .json that are inside the jar file */ - public static String convertInputStreamToString(InputStream inputStream) { - final char[] buffer = new char[8192]; - final StringBuilder result = new StringBuilder(); - - // InputStream -> Reader - try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { - int charsRead; - while ((charsRead = reader.read(buffer, 0, buffer.length)) > 0) { - result.append(buffer, 0, charsRead); - } - } catch (Exception e) { - e.printStackTrace(); - } - - return result.toString(); - } - - /** - * Checks the checksum of a file given an algorithm - * - * @param digest What algorithem to use
- * Eg.
- * MessageDigest.getInstance("MD5")
- * MessageDigest.getInstance("SHA-256")
- * @param file Location of the file - * @return Checksum - */ - // Stolen from https://howtodoinjava.com/java/java-security/sha-md5-file-checksum-hash/ - public static String getFileChecksum(MessageDigest digest, File file) throws IOException { - //Get file input stream for reading the file content - FileInputStream fis = new FileInputStream(file); - - //Create byte array to read data in chunks - byte[] byteArray = new byte[1024]; - int bytesCount = 0; - - //Read file data and update in message digest - while ((bytesCount = fis.read(byteArray)) != -1) { - digest.update(byteArray, 0, bytesCount); - }; - - //close the stream; We don't need it now. - fis.close(); - - //Get the hash's bytes - byte[] bytes = digest.digest(); - - //This bytes[] has bytes in decimal format; - //Convert it to hexadecimal format - StringBuilder sb = new StringBuilder(); - for(int i=0; i< bytes.length ;i++) - { - sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); - } - - //return complete hash - return sb.toString(); - } - - - /** Please use the Platform enum instead */ - @Deprecated - public enum OperatingSystem {WINDOWS, MACOS, LINUX, NONE} // Easy to use enum for the 3 main os's - /** Please use the Platform enum instead */ - @Deprecated - public static OperatingSystem getOperatingSystem() { // Get the os and turn it into that enum - switch (Platform.get()) { - case WINDOWS: return OperatingSystem.WINDOWS; - case LINUX: return OperatingSystem.LINUX; - case MACOS: return OperatingSystem.MACOS; - default: return OperatingSystem.NONE; - } - } +public class JarUtils +{ + public static final File jarFile = new File(JarUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + + + /** + * Gets the URI of a resource + * + * @param resource Resource location + * @return The URI of that file + * @throws URISyntaxException If the file doesnt exist + */ + public static URI accessFileURI(String resource) throws URISyntaxException + { + return Objects.requireNonNull(JarUtils.class.getResource(resource)).toURI(); + } + + /** + * Get a file within the mods resources + * + * @param resource Location of the file you want to get + * @return InputStream + */ + public static InputStream accessFile(String resource) + { + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); + // this is the path within the jar file + InputStream input = loader.getResourceAsStream(resource); + if (input == null) + { + // this is how we load file within editor + input = loader.getResourceAsStream(resource); + } + + return input; + } + + /** Convert inputStream to String. Useful for reading .txt or .json that are inside the jar file */ + public static String convertInputStreamToString(InputStream inputStream) + { + final char[] buffer = new char[8192]; + final StringBuilder result = new StringBuilder(); + + // InputStream -> Reader + try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) + { + int charsRead; + while ((charsRead = reader.read(buffer, 0, buffer.length)) > 0) + { + result.append(buffer, 0, charsRead); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + + return result.toString(); + } + + /** + * Checks the checksum of a file given an algorithm + * + * @param digest What algorithem to use
+ * Eg.
+ * MessageDigest.getInstance("MD5")
+ * MessageDigest.getInstance("SHA-256")
+ * @param file Location of the file + * @return Checksum + */ + // Stolen from https://howtodoinjava.com/java/java-security/sha-md5-file-checksum-hash/ + public static String getFileChecksum(MessageDigest digest, File file) throws IOException + { + //Get file input stream for reading the file content + FileInputStream fis = new FileInputStream(file); + + //Create byte array to read data in chunks + byte[] byteArray = new byte[1024]; + int bytesCount = 0; + + //Read file data and update in message digest + while ((bytesCount = fis.read(byteArray)) != -1) + { + digest.update(byteArray, 0, bytesCount); + } ; + + //close the stream; We don't need it now. + fis.close(); + + //Get the hash's bytes + byte[] bytes = digest.digest(); + + //This bytes[] has bytes in decimal format; + //Convert it to hexadecimal format + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < bytes.length; i++) + { + sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); + } + + //return complete hash + return sb.toString(); + } + + + /** Please use the Platform enum instead */ + @Deprecated + public enum OperatingSystem + {WINDOWS, MACOS, LINUX, NONE} // Easy to use enum for the 3 main os's + /** Please use the Platform enum instead */ + @Deprecated + public static OperatingSystem getOperatingSystem() + { // Get the os and turn it into that enum + switch (Platform.get()) + { + case WINDOWS: + return OperatingSystem.WINDOWS; + case LINUX: + return OperatingSystem.LINUX; + case MACOS: + return OperatingSystem.MACOS; + default: + return OperatingSystem.NONE; + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/ModGitInfo.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/ModGitInfo.java index 04682be33..5d0f73517 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/ModGitInfo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/ModGitInfo.java @@ -12,15 +12,15 @@ import org.apache.logging.log4j.Logger; * * @author coolGi */ -public final class ModGitInfo +public final class ModGitInfo { private static final Logger LOGGER = LogManager.getLogger(); private static final String FILE_NAME = "build_info.json"; - static - { + static + { String gitMainCommit = "UNKNOWN"; - String gitMainBranch = "UNKNOWN"; + String gitMainBranch = "UNKNOWN"; String gitCoreCommit = "UNKNOWN"; try @@ -37,15 +37,16 @@ public final class ModGitInfo } catch (Exception | Error e) { - LOGGER.warn("Unable to get the Git information from "+FILE_NAME); + LOGGER.warn("Unable to get the Git information from " + FILE_NAME); } - - Git_Main_Commit = gitMainCommit; - Git_Core_Commit = gitMainBranch; - Git_Main_Branch = gitCoreCommit; - } - - public static final String Git_Main_Commit; - public static final String Git_Core_Commit; - public static final String Git_Main_Branch; + + Git_Main_Commit = gitMainCommit; + Git_Core_Commit = gitMainBranch; + Git_Main_Branch = gitCoreCommit; + } + + public static final String Git_Main_Commit; + public static final String Git_Core_Commit; + public static final String Git_Main_Branch; + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/Platform.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/Platform.java index d83a80b81..141ad25e6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/Platform.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/Platform.java @@ -6,89 +6,111 @@ package com.seibel.distanthorizons.core.jar; * * @author coolGi */ -public enum Platform { - WINDOWS("Windows", false), - LINUX("Linux", true), - MACOS("macOS", true), - BSD("BSD", true), - UNIX("Unix", true); - - public enum Architecture { - X86(false), - X64(true), - ARM32(false), - ARM64(true); - - static final Architecture current; - final boolean is64Bit; - - static { - String osArch = System.getProperty("os.arch"); - boolean is64Bit = osArch.contains("64") || osArch.startsWith("armv8"); - - current = osArch.startsWith("arm") || osArch.startsWith("aarch64") - ? (is64Bit ? ARM64 : ARM32) - : (is64Bit ? X64 : X86); - } - - Architecture(boolean is64Bit) { - this.is64Bit = is64Bit; - } - } - - private static final Platform current; - - static { - String osName = System.getProperty("os.name").toLowerCase(); - if (osName.contains("windows")) { // Proper name is "Windows" - current = WINDOWS; - } else if (osName.contains("linux")) { // Proper name is "Linux" - current = LINUX; - } else if (osName.contains("mac") || osName.contains("darwin")) { // For MacOS it should either output "Mac OS X" or "Darwin" depending on the version of MacOS - current = MACOS; - } else if (osName.startsWith("bsd")) { // Depending on the BSD distro this will be different - current = BSD; - } else if (osName.startsWith("unix")) { // In case you are running some very niece OS which didnt change their OS name from Unix - current = UNIX; - } else { - // We only test on Windows, Linux and MacOS - // If you use a different os (eg, BSD, Unix) then it may or may not work - // Otherwise, good luck - throw new LinkageError("Unknown platform: " + osName); - } - } - - private final String name; - private final boolean isUnix; - - Platform(String name, boolean isUnix) { - this.name = name; - this.isUnix = isUnix; - } - - /** Returns the platform name. */ - public String getName() { - return name; - } - - /** Returns weather the OS is Unix or Unix-Like OS */ - public boolean isUnix() { - return isUnix; - } - - /** Returns the platform on which the library is running. */ - public static Platform get() { - return current; - } - - /** Returns the architecture on which the library is running. */ - public static Architecture getArchitecture() { - return Architecture.current; - } - - - @Override - public String toString() { - return this.getName(); - } +public enum Platform +{ + WINDOWS("Windows", false), + LINUX("Linux", true), + MACOS("macOS", true), + BSD("BSD", true), + UNIX("Unix", true); + + public enum Architecture + { + X86(false), + X64(true), + ARM32(false), + ARM64(true); + + static final Architecture current; + final boolean is64Bit; + + static + { + String osArch = System.getProperty("os.arch"); + boolean is64Bit = osArch.contains("64") || osArch.startsWith("armv8"); + + current = osArch.startsWith("arm") || osArch.startsWith("aarch64") + ? (is64Bit ? ARM64 : ARM32) + : (is64Bit ? X64 : X86); + } + + Architecture(boolean is64Bit) + { + this.is64Bit = is64Bit; + } + } + + private static final Platform current; + + static + { + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("windows")) + { // Proper name is "Windows" + current = WINDOWS; + } + else if (osName.contains("linux")) + { // Proper name is "Linux" + current = LINUX; + } + else if (osName.contains("mac") || osName.contains("darwin")) + { // For MacOS it should either output "Mac OS X" or "Darwin" depending on the version of MacOS + current = MACOS; + } + else if (osName.startsWith("bsd")) + { // Depending on the BSD distro this will be different + current = BSD; + } + else if (osName.startsWith("unix")) + { // In case you are running some very niece OS which didnt change their OS name from Unix + current = UNIX; + } + else + { + // We only test on Windows, Linux and MacOS + // If you use a different os (eg, BSD, Unix) then it may or may not work + // Otherwise, good luck + throw new LinkageError("Unknown platform: " + osName); + } + } + + private final String name; + private final boolean isUnix; + + Platform(String name, boolean isUnix) + { + this.name = name; + this.isUnix = isUnix; + } + + /** Returns the platform name. */ + public String getName() + { + return name; + } + + /** Returns weather the OS is Unix or Unix-Like OS */ + public boolean isUnix() + { + return isUnix; + } + + /** Returns the platform on which the library is running. */ + public static Platform get() + { + return current; + } + + /** Returns the architecture on which the library is running. */ + public static Architecture getArchitecture() + { + return Architecture.current; + } + + + @Override + public String toString() + { + return this.getName(); + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java index 344d792dd..a230fec5e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java @@ -23,166 +23,215 @@ import java.util.List; // This will be removed later on to make a better ui // To get colors use https://alvinalexander.com/java/java-uimanager-color-keys-list/ // TODO: Make the code less spaghetti later -public class BaseJFrame extends JFrame { - public BaseJFrame() { - init(); - } - public BaseJFrame(boolean show, boolean resizable) { - init(); - setVisible(show); - setResizable(resizable); - } - - public void init() { - setTitle(SingletonInjector.INSTANCE.get(ILangWrapper.class).getLang("lod.title")); - try { - setIconImage(new FlatSVGIcon(JarUtils.accessFile("iconLegacy.svg")).getImage()); // SVG Salamander (the library which we use for svg files) doesn't support css class colors - } catch (Exception e) {e.printStackTrace();} - setSize(720, 480); - setLocationRelativeTo(null); // Puts the window at the middle of the screen - setLayout(new BorderLayout()); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - initLookAndFeel(); - } - - /** - * Buttons for language and theme changing - * - * @param themeOnBottom Puts the theme buttons below the language - * @param rootPosOnLeft Where the start for the x is (on the left of the buttons or on the right) - */ - public void addExtraButtons(int x, int y, boolean themeOnBottom, boolean rootPosOnLeft) { - // ========== LANGUAGE ========== - int langBoxHeight = 25; - int langBoxWidth = 100; - - // Creates a list with all the options in it - List langsToChoose = new ArrayList<>(); - try( - final InputStreamReader isr = new InputStreamReader(JarUtils.accessFile("assets/distanthorizons/lang"), StandardCharsets.UTF_8); - final BufferedReader br = new BufferedReader(isr) - ) { - List col = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(br.lines().toArray()))); - for (Object obj: col) - langsToChoose.add(((String) obj).replaceAll("\\.json", "")); - } catch (Exception e) {e.printStackTrace();} - - // Creates the box - JComboBox languageBox = new JComboBox(new DefaultComboBoxModel(langsToChoose.toArray())); - languageBox.setSelectedIndex(langsToChoose.indexOf(Locale.getDefault().toString().toLowerCase())); - languageBox.addActionListener( e -> { - Locale.setDefault(Locale.forLanguageTag(languageBox.getSelectedItem().toString())); // Change lang on update - } ); - // Set where it goes - languageBox.setBounds(rootPosOnLeft? x : x-langBoxWidth, themeOnBottom? y : y+langBoxHeight, langBoxWidth, langBoxHeight); - // And finally add it - add(languageBox); - - - // ========== THEMING ========== - // TODO: Change the theme to a toggle switch rather than having 2 buttons - int themeButtonSize = 25; - JButton lightMode = null; - JButton darkMode = null; - // Try to set the icons for them - try { - lightMode = new JButton(new ImageIcon( - new FlatSVGIcon(JarUtils.accessFile("assets/distanthorizons/textures/jar/themeLight.svg")).getImage() // Get the image - .getScaledInstance(themeButtonSize, themeButtonSize, Image.SCALE_DEFAULT) // Scale it to the correct size - )); - darkMode = new JButton(new ImageIcon( - new FlatSVGIcon(JarUtils.accessFile("assets/distanthorizons/textures/jar/themeDark.svg")).getImage() // Get the image - .getScaledInstance(themeButtonSize, themeButtonSize, Image.SCALE_DEFAULT) // Scale it to the correct size - )); - } catch (Exception e) {e.printStackTrace();} - // Where do the buttons go - lightMode.setBounds(rootPosOnLeft? x : x-(themeButtonSize*2), themeOnBottom? y+langBoxHeight: y, themeButtonSize, themeButtonSize); - darkMode.setBounds(rootPosOnLeft? x+themeButtonSize : x-themeButtonSize, themeOnBottom? y+langBoxHeight: y, themeButtonSize, themeButtonSize); - // Tell buttons what to do - lightMode.addActionListener(e -> { - FlatLightLaf.setup(); - FlatLightLaf.updateUI(); - }); - darkMode.addActionListener(e -> { - FlatDarkLaf.setup(); - FlatDarkLaf.updateUI(); - }); - // Finally add the buttons - add(lightMode); - add(darkMode); - } - - public BaseJFrame addLogo() { - int logoHeight = 200; - - JPanel logo = new JPanel() { - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - try { - BufferedImage image = ImageIO.read(JarUtils.accessFile("logo.png")); - int logoWidth = (int) ((double) logoHeight * ((double) image.getWidth() / (double) image.getHeight())); // Calculate the aspect ratio and set the height correctly to not stretch it - g.drawImage(image, (getWidth()/2)-(logoWidth/2), 0, logoWidth, logoHeight,this); // Resize image and draw it - } catch (Exception e) {e.printStackTrace();} - } - }; - logo.setBounds(logo.getX(), logo.getY(), logo.getWidth(), logo.getHeight()); - - add(logo); - - return this; - } - - - - - // This part of the code is taken from the official java docs at https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html - - // Specify the look and feel to use by defining the LOOKANDFEEL constant - // Valid values are: null (use the default), "Metal", "System", "Motif", and "GTK" - final static String LOOKANDFEEL = "GTK"; - private static void initLookAndFeel() { - String lookAndFeel = null; - - if (LOOKANDFEEL != null) { - if (LOOKANDFEEL.equals("Metal")) { - lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); - // an alternative way to set the Metal L&F is to replace the - // previous line with: - // lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel"; - - } else if (LOOKANDFEEL.equals("System")) { - lookAndFeel = UIManager.getSystemLookAndFeelClassName(); - } else if (LOOKANDFEEL.equals("Motif")) { - lookAndFeel = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; - } else if (LOOKANDFEEL.equals("GTK")) { - lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; - } else { - System.err.println("Unexpected value of LOOKANDFEEL specified: " - + LOOKANDFEEL); - lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); - } - - try { - UIManager.setLookAndFeel(lookAndFeel); - } catch (ClassNotFoundException e) { - System.err.println("Couldn't find class for specified look and feel:" - + lookAndFeel); - System.err.println("Did you include the L&F library in the class path?"); - System.err.println("Using the default look and feel."); - } catch (UnsupportedLookAndFeelException e) { - System.err.println("Can't use the specified look and feel (" - + lookAndFeel - + ") on this platform."); - System.err.println("Using the default look and feel."); - } catch (Exception e) { - System.err.println("Couldn't get specified look and feel (" - + lookAndFeel - + "), for some reason."); - System.err.println("Using the default look and feel."); - e.printStackTrace(); - } - } - } +public class BaseJFrame extends JFrame +{ + public BaseJFrame() + { + init(); + } + public BaseJFrame(boolean show, boolean resizable) + { + init(); + setVisible(show); + setResizable(resizable); + } + + public void init() + { + setTitle(SingletonInjector.INSTANCE.get(ILangWrapper.class).getLang("lod.title")); + try + { + setIconImage(new FlatSVGIcon(JarUtils.accessFile("iconLegacy.svg")).getImage()); // SVG Salamander (the library which we use for svg files) doesn't support css class colors + } + catch (Exception e) + { + e.printStackTrace(); + } + setSize(720, 480); + setLocationRelativeTo(null); // Puts the window at the middle of the screen + setLayout(new BorderLayout()); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + initLookAndFeel(); + } + + /** + * Buttons for language and theme changing + * + * @param themeOnBottom Puts the theme buttons below the language + * @param rootPosOnLeft Where the start for the x is (on the left of the buttons or on the right) + */ + public void addExtraButtons(int x, int y, boolean themeOnBottom, boolean rootPosOnLeft) + { + // ========== LANGUAGE ========== + int langBoxHeight = 25; + int langBoxWidth = 100; + + // Creates a list with all the options in it + List langsToChoose = new ArrayList<>(); + try ( + final InputStreamReader isr = new InputStreamReader(JarUtils.accessFile("assets/distanthorizons/lang"), StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(isr) + ) + { + List col = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(br.lines().toArray()))); + for (Object obj : col) + { + langsToChoose.add(((String) obj).replaceAll("\\.json", "")); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + + // Creates the box + JComboBox languageBox = new JComboBox(new DefaultComboBoxModel(langsToChoose.toArray())); + languageBox.setSelectedIndex(langsToChoose.indexOf(Locale.getDefault().toString().toLowerCase())); + languageBox.addActionListener(e -> { + Locale.setDefault(Locale.forLanguageTag(languageBox.getSelectedItem().toString())); // Change lang on update + }); + // Set where it goes + languageBox.setBounds(rootPosOnLeft ? x : x - langBoxWidth, themeOnBottom ? y : y + langBoxHeight, langBoxWidth, langBoxHeight); + // And finally add it + add(languageBox); + + + // ========== THEMING ========== + // TODO: Change the theme to a toggle switch rather than having 2 buttons + int themeButtonSize = 25; + JButton lightMode = null; + JButton darkMode = null; + // Try to set the icons for them + try + { + lightMode = new JButton(new ImageIcon( + new FlatSVGIcon(JarUtils.accessFile("assets/distanthorizons/textures/jar/themeLight.svg")).getImage() // Get the image + .getScaledInstance(themeButtonSize, themeButtonSize, Image.SCALE_DEFAULT) // Scale it to the correct size + )); + darkMode = new JButton(new ImageIcon( + new FlatSVGIcon(JarUtils.accessFile("assets/distanthorizons/textures/jar/themeDark.svg")).getImage() // Get the image + .getScaledInstance(themeButtonSize, themeButtonSize, Image.SCALE_DEFAULT) // Scale it to the correct size + )); + } + catch (Exception e) + { + e.printStackTrace(); + } + // Where do the buttons go + lightMode.setBounds(rootPosOnLeft ? x : x - (themeButtonSize * 2), themeOnBottom ? y + langBoxHeight : y, themeButtonSize, themeButtonSize); + darkMode.setBounds(rootPosOnLeft ? x + themeButtonSize : x - themeButtonSize, themeOnBottom ? y + langBoxHeight : y, themeButtonSize, themeButtonSize); + // Tell buttons what to do + lightMode.addActionListener(e -> { + FlatLightLaf.setup(); + FlatLightLaf.updateUI(); + }); + darkMode.addActionListener(e -> { + FlatDarkLaf.setup(); + FlatDarkLaf.updateUI(); + }); + // Finally add the buttons + add(lightMode); + add(darkMode); + } + + public BaseJFrame addLogo() + { + int logoHeight = 200; + + JPanel logo = new JPanel() + { + @Override + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + try + { + BufferedImage image = ImageIO.read(JarUtils.accessFile("logo.png")); + int logoWidth = (int) ((double) logoHeight * ((double) image.getWidth() / (double) image.getHeight())); // Calculate the aspect ratio and set the height correctly to not stretch it + g.drawImage(image, (getWidth() / 2) - (logoWidth / 2), 0, logoWidth, logoHeight, this); // Resize image and draw it + } + catch (Exception e) + { + e.printStackTrace(); + } + } + }; + logo.setBounds(logo.getX(), logo.getY(), logo.getWidth(), logo.getHeight()); + + add(logo); + + return this; + } + + + + + // This part of the code is taken from the official java docs at https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html + + // Specify the look and feel to use by defining the LOOKANDFEEL constant + // Valid values are: null (use the default), "Metal", "System", "Motif", and "GTK" + final static String LOOKANDFEEL = "GTK"; + private static void initLookAndFeel() + { + String lookAndFeel = null; + + if (LOOKANDFEEL != null) + { + if (LOOKANDFEEL.equals("Metal")) + { + lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); + // an alternative way to set the Metal L&F is to replace the + // previous line with: + // lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel"; + + } + else if (LOOKANDFEEL.equals("System")) + { + lookAndFeel = UIManager.getSystemLookAndFeelClassName(); + } + else if (LOOKANDFEEL.equals("Motif")) + { + lookAndFeel = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + } + else if (LOOKANDFEEL.equals("GTK")) + { + lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; + } + else + { + System.err.println("Unexpected value of LOOKANDFEEL specified: " + + LOOKANDFEEL); + lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); + } + + try + { + UIManager.setLookAndFeel(lookAndFeel); + } + catch (ClassNotFoundException e) + { + System.err.println("Couldn't find class for specified look and feel:" + + lookAndFeel); + System.err.println("Did you include the L&F library in the class path?"); + System.err.println("Using the default look and feel."); + } + catch (UnsupportedLookAndFeelException e) + { + System.err.println("Can't use the specified look and feel (" + + lookAndFeel + + ") on this platform."); + System.err.println("Using the default look and feel."); + } + catch (Exception e) + { + System.err.println("Couldn't get specified look and feel (" + + lookAndFeel + + "), for some reason."); + System.err.println("Using the default look and feel."); + e.printStackTrace(); + } + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitch.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitch.java index 8fb7c4fb7..f04776fae 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitch.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitch.java @@ -14,11 +14,11 @@ import javax.swing.plaf.ButtonUI; * A switch button cus Java dosnt have one * *

- * Ever wanted a switch like - * this - * or - * this? - * Well now you can this this class! + * Ever wanted a switch like + * this + * or + * this? + * Well now you can this this class! *

* * Based off Java's JButton @@ -27,57 +27,63 @@ import javax.swing.plaf.ButtonUI; */ // TODO: Make this for the theme (and finish the documentation once it is done) @SuppressWarnings("serial") -public class JSwitch extends AbstractButton { - private static final String uiClassID = "SwitchUI"; - - /** Creates a switch with no set text or icons */ - public JSwitch() { - this(null, null, null, null); - } - - /** - * Creates a switch with an icon - * - * @param offIcon The deactivated icon image - * @param onIcon The activated icon image - */ - public JSwitch(Icon offIcon, Icon onIcon) { - this(null, null, offIcon, onIcon); - } - - /** - * Creates a switch with text - * - * @param offText the deactivated text of the button - * @param onText the activated text of the button - */ - @ConstructorProperties({"text"}) - public JSwitch(String offText, String onText) { - this(offText, onText, null, null); - } - - /** - * Creates a switch where properties are taken from the - * Action supplied. - * - * @param a the Action used to specify the code that runs when pressing - */ - public JSwitch(Action a) { - this(); - setAction(a); - } - - /** - * Creates a switch with initial text and an icon - * - * @param offText the deactivated text of the button - * @param onText the activated text of the button - * @param offIcon The deactivated icon image - * @param onIcon The activated icon image - */ - public JSwitch(String offText, String onText, Icon offIcon, Icon onIcon) { - // Create the model - setModel(new DefaultButtonModel()); +public class JSwitch extends AbstractButton +{ + private static final String uiClassID = "SwitchUI"; + + /** Creates a switch with no set text or icons */ + public JSwitch() + { + this(null, null, null, null); + } + + /** + * Creates a switch with an icon + * + * @param offIcon The deactivated icon image + * @param onIcon The activated icon image + */ + public JSwitch(Icon offIcon, Icon onIcon) + { + this(null, null, offIcon, onIcon); + } + + /** + * Creates a switch with text + * + * @param offText the deactivated text of the button + * @param onText the activated text of the button + */ + @ConstructorProperties({"text"}) + public JSwitch(String offText, String onText) + { + this(offText, onText, null, null); + } + + /** + * Creates a switch where properties are taken from the + * Action supplied. + * + * @param a the Action used to specify the code that runs when pressing + */ + public JSwitch(Action a) + { + this(); + setAction(a); + } + + /** + * Creates a switch with initial text and an icon + * + * @param offText the deactivated text of the button + * @param onText the activated text of the button + * @param offIcon The deactivated icon image + * @param onIcon The activated icon image + */ + public JSwitch(String offText, String onText, Icon offIcon, Icon onIcon) + { + // Create the model + setModel(new DefaultButtonModel()); // this.trueLabel = trueLabel; // this.falseLabel = falseLabel; @@ -97,20 +103,22 @@ public class JSwitch extends AbstractButton { // } // } // }); - } - - /** - * Resets the UI property to a value from the current look and feel - * - * @see JComponent#updateUI - */ - public void updateUI() { - setUI((ButtonUI)UIManager.getUI(this)); - } - - - @Override - public void setSelected( boolean b ) { + } + + /** + * Resets the UI property to a value from the current look and feel + * + * @see JComponent#updateUI + */ + public void updateUI() + { + setUI((ButtonUI) UIManager.getUI(this)); + } + + + @Override + public void setSelected(boolean b) + { // if(b){ // setText( trueLabel ); // setBackground( green ); @@ -118,32 +126,35 @@ public class JSwitch extends AbstractButton { // setBackground( red ); // setText( falseLabel ); // } - super.setSelected( b ); - } - - - /** - * Returns a string that specifies the name of the L&F class - * that renders this component. - * - * @return the string "ButtonUI" - * @see JComponent#getUIClassID - * @see UIDefaults#getUI - */ - public String getUIClassID() { - return uiClassID; - } - - - /** - * Overrides JComponent.removeNotify to check if - * this button is currently set as the default button on the - * RootPane, and if so, sets the RootPane's - * default button to null to ensure the - * RootPane doesn't hold onto an invalid button reference. - */ - public void removeNotify() { - JRootPane root = SwingUtilities.getRootPane(this); - super.removeNotify(); - } + super.setSelected(b); + } + + + /** + * Returns a string that specifies the name of the L&F class + * that renders this component. + * + * @return the string "ButtonUI" + * @see JComponent#getUIClassID + * @see UIDefaults#getUI + */ + public String getUIClassID() + { + return uiClassID; + } + + + /** + * Overrides JComponent.removeNotify to check if + * this button is currently set as the default button on the + * RootPane, and if so, sets the RootPane's + * default button to null to ensure the + * RootPane doesn't hold onto an invalid button reference. + */ + public void removeNotify() + { + JRootPane root = SwingUtilities.getRootPane(this); + super.removeNotify(); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitchBox.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitchBox.java index 75a077356..0393f49f6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitchBox.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/JSwitchBox.java @@ -26,155 +26,175 @@ import javax.swing.border.Border; */ // TODO: Merge this with my own JSwitch rather than use all their code // TODO: Make it work with the theme rather than do whatever it is doing now -public class JSwitchBox extends AbstractButton { - private Color shadow1 = UIManager.getColor("controlHighlight"); - private Color shadow2 = UIManager.getColor("control"); - private Color colorBright = UIManager.getColor("Button.light"); - private Color red = UIManager.getColor("controlShadow"); - private Color redf = UIManager.getColor("Button.foreground"); - private Color trackBackground = UIManager.getColor("textHighlight"); - private Color trackBackgroundText = UIManager.getColor("textHighlightText"); - private Border buttonBorder = UIManager.getBorder("Button.border"); - private Border trackBorder = UIManager.getBorder("Button.border"); - - private Font font = new JLabel().getFont(); - private int gap = 5; - private int globalWitdh = 0; - private final String trueLabel; - private final String falseLabel; - private Dimension thumbBounds; - private Rectangle2D bounds; - private int max; - - public JSwitchBox(String trueLabel, String falseLabel) { - setBackground(UIManager.getColor("Panel.background")); - this.trueLabel = trueLabel; - this.falseLabel = falseLabel; - FontMetrics fontMetrics = getFontMetrics(getFont()); - double trueLenth = fontMetrics - .getStringBounds(trueLabel, getGraphics()).getWidth(); - double falseLenght = fontMetrics.getStringBounds(falseLabel, - getGraphics()).getWidth(); - max = (int) Math.max(trueLenth, falseLenght); - gap = Math.max(5, 5 + (int) Math.abs(trueLenth - falseLenght)); - thumbBounds = new Dimension(max + gap * 2, - (int) ((float) fontMetrics.getHeight() * 1.5)); - globalWitdh = max + thumbBounds.width + gap * 2; - setModel(new DefaultButtonModel()); - setSelected(false); - addMouseListener(new MouseAdapter() { - @Override - public void mouseReleased(MouseEvent e) { - if (new Rectangle(getPreferredSize()).contains(e.getPoint())) { - setSelected(!isSelected()); - } - } - }); - } - - @Override - public Dimension getPreferredSize() { - return new Dimension(globalWitdh, thumbBounds.height); - } - - @Override - public void setSelected(boolean b) { - if (b) { - setText(trueLabel); - setBackground(trackBackground); - setForeground(trackBackgroundText); - } else { - setBackground(red); - setForeground(redf); - setText(falseLabel); - } - super.setSelected(b); - } - - @Override - public void setText(String text) { - super.setText(text); - } - - @Override - public int getHeight() { - - return getPreferredSize().height; - } - - @Override - public int getWidth() { - return getPreferredSize().width; - } - - @Override - public Font getFont() { - return font; - } - - @Override - protected void paintComponent(Graphics g) { - g.setColor(getBackground()); - g.fillRect(0, 0, getWidth(), getHeight() - 4); - Graphics2D g2 = (Graphics2D) g; - - // g2.setColor(black); - // g2.drawRoundRect(1, 1, getWidth() - 2 - 1, getHeight() - 2 - 1, 2, - // 2); - // g2.setColor(white); - // g2.drawRoundRect(1 + 1, 1 + 1, getWidth() - 2 - 3, getHeight() - 2 - - // 3, - // 2, 2); - - trackBorder.paintBorder(this, g2, 0, 2, getWidth(), getHeight() - 4); - - int buttonX = 0; - int textX = 0; - if (isSelected()) { - textX = thumbBounds.width; - } else { - buttonX = thumbBounds.width; - } - int y = 0; - int w = thumbBounds.width; - int h = thumbBounds.height; - - g2.setPaint(new GradientPaint(buttonX, (int) (y - 0.1 * h), shadow2, - buttonX, (int) (y + 1.2 * h), shadow1)); - g2.fillRect(buttonX, y, w, h); - g2.setPaint(new GradientPaint(buttonX, (int) (y + .65 * h), shadow1, - buttonX, (int) (y + 1.3 * h), shadow2)); - g2.fillRect(buttonX, (int) (y + .65 * h), w, (int) (h - .65 * h)); - - if (w > 14) { - int size = 10; - g2.setColor(colorBright); - g2.fillRect(buttonX + w / 2 - size / 2, y + h / 2 - size / 2, size, - size); - g2.setColor(colorBright.darker()); - g2.fillRect(buttonX + w / 2 - 4, h / 2 - 4, 2, 2); - g2.fillRect(buttonX + w / 2 - 1, h / 2 - 4, 2, 2); - g2.fillRect(buttonX + w / 2 + 2, h / 2 - 4, 2, 2); - g2.setColor(colorBright.darker().darker()); - g2.fillRect(buttonX + w / 2 - 4, h / 2 - 2, 2, 6); - g2.fillRect(buttonX + w / 2 - 1, h / 2 - 2, 2, 6); - g2.fillRect(buttonX + w / 2 + 2, h / 2 - 2, 2, 6); - g2.setColor(colorBright.darker()); - g2.fillRect(buttonX + w / 2 - 4, h / 2 + 2, 2, 2); - g2.fillRect(buttonX + w / 2 - 1, h / 2 + 2, 2, 2); - g2.fillRect(buttonX + w / 2 + 2, h / 2 + 2, 2, 2); - } - - buttonBorder.paintBorder(this, g2, buttonX, y, w, h); - // g2.setColor(black); - // g2.drawRoundRect(x, y, w - 1, h - 1, 2, 2); - // g2.setColor(white); - // g2.drawRoundRect(x + 1, y + 1, w - 3, h - 3, 2, 2); - - g2.setColor(getForeground()); - g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g2.setFont(getFont()); - g2.drawString(getText(), textX + gap, y + h / 2 + h / 4); - } +public class JSwitchBox extends AbstractButton +{ + private Color shadow1 = UIManager.getColor("controlHighlight"); + private Color shadow2 = UIManager.getColor("control"); + private Color colorBright = UIManager.getColor("Button.light"); + private Color red = UIManager.getColor("controlShadow"); + private Color redf = UIManager.getColor("Button.foreground"); + private Color trackBackground = UIManager.getColor("textHighlight"); + private Color trackBackgroundText = UIManager.getColor("textHighlightText"); + private Border buttonBorder = UIManager.getBorder("Button.border"); + private Border trackBorder = UIManager.getBorder("Button.border"); + + private Font font = new JLabel().getFont(); + private int gap = 5; + private int globalWitdh = 0; + private final String trueLabel; + private final String falseLabel; + private Dimension thumbBounds; + private Rectangle2D bounds; + private int max; + + public JSwitchBox(String trueLabel, String falseLabel) + { + setBackground(UIManager.getColor("Panel.background")); + this.trueLabel = trueLabel; + this.falseLabel = falseLabel; + FontMetrics fontMetrics = getFontMetrics(getFont()); + double trueLenth = fontMetrics + .getStringBounds(trueLabel, getGraphics()).getWidth(); + double falseLenght = fontMetrics.getStringBounds(falseLabel, + getGraphics()).getWidth(); + max = (int) Math.max(trueLenth, falseLenght); + gap = Math.max(5, 5 + (int) Math.abs(trueLenth - falseLenght)); + thumbBounds = new Dimension(max + gap * 2, + (int) ((float) fontMetrics.getHeight() * 1.5)); + globalWitdh = max + thumbBounds.width + gap * 2; + setModel(new DefaultButtonModel()); + setSelected(false); + addMouseListener(new MouseAdapter() + { + @Override + public void mouseReleased(MouseEvent e) + { + if (new Rectangle(getPreferredSize()).contains(e.getPoint())) + { + setSelected(!isSelected()); + } + } + }); + } + + @Override + public Dimension getPreferredSize() + { + return new Dimension(globalWitdh, thumbBounds.height); + } + + @Override + public void setSelected(boolean b) + { + if (b) + { + setText(trueLabel); + setBackground(trackBackground); + setForeground(trackBackgroundText); + } + else + { + setBackground(red); + setForeground(redf); + setText(falseLabel); + } + super.setSelected(b); + } + + @Override + public void setText(String text) + { + super.setText(text); + } + + @Override + public int getHeight() + { + + return getPreferredSize().height; + } + + @Override + public int getWidth() + { + return getPreferredSize().width; + } + + @Override + public Font getFont() + { + return font; + } + + @Override + protected void paintComponent(Graphics g) + { + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight() - 4); + Graphics2D g2 = (Graphics2D) g; + + // g2.setColor(black); + // g2.drawRoundRect(1, 1, getWidth() - 2 - 1, getHeight() - 2 - 1, 2, + // 2); + // g2.setColor(white); + // g2.drawRoundRect(1 + 1, 1 + 1, getWidth() - 2 - 3, getHeight() - 2 - + // 3, + // 2, 2); + + trackBorder.paintBorder(this, g2, 0, 2, getWidth(), getHeight() - 4); + + int buttonX = 0; + int textX = 0; + if (isSelected()) + { + textX = thumbBounds.width; + } + else + { + buttonX = thumbBounds.width; + } + int y = 0; + int w = thumbBounds.width; + int h = thumbBounds.height; + + g2.setPaint(new GradientPaint(buttonX, (int) (y - 0.1 * h), shadow2, + buttonX, (int) (y + 1.2 * h), shadow1)); + g2.fillRect(buttonX, y, w, h); + g2.setPaint(new GradientPaint(buttonX, (int) (y + .65 * h), shadow1, + buttonX, (int) (y + 1.3 * h), shadow2)); + g2.fillRect(buttonX, (int) (y + .65 * h), w, (int) (h - .65 * h)); + + if (w > 14) + { + int size = 10; + g2.setColor(colorBright); + g2.fillRect(buttonX + w / 2 - size / 2, y + h / 2 - size / 2, size, + size); + g2.setColor(colorBright.darker()); + g2.fillRect(buttonX + w / 2 - 4, h / 2 - 4, 2, 2); + g2.fillRect(buttonX + w / 2 - 1, h / 2 - 4, 2, 2); + g2.fillRect(buttonX + w / 2 + 2, h / 2 - 4, 2, 2); + g2.setColor(colorBright.darker().darker()); + g2.fillRect(buttonX + w / 2 - 4, h / 2 - 2, 2, 6); + g2.fillRect(buttonX + w / 2 - 1, h / 2 - 2, 2, 6); + g2.fillRect(buttonX + w / 2 + 2, h / 2 - 2, 2, 6); + g2.setColor(colorBright.darker()); + g2.fillRect(buttonX + w / 2 - 4, h / 2 + 2, 2, 2); + g2.fillRect(buttonX + w / 2 - 1, h / 2 + 2, 2, 2); + g2.fillRect(buttonX + w / 2 + 2, h / 2 + 2, 2, 2); + } + + buttonBorder.paintBorder(this, g2, buttonX, y, w, h); + // g2.setColor(black); + // g2.drawRoundRect(x, y, w - 1, h - 1, 2, 2); + // g2.setColor(white); + // g2.drawRoundRect(x + 1, y + 1, w - 3, h - 3, 2, 2); + + g2.setColor(getForeground()); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2.setFont(getFont()); + g2.drawString(getText(), textX + gap, y + h / 2 + h / 4); + } + } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/cusomJObject/JBox.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/cusomJObject/JBox.java index ffcf9eaa7..107d97883 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/cusomJObject/JBox.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/cusomJObject/JBox.java @@ -8,42 +8,49 @@ import java.awt.*; * * @author coolGi */ -public class JBox extends JComponent { - private static final String uiClassID = "BoxBarUI"; - - private Color color; - - private int x; - private int y; - private int width; - private int height; - - public JBox() { - this(null); - } - - public JBox(Color color) { - this.color = color; - } - - public JBox(Color color, Rectangle rectangle) { - this(color, rectangle.x, rectangle.y, rectangle.width, rectangle.height); - } - - public JBox(Color color, int x, int y, int width, int height) { - this.color = color; - setBounds(x, y, width, height); - } - - public void setColor(Color color) { - this.color = color; - } - - @Override - public void paintComponent(Graphics g) - { - super.paintComponent(g); - g.setColor(color); - g.fillRect(0, 0, getBounds().width, getBounds().height); - } +public class JBox extends JComponent +{ + private static final String uiClassID = "BoxBarUI"; + + private Color color; + + private int x; + private int y; + private int width; + private int height; + + public JBox() + { + this(null); + } + + public JBox(Color color) + { + this.color = color; + } + + public JBox(Color color, Rectangle rectangle) + { + this(color, rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } + + public JBox(Color color, int x, int y, int width, int height) + { + this.color = color; + setBounds(x, y, width, height); + } + + public void setColor(Color color) + { + this.color = color; + } + + @Override + public void paintComponent(Graphics g) + { + super.paintComponent(g); + g.setColor(color); + g.fillRect(0, 0, getBounds().width, getBounds().height); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java index 7f12e75d7..9aa9f51c9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java @@ -15,18 +15,20 @@ import java.util.stream.Collectors; */ // TODO: Change this to a way to get the nightly builds @Deprecated -public class GitlabGetter { - public static final String GitLabApi = "https://gitlab.com/api/v4/projects/"; - public static final String projectID = "18204078"; +public class GitlabGetter +{ + public static final String GitLabApi = "https://gitlab.com/api/v4/projects/"; + public static final String projectID = "18204078"; // public static JSONArray projectRelease = new JSONArray(); - - public static List releaseNames = new ArrayList<>(); // This list contains the release ID's - public static List readableReleaseNames = new ArrayList<>(); // This list contains the readable names of the ID's - private static List mcVersionReleases = new ArrayList<>(); // A list of all minecraft releases - - - - public static void init() { + + public static List releaseNames = new ArrayList<>(); // This list contains the release ID's + public static List readableReleaseNames = new ArrayList<>(); // This list contains the readable names of the ID's + private static List mcVersionReleases = new ArrayList<>(); // A list of all minecraft releases + + + + public static void init() + { // try { // // TODO: Modify the projectRelease to fix 1.6.0a's versions rather than fixing it everytime we want to use projectReleases // projectRelease = (JSONArray) new JSONParser().parse(WebDownloader.downloadAsString(new URL(GitLabApi+projectID+"/releases"))); @@ -63,11 +65,12 @@ public class GitlabGetter { //// System.out.println(getMcVersionsInRelease("1.6.5a")); //// System.out.println(getMcVersionsInRelease("1.16.4-a1.2")); // } catch (Exception e) { e.printStackTrace(); } - } - - /** Gets the compatible minecraft versions a release of the mod works with */ - public static List getMcVersionsInRelease(String version) { - List versions = new ArrayList<>(); + } + + /** Gets the compatible minecraft versions a release of the mod works with */ + public static List getMcVersionsInRelease(String version) + { + List versions = new ArrayList<>(); // // JSONArray releaseArray = getScuffedReleaseArray(version); // @@ -85,11 +88,12 @@ public class GitlabGetter { // // Sort it so the newest versions of minecraft are at the top // Collections.sort(versions); // Collections.reverse(versions); - - return versions; - } - /** Gets the url to the download of a release of the mod */ - public static URL getRelease(String version, String mcVersion) { + + return versions; + } + /** Gets the url to the download of a release of the mod */ + public static URL getRelease(String version, String mcVersion) + { // JSONArray releaseArray = getScuffedReleaseArray(version); // // if (mcVersion != null) { @@ -106,11 +110,12 @@ public class GitlabGetter { // return new URL(((JSONObject) releaseArray.get(0)).get("direct_asset_url").toString()); // } catch (Exception e) { e.printStackTrace(); } // } - - return null; - } - /** Gets the update log of a release */ - public static String getVersionDescription(String version) { + + return null; + } + /** Gets the update log of a release */ + public static String getVersionDescription(String version) + { // try { // if (!version.equals("1.6.0a")) { // We have to do this cus 1.6.0a stuffed up some ordering // // Do this hack to remove all the mcVer-1.6.0a items from the releaseNames @@ -129,8 +134,8 @@ public class GitlabGetter { // } catch (Exception e) { // e.printStackTrace(); // } - return null; - } + return null; + } // public static JSONArray getScuffedReleaseArray(String version) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/MarkdownFormatter.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/MarkdownFormatter.java index 581ffa836..4e12235f3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/MarkdownFormatter.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/MarkdownFormatter.java @@ -9,59 +9,74 @@ import java.util.regex.Pattern; * * @author coolGi */ -public class MarkdownFormatter { - public static abstract class GenericFormat { - /** Converts Markdown text to a different format */ - public String convertFrom(String original) { - System.out.println("Function \"convertFrom\" for \""+this.getClass().getSimpleName()+"\" not done yet"); - return null; - } - /** Converts formatted text back to Markdown */ - public String convertTo(String original) { - System.out.println("Function \"convertTo\" for \""+this.getClass().getSimpleName()+"\" not done yet"); - return null; - } - } - - - /** Split a string every n characters */ - public static List splitString(String text, int n) { - return Arrays.asList( - text.split("(?<=\\G.{"+ n +"})") - ); - } - private static String replaceRegex(String text, String regex, String start, String end) { - while (Pattern.compile(regex).matcher(text).find()) { - text = text.replaceFirst(regex, start).replaceFirst(regex, end); - } - return text; - } - - - - - public static class HTMLFormat extends GenericFormat { - @Override - public String convertTo(String original) { - original = original.replaceAll("\\\\\\n", "
") // Removes the "\" used in markdown to create new line - .replaceAll("\\n", "
"); // Fix the new line - - original = replaceRegex(original, "\\*\\*", "", ""); // Makes the text bold - original = replaceRegex(original, "~~", "", ""); // Striketrough +public class MarkdownFormatter +{ + public static abstract class GenericFormat + { + /** Converts Markdown text to a different format */ + public String convertFrom(String original) + { + System.out.println("Function \"convertFrom\" for \"" + this.getClass().getSimpleName() + "\" not done yet"); + return null; + } + /** Converts formatted text back to Markdown */ + public String convertTo(String original) + { + System.out.println("Function \"convertTo\" for \"" + this.getClass().getSimpleName() + "\" not done yet"); + return null; + } + + } + + + /** Split a string every n characters */ + public static List splitString(String text, int n) + { + return Arrays.asList( + text.split("(?<=\\G.{" + n + "})") + ); + } + private static String replaceRegex(String text, String regex, String start, String end) + { + while (Pattern.compile(regex).matcher(text).find()) + { + text = text.replaceFirst(regex, start).replaceFirst(regex, end); + } + return text; + } + + + + + public static class HTMLFormat extends GenericFormat + { + @Override + public String convertTo(String original) + { + original = original.replaceAll("\\\\\\n", "
") // Removes the "\" used in markdown to create new line + .replaceAll("\\n", "
"); // Fix the new line + + original = replaceRegex(original, "\\*\\*", "", ""); // Makes the text bold + original = replaceRegex(original, "~~", "", ""); // Striketrough // original = replaceRegex(original, "_", "", ""); // Italic - - return original; - } - } - - public static class MinecraftFormat extends GenericFormat { - @Override - public String convertTo(String original) { - original = original.replaceAll("
", "\n"); // New lines - original = replaceRegex(original, "\\*\\*", "§l", "§r"); // Bold - original = replaceRegex(original, "~~", "§m", "§r"); // Striketrough + + return original; + } + + } + + public static class MinecraftFormat extends GenericFormat + { + @Override + public String convertTo(String original) + { + original = original.replaceAll("
", "\n"); // New lines + original = replaceRegex(original, "\\*\\*", "§l", "§r"); // Bold + original = replaceRegex(original, "~~", "§m", "§r"); // Striketrough // original = replaceRegex(original, "_", "§n", "§r"); // Italic - return original; - } - } + return original; + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java index 8640c678f..704e922b3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java @@ -12,87 +12,113 @@ import java.util.*; * @author coolGi */ // TODO: Fix stuff in here (check how to do stuff with `[{jsonStuff},{jsonStuff}]` which needs to be remade with nightconfig's json -public class ModrinthGetter { - public static final String ModrinthAPI = "https://api.modrinth.com/v2/project/"; - public static final String projectID = "distanthorizons"; - public static boolean initted = false; - public static ArrayList projectRelease; - public static Map idToJson = new HashMap<>(); - - public static List releaseID = new ArrayList<>(); // This list contains the release ID's - public static List mcVersions = new ArrayList<>(); // List of available Minecraft versions in the mod - /** Arg 1 = Release ID; - * Arg 2 = Readable name */ - public static Map releaseNames = new HashMap<>(); // This list contains the readable names of the ID's to the - /** Arg 1 = Minecraft version; - * Arg 2 = Compatible project ID's for that */ - public static Map> mcVerToReleaseID = new HashMap<>(); - /** Arg 1 = ID; - * Arg 2 = Download URL */ - public static Map downloadUrl = new HashMap<>(); // Get the download url - /** Arg 1 = ID; - * Arg 2 = Changelog */ - public static Map changeLogs = new HashMap<>(); - - - public static boolean init() { - try { - initted = false; - projectRelease = JsonFormat.fancyInstance().createParser().parse("{\"E\":" + WebDownloader.downloadAsString(new URL(ModrinthAPI+projectID+"/version")) + "}").get("E"); - - - for (Config currentRelease: projectRelease) { - String workingID = currentRelease.get("id").toString(); - - releaseID.add(workingID); - idToJson.put(workingID, currentRelease); - releaseNames.put(workingID, currentRelease.get("name").toString().replaceAll(" - 1\\..*", "")); - changeLogs.put(workingID, currentRelease.get("changelog").toString()); - try { - downloadUrl.put(workingID, - new URL( - ((Config) - ((ArrayList) currentRelease.get("files")) - .get(0)) - .get("url") - .toString() - )); - } catch (Exception e) { e.printStackTrace(); } - - // Get all the mc versions this mod is available for - for(String mcVer : (List) currentRelease.get("game_versions")) { - if (!mcVersions.contains(mcVer)) { - mcVersions.add(mcVer); - mcVerToReleaseID.put(mcVer, new ArrayList<>()); - } - mcVerToReleaseID.get(mcVer).add(workingID); - } - } - // Sort them to look better - Collections.sort(mcVersions); - Collections.reverse(mcVersions); - - initted = true; - return true; - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - public static String getLatestIDForVersion(String mcVer) { - return mcVerToReleaseID.get(mcVer).get(0); - } - public static String getLatestNameForVersion(String mcVer) { - return releaseNames.get(mcVerToReleaseID.get(mcVer).get(0)); - } - public static URL getLatestDownloadForVersion(String mcVer) { - return downloadUrl.get(mcVerToReleaseID.get(mcVer).get(0)); - } - public static String getLatestShaForVersion(String mcVer) { - return (((ArrayList) idToJson.get( - mcVerToReleaseID.get(mcVer).get(0) - ).get("files")).get(0).get("hashes.sha1") - .toString()); - } +public class ModrinthGetter +{ + public static final String ModrinthAPI = "https://api.modrinth.com/v2/project/"; + public static final String projectID = "distanthorizons"; + public static boolean initted = false; + public static ArrayList projectRelease; + public static Map idToJson = new HashMap<>(); + + public static List releaseID = new ArrayList<>(); // This list contains the release ID's + public static List mcVersions = new ArrayList<>(); // List of available Minecraft versions in the mod + /** + * Arg 1 = Release ID; + * Arg 2 = Readable name + */ + public static Map releaseNames = new HashMap<>(); // This list contains the readable names of the ID's to the + /** + * Arg 1 = Minecraft version; + * Arg 2 = Compatible project ID's for that + */ + public static Map> mcVerToReleaseID = new HashMap<>(); + /** + * Arg 1 = ID; + * Arg 2 = Download URL + */ + public static Map downloadUrl = new HashMap<>(); // Get the download url + /** + * Arg 1 = ID; + * Arg 2 = Changelog + */ + public static Map changeLogs = new HashMap<>(); + + + public static boolean init() + { + try + { + initted = false; + projectRelease = JsonFormat.fancyInstance().createParser().parse("{\"E\":" + WebDownloader.downloadAsString(new URL(ModrinthAPI + projectID + "/version")) + "}").get("E"); + + + for (Config currentRelease : projectRelease) + { + String workingID = currentRelease.get("id").toString(); + + releaseID.add(workingID); + idToJson.put(workingID, currentRelease); + releaseNames.put(workingID, currentRelease.get("name").toString().replaceAll(" - 1\\..*", "")); + changeLogs.put(workingID, currentRelease.get("changelog").toString()); + try + { + downloadUrl.put(workingID, + new URL( + ((Config) + ((ArrayList) currentRelease.get("files")) + .get(0)) + .get("url") + .toString() + )); + } + catch (Exception e) + { + e.printStackTrace(); + } + + // Get all the mc versions this mod is available for + for (String mcVer : (List) currentRelease.get("game_versions")) + { + if (!mcVersions.contains(mcVer)) + { + mcVersions.add(mcVer); + mcVerToReleaseID.put(mcVer, new ArrayList<>()); + } + mcVerToReleaseID.get(mcVer).add(workingID); + } + } + // Sort them to look better + Collections.sort(mcVersions); + Collections.reverse(mcVersions); + + initted = true; + return true; + } + catch (Exception e) + { + e.printStackTrace(); + return false; + } + } + + public static String getLatestIDForVersion(String mcVer) + { + return mcVerToReleaseID.get(mcVer).get(0); + } + public static String getLatestNameForVersion(String mcVer) + { + return releaseNames.get(mcVerToReleaseID.get(mcVer).get(0)); + } + public static URL getLatestDownloadForVersion(String mcVer) + { + return downloadUrl.get(mcVerToReleaseID.get(mcVer).get(0)); + } + public static String getLatestShaForVersion(String mcVer) + { + return (((ArrayList) idToJson.get( + mcVerToReleaseID.get(mcVer).get(0) + ).get("files")).get(0).get("hashes.sha1") + .toString()); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java index 4a561ce84..9f0094abc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java @@ -13,89 +13,106 @@ import java.security.MessageDigest; * * @author coolGi */ -public class WebDownloader { - public static boolean netIsAvailable() { - try { - final URL url = new URL("https://www.google.com"); // Google will probably be online forever so we use that to check network connection - final URLConnection conn = url.openConnection(); - conn.connect(); - conn.getInputStream().close(); - return false; - } catch (Exception e) { - return true; - } - } - - public static void downloadAsFile(URL url, File file) throws Exception { +public class WebDownloader +{ + public static boolean netIsAvailable() + { + try + { + final URL url = new URL("https://www.google.com"); // Google will probably be online forever so we use that to check network connection + final URLConnection conn = url.openConnection(); + conn.connect(); + conn.getInputStream().close(); + return false; + } + catch (Exception e) + { + return true; + } + } + + public static void downloadAsFile(URL url, File file) throws Exception + { // URL url = new URL(urlS); - - HttpsURLConnection connection = (HttpsURLConnection) url - .openConnection(); - long filesize = connection.getContentLengthLong(); - if (filesize == -1) { - throw new Exception("Content length must not be -1 (unknown)!"); - } - long totalDataRead = 0; - try (java.io.BufferedInputStream in = new java.io.BufferedInputStream( - connection.getInputStream())) { - java.io.FileOutputStream fos = new java.io.FileOutputStream(file); - try (java.io.BufferedOutputStream bout = new BufferedOutputStream( - fos, 1024)) { - byte[] data = new byte[1024]; - int i; - while ((i = in.read(data, 0, 1024)) >= 0) { - totalDataRead = totalDataRead + i; - bout.write(data, 0, i); + + HttpsURLConnection connection = (HttpsURLConnection) url + .openConnection(); + long filesize = connection.getContentLengthLong(); + if (filesize == -1) + { + throw new Exception("Content length must not be -1 (unknown)!"); + } + long totalDataRead = 0; + try (java.io.BufferedInputStream in = new java.io.BufferedInputStream( + connection.getInputStream())) + { + java.io.FileOutputStream fos = new java.io.FileOutputStream(file); + try (java.io.BufferedOutputStream bout = new BufferedOutputStream( + fos, 1024)) + { + byte[] data = new byte[1024]; + int i; + while ((i = in.read(data, 0, 1024)) >= 0) + { + totalDataRead = totalDataRead + i; + bout.write(data, 0, i); // int percent = (int) ((totalDataRead * 100) / filesize); // System.out.println(percent); - } - } - } - } - - public static String downloadAsString(URL url) throws Exception { - StringBuilder stringBuilder = new StringBuilder(); + } + } + } + } + + public static String downloadAsString(URL url) throws Exception + { + StringBuilder stringBuilder = new StringBuilder(); // URL url = new URL(urlS); - - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(1000); - urlConnection.setReadTimeout(1000); - BufferedReader bReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); - - String line; - while ((line = bReader.readLine()) != null) { - stringBuilder.append(line); - } - - return (stringBuilder.toString()); - } - - public static String formatMarkdownToHtml(String md, int width) { - String str = String.format("
%s
", width, md); - return new MarkdownFormatter.HTMLFormat().convertTo(str); - } - - - - // Stolen from https://mkyong.com/java/how-to-generate-a-file-checksum-value-in-java/ but added some comments - /** - * @param filepath Path to the file - * @param md The checksum. Can be gotten by "MessageDigest.getInstance("SHA-256")" and can replace string with something like SHA, MD2, MD5, SHA-256, SHA-384... - * @return Returns the checksum using the previous md - */ - private static String checksum(String filepath, MessageDigest md) throws IOException { - // file hashing with DigestInputStream - try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) { - while (dis.read() != -1) ; //empty loop to clear the data - md = dis.getMessageDigest(); - } - - // bytes to hex - StringBuilder result = new StringBuilder(); - for (byte b : md.digest()) { - result.append(String.format("%02x", b)); - } - return result.toString(); - - } + + URLConnection urlConnection = url.openConnection(); + urlConnection.setConnectTimeout(1000); + urlConnection.setReadTimeout(1000); + BufferedReader bReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + + String line; + while ((line = bReader.readLine()) != null) + { + stringBuilder.append(line); + } + + return (stringBuilder.toString()); + } + + public static String formatMarkdownToHtml(String md, int width) + { + String str = String.format("
%s
", width, md); + return new MarkdownFormatter.HTMLFormat().convertTo(str); + } + + + + // Stolen from https://mkyong.com/java/how-to-generate-a-file-checksum-value-in-java/ but added some comments + /** + * @param filepath Path to the file + * @param md The checksum. Can be gotten by "MessageDigest.getInstance("SHA-256")" and can replace string with something like SHA, MD2, MD5, SHA-256, SHA-384... + * @return Returns the checksum using the previous md + */ + private static String checksum(String filepath, MessageDigest md) throws IOException + { + // file hashing with DigestInputStream + try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) + { + while (dis.read() != -1) ; //empty loop to clear the data + md = dis.getMessageDigest(); + } + + // bytes to hex + StringBuilder result = new StringBuilder(); + for (byte b : md.digest()) + { + result.append(String.format("%02x", b)); + } + return result.toString(); + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/tui/BaseTUI.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/tui/BaseTUI.java index 8dff949dd..0bf8e2206 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/tui/BaseTUI.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/tui/BaseTUI.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.core.jar.tui; // TUI stands for terminal ui btw -public class BaseTUI { +public class BaseTUI +{ } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java index 047ae3915..136573f85 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java @@ -22,101 +22,123 @@ import java.security.MessageDigest; * * @author coolGi */ -public class SelfUpdater { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(SelfUpdater.class.getSimpleName()); - - /** As we cannot delete(or replace) the jar while the mod is running, we just have this to delete it once the game closes */ - public static boolean deleteOldOnClose = false; - public static File newFileLocation; - - /** - * Should be called on the game starting. - * (After the config has been initialised) - * @return Whether it should open the update ui - */ - public static boolean onStart() { - // Some init stuff - // We use sha1 to check the version as our versioning system is different to the one on modrinth - if (!ModrinthGetter.init()) return false; - String jarSha = ""; - try { jarSha = JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), JarUtils.jarFile); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - String mcVersion = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); - - // Check the sha's of both our stuff - if (jarSha.equals(ModrinthGetter.getLatestShaForVersion(mcVersion))) - return false; - - - LOGGER.info("New version ("+ModrinthGetter.getLatestNameForVersion(mcVersion)+") of "+ ModInfo.READABLE_NAME+" is available"); - if (Config.Client.Advanced.AutoUpdater.enableSilentUpdates.get()) +public class SelfUpdater +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(SelfUpdater.class.getSimpleName()); + + /** As we cannot delete(or replace) the jar while the mod is running, we just have this to delete it once the game closes */ + public static boolean deleteOldOnClose = false; + public static File newFileLocation; + + /** + * Should be called on the game starting. + * (After the config has been initialised) + * + * @return Whether it should open the update ui + */ + public static boolean onStart() + { + // Some init stuff + // We use sha1 to check the version as our versioning system is different to the one on modrinth + if (!ModrinthGetter.init()) return false; + String jarSha = ""; + try { - newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVersion) + ".jar").toFile(); + jarSha = JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), JarUtils.jarFile); + } + catch (Exception e) + { + e.printStackTrace(); + return false; + } + String mcVersion = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); + + // Check the sha's of both our stuff + if (jarSha.equals(ModrinthGetter.getLatestShaForVersion(mcVersion))) + return false; + + + LOGGER.info("New version (" + ModrinthGetter.getLatestNameForVersion(mcVersion) + ") of " + ModInfo.READABLE_NAME + " is available"); + if (Config.Client.Advanced.AutoUpdater.enableSilentUpdates.get()) + { + newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVersion) + ".jar").toFile(); // Auto-update mod updateMod(mcVersion, newFileLocation); return false; } // else - return true; - } - - /** - * Should be called when the game is closed. - * This is ued to delete the previous file if it is required at the end. - */ - public static void onClose() { - if (deleteOldOnClose) { - try { - Files.move(newFileLocation.toPath(), JarUtils.jarFile.getParentFile().toPath().resolve(newFileLocation.getName())); - Files.delete(newFileLocation.getParentFile().toPath()); - } catch (Exception e) { - LOGGER.warn("Failed to move updated fire from ["+ newFileLocation.getAbsolutePath() +"] to ["+ JarUtils.jarFile.getParentFile().getAbsolutePath() +"], please move it manually"); - e.printStackTrace(); - } - try { - Files.delete(JarUtils.jarFile.toPath()); - } catch (Exception e) { - LOGGER.warn("Failed to delete previous " + ModInfo.READABLE_NAME + " file, please delete it manually at [" + JarUtils.jarFile + "]"); - e.printStackTrace(); - } - } - } - - public static boolean updateMod() { - String mcVer = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); - newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVer) + ".jar").toFile(); - return updateMod( - mcVer, - newFileLocation - ); - } - public static boolean updateMod(String minecraftVersion, File file) { - try { - LOGGER.info("Attempting to auto update " + ModInfo.READABLE_NAME); - - Files.createDirectories(file.getParentFile().toPath()); - WebDownloader.downloadAsFile(ModrinthGetter.getLatestDownloadForVersion(minecraftVersion), file); - - // Check if the checksum of the downloaded jar is correct (not required, but good to have to prevent corruption or interception) - if (!JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), file).equals(ModrinthGetter.getLatestShaForVersion(minecraftVersion))) { - LOGGER.warn("DH update checksum failed, aborting install"); - throw new Exception("Checksum failed"); - } - - deleteOldOnClose = true; - - LOGGER.info(ModInfo.READABLE_NAME + " successfully updated. It will apply on game's relaunch"); - new Thread(() -> { - System.setProperty("java.awt.headless", "false"); // Required to make it work - JOptionPane.showMessageDialog(null, ModInfo.READABLE_NAME+ " updated, this will be applied on game restart.", ModInfo.READABLE_NAME, JOptionPane.INFORMATION_MESSAGE); - }).start(); - return true; - } catch (Exception e) { - LOGGER.warn("Failed to update "+ModInfo.READABLE_NAME+" to version "+ModrinthGetter.getLatestNameForVersion(minecraftVersion)); - e.printStackTrace(); - return false; - } - } + return true; + } + + /** + * Should be called when the game is closed. + * This is ued to delete the previous file if it is required at the end. + */ + public static void onClose() + { + if (deleteOldOnClose) + { + try + { + Files.move(newFileLocation.toPath(), JarUtils.jarFile.getParentFile().toPath().resolve(newFileLocation.getName())); + Files.delete(newFileLocation.getParentFile().toPath()); + } + catch (Exception e) + { + LOGGER.warn("Failed to move updated fire from [" + newFileLocation.getAbsolutePath() + "] to [" + JarUtils.jarFile.getParentFile().getAbsolutePath() + "], please move it manually"); + e.printStackTrace(); + } + try + { + Files.delete(JarUtils.jarFile.toPath()); + } + catch (Exception e) + { + LOGGER.warn("Failed to delete previous " + ModInfo.READABLE_NAME + " file, please delete it manually at [" + JarUtils.jarFile + "]"); + e.printStackTrace(); + } + } + } + + public static boolean updateMod() + { + String mcVer = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); + newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVer) + ".jar").toFile(); + return updateMod( + mcVer, + newFileLocation + ); + } + public static boolean updateMod(String minecraftVersion, File file) + { + try + { + LOGGER.info("Attempting to auto update " + ModInfo.READABLE_NAME); + + Files.createDirectories(file.getParentFile().toPath()); + WebDownloader.downloadAsFile(ModrinthGetter.getLatestDownloadForVersion(minecraftVersion), file); + + // Check if the checksum of the downloaded jar is correct (not required, but good to have to prevent corruption or interception) + if (!JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), file).equals(ModrinthGetter.getLatestShaForVersion(minecraftVersion))) + { + LOGGER.warn("DH update checksum failed, aborting install"); + throw new Exception("Checksum failed"); + } + + deleteOldOnClose = true; + + LOGGER.info(ModInfo.READABLE_NAME + " successfully updated. It will apply on game's relaunch"); + new Thread(() -> { + System.setProperty("java.awt.headless", "false"); // Required to make it work + JOptionPane.showMessageDialog(null, ModInfo.READABLE_NAME + " updated, this will be applied on game restart.", ModInfo.READABLE_NAME, JOptionPane.INFORMATION_MESSAGE); + }).start(); + return true; + } + catch (Exception e) + { + LOGGER.warn("Failed to update " + ModInfo.READABLE_NAME + " to version " + ModrinthGetter.getLatestNameForVersion(minecraftVersion)); + e.printStackTrace(); + return false; + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/wrapperInterfaces/config/LangWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/wrapperInterfaces/config/LangWrapper.java index 15e70d2ab..9ac82b8e7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/wrapperInterfaces/config/LangWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/wrapperInterfaces/config/LangWrapper.java @@ -10,35 +10,43 @@ import org.apache.logging.log4j.Logger; import java.util.Locale; -public class LangWrapper implements ILangWrapper { - public static final LangWrapper INSTANCE = new LangWrapper(); - private static final Config jsonObject = Config.inMemory(); - private static final Logger logger = LogManager.getLogger(LangWrapper.class.getSimpleName()); - - public static void init() { - try { +public class LangWrapper implements ILangWrapper +{ + public static final LangWrapper INSTANCE = new LangWrapper(); + private static final Config jsonObject = Config.inMemory(); + private static final Logger logger = LogManager.getLogger(LangWrapper.class.getSimpleName()); + + public static void init() + { + try + { // System.out.println(JarUtils.convertInputStreamToString(JarUtils.accessFile("assets/lod/lang/"+ Locale.getDefault().toString().toLowerCase()+".json")).replaceAll(":\\n.+?(?=\")",":")); - // FIXME: Is there something in the config that the parser cant read? - JsonFormat.fancyInstance().createParser().parse( - JarUtils.convertInputStreamToString(JarUtils.accessFile("assets/lod/lang/"+ Locale.getDefault().toString().toLowerCase()+".json")), - jsonObject, ParsingMode.REPLACE - ); - } catch (Exception e) { - logger.error("Failed to read lang file"); - e.printStackTrace(); - } - } - - @Override - public boolean langExists(String str) { - return jsonObject.get(str) != null; - } - - @Override - public String getLang(String str) { - if (jsonObject.get(str) != null) - return (String) jsonObject.get(str); - else - return str; - } + // FIXME: Is there something in the config that the parser cant read? + JsonFormat.fancyInstance().createParser().parse( + JarUtils.convertInputStreamToString(JarUtils.accessFile("assets/lod/lang/" + Locale.getDefault().toString().toLowerCase() + ".json")), + jsonObject, ParsingMode.REPLACE + ); + } + catch (Exception e) + { + logger.error("Failed to read lang file"); + e.printStackTrace(); + } + } + + @Override + public boolean langExists(String str) + { + return jsonObject.get(str) != null; + } + + @Override + public String getLang(String str) + { + if (jsonObject.get(str) != null) + return (String) jsonObject.get(str); + else + return str; + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index 35ac48794..5fbd2435e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -27,260 +27,266 @@ import java.io.Closeable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; -public class ClientLevelModule implements Closeable { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - private final IDhClientLevel parent; - public final AtomicReference ClientRenderStateRef = new AtomicReference<>(); - public final F3Screen.NestedMessage f3Message; - public ClientLevelModule(IDhClientLevel parent) - { - this.parent = parent; - this.f3Message = new F3Screen.NestedMessage(this::f3Log); - } - - //==============// - // tick methods // - //==============// - - private EDebugRendering lastDebugRendering = EDebugRendering.OFF; - - public void clientTick() - { - // can be false if the level is unloading - if (!MC_CLIENT.playerExists()) - { - return; - } +public class ClientLevelModule implements Closeable +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + private final IDhClientLevel parent; + public final AtomicReference ClientRenderStateRef = new AtomicReference<>(); + public final F3Screen.NestedMessage f3Message; + public ClientLevelModule(IDhClientLevel parent) + { + this.parent = parent; + this.f3Message = new F3Screen.NestedMessage(this::f3Log); + } + + //==============// + // tick methods // + //==============// + + private EDebugRendering lastDebugRendering = EDebugRendering.OFF; + + public void clientTick() + { + // can be false if the level is unloading + if (!MC_CLIENT.playerExists()) + { + return; + } - ClientRenderState clientRenderState = this.ClientRenderStateRef.get(); - if (clientRenderState == null) - { - return; - } - // TODO this should probably be handled via a config change listener - // recreate the RenderState if the render distance changes - if (clientRenderState.quadtree.blockRenderDistanceRadius != Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH) - { - if (!this.ClientRenderStateRef.compareAndSet(clientRenderState, null)) - { - return; - } - - clientRenderState.close(); - clientRenderState = new ClientRenderState(parent, parent.getFileHandler(), parent.getSaveStructure()); - if (!this.ClientRenderStateRef.compareAndSet(null, clientRenderState)) - { - //FIXME: How to handle this? - LOGGER.warn("Failed to set render state due to concurrency after changing view distance"); - clientRenderState.close(); - return; - } - } - clientRenderState.quadtree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos())); - - boolean isBuffersDirty = false; - EDebugRendering newDebugRendering = Config.Client.Advanced.Debugging.debugRendering.get(); - if (newDebugRendering != lastDebugRendering) - { - lastDebugRendering = newDebugRendering; - isBuffersDirty = true; - } - if (isBuffersDirty) { - clientRenderState.renderer.bufferHandler.MarkAllBuffersDirty(); - } - } - - - //========// - // render // - //========// - - /** @return if the {@link ClientRenderState} was successfully swapped */ - public boolean startRenderer() - { - ClientRenderState ClientRenderState = new ClientRenderState(parent, parent.getFileHandler(), parent.getSaveStructure()); - if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState)) - { - LOGGER.warn("Failed to start renderer due to concurrency"); - ClientRenderState.close(); - return false; - } - else - { - return true; - } - } - - public boolean isRendering() { - return this.ClientRenderStateRef.get() != null; - } - - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) - { - ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState == null) - { - // either the renderer hasn't been started yet, or is being reloaded - return; - } - ClientRenderState.renderer.drawLODs(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); - } - - public void stopRenderer() - { - LOGGER.info("Stopping renderer for "+this); - ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState == null) - { - LOGGER.warn("Tried to stop renderer for "+this+" when it was not started!"); - return; - } - // stop the render state - while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null)) // TODO why is there a while loop here? - { - ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState == null) - { - return; - } - } - ClientRenderState.close(); - } - - //===============// - // data handling // - //===============// - public void saveWrites(ChunkSizedFullDataAccessor data) - { - ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); - DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET); - if (ClientRenderState != null) - { - ClientRenderState.renderSourceFileHandler.writeChunkDataToFile(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data); - } - else - { - parent.getFileHandler().write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data); - } - } - - public CompletableFuture saveAsync() - { - ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState != null) - { - return ClientRenderState.renderSourceFileHandler.flushAndSaveAsync(); - } - else - { - return CompletableFuture.completedFuture(null); - } - } - - public void close() - { - // shutdown the renderer - ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState != null) - { - // TODO does this have to be in a while loop, if so why? - while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null)) - { - ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState == null) - { - break; - } - } - - if (ClientRenderState != null) - { - ClientRenderState.close(); - } - } - f3Message.close(); - } - - - - - //=======================// - // misc helper functions // - //=======================// - - public void dumpRamUsage() - { - //TODO - } - - /** Returns what should be displayed in Minecraft's F3 debug menu */ - protected String[] f3Log() - { - String dimName = parent.getClientLevelWrapper().getDimensionType().getDimensionName(); - ClientRenderState renderState = this.ClientRenderStateRef.get(); - if (renderState == null) - { - return new String[] { "level @ "+dimName+": Inactive" }; - } - else - { - return new String[] { "level @ "+dimName+": Active" }; - } - } - - public void clearRenderCache() - { - ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); - if (ClientRenderState != null && ClientRenderState.quadtree != null) - { - ClientRenderState.quadtree.clearRenderDataCache(); - } - } - - public void reloadPos(DhSectionPos pos) { - ClientRenderState clientRenderState = this.ClientRenderStateRef.get(); - if (clientRenderState != null && clientRenderState.quadtree != null) - { - clientRenderState.quadtree.reloadPos(pos); - } - } - - public static class ClientRenderState - { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - - public final ILevelWrapper levelWrapper; - public final LodQuadTree quadtree; - public final RenderSourceFileHandler renderSourceFileHandler; - public final LodRenderer renderer; - - public ClientRenderState(IDhClientLevel dhClientLevel, IFullDataSourceProvider fullDataSourceProvider, - AbstractSaveStructure saveStructure) - { - this.levelWrapper = dhClientLevel.getLevelWrapper(); - this.renderSourceFileHandler = new RenderSourceFileHandler(fullDataSourceProvider, dhClientLevel, saveStructure); - - this.quadtree = new LodQuadTree(dhClientLevel, Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH, - // initial position is (0,0) just in case the player hasn't loaded in yet, the tree will be moved once the level starts ticking - 0, 0, - this.renderSourceFileHandler); - - RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree); - this.renderer = new LodRenderer(renderBufferHandler); - } - - - - public void close() - { - LOGGER.info("Shutting down "+ ClientRenderState.class.getSimpleName()); - - this.renderer.close(); - this.quadtree.close(); - this.renderSourceFileHandler.close(); - } - - } + ClientRenderState clientRenderState = this.ClientRenderStateRef.get(); + if (clientRenderState == null) + { + return; + } + // TODO this should probably be handled via a config change listener + // recreate the RenderState if the render distance changes + if (clientRenderState.quadtree.blockRenderDistanceRadius != Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH) + { + if (!this.ClientRenderStateRef.compareAndSet(clientRenderState, null)) + { + return; + } + + clientRenderState.close(); + clientRenderState = new ClientRenderState(parent, parent.getFileHandler(), parent.getSaveStructure()); + if (!this.ClientRenderStateRef.compareAndSet(null, clientRenderState)) + { + //FIXME: How to handle this? + LOGGER.warn("Failed to set render state due to concurrency after changing view distance"); + clientRenderState.close(); + return; + } + } + clientRenderState.quadtree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos())); + + boolean isBuffersDirty = false; + EDebugRendering newDebugRendering = Config.Client.Advanced.Debugging.debugRendering.get(); + if (newDebugRendering != lastDebugRendering) + { + lastDebugRendering = newDebugRendering; + isBuffersDirty = true; + } + if (isBuffersDirty) + { + clientRenderState.renderer.bufferHandler.MarkAllBuffersDirty(); + } + } + + + //========// + // render // + //========// + + /** @return if the {@link ClientRenderState} was successfully swapped */ + public boolean startRenderer() + { + ClientRenderState ClientRenderState = new ClientRenderState(parent, parent.getFileHandler(), parent.getSaveStructure()); + if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState)) + { + LOGGER.warn("Failed to start renderer due to concurrency"); + ClientRenderState.close(); + return false; + } + else + { + return true; + } + } + + public boolean isRendering() + { + return this.ClientRenderStateRef.get() != null; + } + + public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + { + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState == null) + { + // either the renderer hasn't been started yet, or is being reloaded + return; + } + ClientRenderState.renderer.drawLODs(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + } + + public void stopRenderer() + { + LOGGER.info("Stopping renderer for " + this); + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState == null) + { + LOGGER.warn("Tried to stop renderer for " + this + " when it was not started!"); + return; + } + // stop the render state + while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null)) // TODO why is there a while loop here? + { + ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState == null) + { + return; + } + } + ClientRenderState.close(); + } + + //===============// + // data handling // + //===============// + public void saveWrites(ChunkSizedFullDataAccessor data) + { + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET); + if (ClientRenderState != null) + { + ClientRenderState.renderSourceFileHandler.writeChunkDataToFile(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data); + } + else + { + parent.getFileHandler().write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data); + } + } + + public CompletableFuture saveAsync() + { + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState != null) + { + return ClientRenderState.renderSourceFileHandler.flushAndSaveAsync(); + } + else + { + return CompletableFuture.completedFuture(null); + } + } + + public void close() + { + // shutdown the renderer + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState != null) + { + // TODO does this have to be in a while loop, if so why? + while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null)) + { + ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState == null) + { + break; + } + } + + if (ClientRenderState != null) + { + ClientRenderState.close(); + } + } + f3Message.close(); + } + + + + + //=======================// + // misc helper functions // + //=======================// + + public void dumpRamUsage() + { + //TODO + } + + /** Returns what should be displayed in Minecraft's F3 debug menu */ + protected String[] f3Log() + { + String dimName = parent.getClientLevelWrapper().getDimensionType().getDimensionName(); + ClientRenderState renderState = this.ClientRenderStateRef.get(); + if (renderState == null) + { + return new String[]{"level @ " + dimName + ": Inactive"}; + } + else + { + return new String[]{"level @ " + dimName + ": Active"}; + } + } + + public void clearRenderCache() + { + ClientRenderState ClientRenderState = this.ClientRenderStateRef.get(); + if (ClientRenderState != null && ClientRenderState.quadtree != null) + { + ClientRenderState.quadtree.clearRenderDataCache(); + } + } + + public void reloadPos(DhSectionPos pos) + { + ClientRenderState clientRenderState = this.ClientRenderStateRef.get(); + if (clientRenderState != null && clientRenderState.quadtree != null) + { + clientRenderState.quadtree.reloadPos(pos); + } + } + + public static class ClientRenderState + { + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + + public final ILevelWrapper levelWrapper; + public final LodQuadTree quadtree; + public final RenderSourceFileHandler renderSourceFileHandler; + public final LodRenderer renderer; + + public ClientRenderState( + IDhClientLevel dhClientLevel, IFullDataSourceProvider fullDataSourceProvider, + AbstractSaveStructure saveStructure) + { + this.levelWrapper = dhClientLevel.getLevelWrapper(); + this.renderSourceFileHandler = new RenderSourceFileHandler(fullDataSourceProvider, dhClientLevel, saveStructure); + + this.quadtree = new LodQuadTree(dhClientLevel, Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH, + // initial position is (0,0) just in case the player hasn't loaded in yet, the tree will be moved once the level starts ticking + 0, 0, + this.renderSourceFileHandler); + + RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree); + this.renderer = new LodRenderer(renderBufferHandler); + } + + + + public void close() + { + LOGGER.info("Shutting down " + ClientRenderState.class.getSimpleName()); + + this.renderer.close(); + this.quadtree.close(); + this.renderSourceFileHandler.close(); + } + + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 7dd641339..6c8cf45c3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -20,12 +20,12 @@ import java.util.concurrent.CompletableFuture; public class DhClientLevel extends DhLevel implements IDhClientLevel { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - + public final ClientLevelModule clientside; public final IClientLevelWrapper levelWrapper; public final AbstractSaveStructure saveStructure; public final RemoteFullDataFileHandler dataFileHandler; - + //=============// // constructor // //=============// @@ -37,9 +37,9 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel dataFileHandler = new RemoteFullDataFileHandler(this, saveStructure); clientside = new ClientLevelModule(this); clientside.startRenderer(); - LOGGER.info("Started DHLevel for "+this.levelWrapper+" with saves at "+this.saveStructure); + LOGGER.info("Started DHLevel for " + this.levelWrapper + " with saves at " + this.saveStructure); } - + //==============// // tick methods // //==============// @@ -50,12 +50,13 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel chunkToLodBuilder.tick(); clientside.clientTick(); } - + @Override - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) { + public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + { clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } - + //================// // level handling // //================// @@ -65,37 +66,40 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel @Override public IClientLevelWrapper getClientLevelWrapper() { return levelWrapper; } - + @Override - public void clearRenderCache() { + public void clearRenderCache() + { clientside.clearRenderCache(); } - + @Override public ILevelWrapper getLevelWrapper() { return levelWrapper; } - + @Override - public CompletableFuture saveAsync() { + public CompletableFuture saveAsync() + { return CompletableFuture.allOf(clientside.saveAsync(), dataFileHandler.flushAndSave()); } - + @Override - public void saveWrites(ChunkSizedFullDataAccessor data) { + public void saveWrites(ChunkSizedFullDataAccessor data) + { clientside.saveWrites(data); } - + @Override public int getMinY() { return levelWrapper.getMinHeight(); } - + @Override public void close() { clientside.close(); super.close(); dataFileHandler.close(); - LOGGER.info("Closed "+DhClientLevel.class.getSimpleName()+" for "+levelWrapper); + LOGGER.info("Closed " + DhClientLevel.class.getSimpleName() + " for " + levelWrapper); } - + //=======================// // misc helper functions // //=======================// @@ -107,13 +111,15 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel } @Override - public IFullDataSourceProvider getFileHandler() { + public IFullDataSourceProvider getFileHandler() + { return dataFileHandler; } - + @Override - public AbstractSaveStructure getSaveStructure() { + public AbstractSaveStructure getSaveStructure() + { return saveStructure; } - + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index ec96d5d0c..dbe06fbc0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -27,10 +27,10 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - + public final ServerLevelModule serverside; public final ClientLevelModule clientside; - + private final IServerLevelWrapper serverLevelWrapper; public IClientLevelWrapper clientLevelWrapper; @@ -43,9 +43,9 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS this.serverLevelWrapper = serverLevelWrapper; serverside = new ServerLevelModule(this, serverLevelWrapper, saveStructure); clientside = new ClientLevelModule(this); - LOGGER.info("Started "+DhClientServerLevel.class.getSimpleName()+" for "+ serverLevelWrapper +" with saves at "+saveStructure); + LOGGER.info("Started " + DhClientServerLevel.class.getSimpleName() + " for " + serverLevelWrapper + " with saves at " + saveStructure); } - + //==============// // tick methods // //==============// @@ -55,12 +55,13 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS { clientside.clientTick(); } - + @Override - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) { + public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) + { clientside.render(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); } - + @Override public void serverTick() { @@ -83,7 +84,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS // stop world gen serverside.stopWorldGen(); } - + if (serverside.isWorldGenRunning()) { ClientLevelModule.ClientRenderState renderState = clientside.ClientRenderStateRef.get(); @@ -94,7 +95,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS serverside.worldGenTick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos())); } } - + //========// // render // //========// @@ -109,7 +110,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS clientside.stopRenderer(); clientLevelWrapper = null; } - + //================// // level handling // //================// @@ -130,40 +131,45 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS @Override public IClientLevelWrapper getClientLevelWrapper() { return serverside.levelWrapper.tryGetClientLevelWrapper(); } - + @Override - public void clearRenderCache() { + public void clearRenderCache() + { clientside.clearRenderCache(); } - + @Override public IServerLevelWrapper getServerLevelWrapper() { return serverLevelWrapper; } @Override public ILevelWrapper getLevelWrapper() { return getServerLevelWrapper(); } - + @Override - public IFullDataSourceProvider getFileHandler() { + public IFullDataSourceProvider getFileHandler() + { return serverside.dataFileHandler; } - + @Override - public AbstractSaveStructure getSaveStructure() { + public AbstractSaveStructure getSaveStructure() + { return serverside.saveStructure; } - + @Override - public void saveWrites(ChunkSizedFullDataAccessor data) { + public void saveWrites(ChunkSizedFullDataAccessor data) + { clientside.saveWrites(data); } - + @Override public int getMinY() { return getLevelWrapper().getMinHeight(); } - + @Override - public CompletableFuture saveAsync() { + public CompletableFuture saveAsync() + { return CompletableFuture.allOf(clientside.saveAsync(), getFileHandler().flushAndSave()); } - + //===============// // data handling // //===============// @@ -174,24 +180,26 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS clientside.close(); super.close(); serverside.close(); - LOGGER.info("Closed "+this.getClass().getSimpleName()+" for "+this.getServerLevelWrapper()); + LOGGER.info("Closed " + this.getClass().getSimpleName() + " for " + this.getServerLevelWrapper()); } - - @Override + + @Override public void onWorldGenTaskComplete(DhSectionPos pos) { //if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) - DebugRenderer.makeParticle( - new DebugRenderer.BoxParticle( - new DebugRenderer.Box(pos, 128f, 156f, 0.09f, Color.red.darker()), - 0.2, 32f - ) - ); + DebugRenderer.makeParticle( + new DebugRenderer.BoxParticle( + new DebugRenderer.Box(pos, 128f, 156f, 0.09f, Color.red.darker()), + 0.2, 32f + ) + ); clientside.reloadPos(pos); } - + @Override - public void dumpRamUsage() { - + public void dumpRamUsage() + { + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java index 94af05afb..08fd32fd8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java @@ -8,42 +8,45 @@ import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import java.util.concurrent.CompletableFuture; -public abstract class DhLevel implements IDhLevel { - - public final ChunkToLodBuilder chunkToLodBuilder; - - protected DhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); } - - public abstract void saveWrites(ChunkSizedFullDataAccessor data); - - - @Override - public int getMinY() { - return 0; - } - - @Override - public void updateChunkAsync(IChunkWrapper chunk) - { - CompletableFuture future = this.chunkToLodBuilder.tryGenerateData(chunk); - if (future != null) - { - future.thenAccept((chunkSizedFullDataAccessor) -> +public abstract class DhLevel implements IDhLevel +{ + + public final ChunkToLodBuilder chunkToLodBuilder; + + protected DhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); } + + public abstract void saveWrites(ChunkSizedFullDataAccessor data); + + + @Override + public int getMinY() + { + return 0; + } + + @Override + public void updateChunkAsync(IChunkWrapper chunk) + { + CompletableFuture future = this.chunkToLodBuilder.tryGenerateData(chunk); + if (future != null) + { + future.thenAccept((chunkSizedFullDataAccessor) -> + { + if (chunkSizedFullDataAccessor == null) { - if (chunkSizedFullDataAccessor == null) { - // This can happen if, among other reasons, a chunk save is superceded by a later event - return; - } - - this.saveWrites(chunkSizedFullDataAccessor); - ApiEventInjector.INSTANCE.fireAllEvents( - DhApiChunkModifiedEvent.class, - new DhApiChunkModifiedEvent.EventParam(this.getLevelWrapper(), chunk.getChunkPos().x, chunk.getChunkPos().z)); - }); - } - } - - @Override - public void close() { this.chunkToLodBuilder.close(); } - + // This can happen if, among other reasons, a chunk save is superceded by a later event + return; + } + + this.saveWrites(chunkSizedFullDataAccessor); + ApiEventInjector.INSTANCE.fireAllEvents( + DhApiChunkModifiedEvent.class, + new DhApiChunkModifiedEvent.EventParam(this.getLevelWrapper(), chunk.getChunkPos().x, chunk.getChunkPos().z)); + }); + } + } + + @Override + public void close() { this.chunkToLodBuilder.close(); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 84826eb25..691193e95 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -19,7 +19,7 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public final ServerLevelModule serverside; private final IServerLevelWrapper serverLevelWrapper; - + public DhServerLevel(AbstractSaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper) { if (saveStructure.getFullDataFolder(serverLevelWrapper).mkdirs()) @@ -35,13 +35,14 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel { chunkToLodBuilder.tick(); } - + @Override - public void saveWrites(ChunkSizedFullDataAccessor data) { + public void saveWrites(ChunkSizedFullDataAccessor data) + { DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET); getFileHandler().write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data); } - + @Override public int getMinY() { return getLevelWrapper().getMinHeight(); } @@ -77,7 +78,7 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel // stop world gen serverside.stopWorldGen(); } - + if (serverside.isWorldGenRunning()) { serverside.worldGenTick(new DhBlockPos2D(0, 0)); // todo; @@ -92,14 +93,17 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel @Override public IFullDataSourceProvider getFileHandler() { return serverside.dataFileHandler; } - + @Override - public AbstractSaveStructure getSaveStructure() { + public AbstractSaveStructure getSaveStructure() + { return serverside.saveStructure; } - + @Override - public void onWorldGenTaskComplete(DhSectionPos pos) { + public void onWorldGenTaskComplete(DhSectionPos pos) + { //TODO: Send packet to client } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java index 3a55bd252..f7d71c392 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhClientLevel.java @@ -9,17 +9,18 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp public interface IDhClientLevel extends IDhLevel { - void clientTick(); + void clientTick(); - void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); + void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); - int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block); + int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block); + + IClientLevelWrapper getClientLevelWrapper(); + + /** + * Re-creates the color, render data. + * This method should be called after resource packs are changed or LOD settings are modified. + */ + void clearRenderCache(); - IClientLevelWrapper getClientLevelWrapper(); - - /** - * Re-creates the color, render data. - * This method should be called after resource packs are changed or LOD settings are modified. - */ - void clearRenderCache(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index dd980e252..688e7fe29 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -9,23 +9,23 @@ import java.util.concurrent.CompletableFuture; public interface IDhLevel extends AutoCloseable { - int getMinY(); - CompletableFuture saveAsync(); + int getMinY(); + CompletableFuture saveAsync(); - void dumpRamUsage(); + void dumpRamUsage(); - /** + /** * May return either a client or server level wrapper.
* Should not return null */ - ILevelWrapper getLevelWrapper(); + ILevelWrapper getLevelWrapper(); - void updateChunkAsync(IChunkWrapper chunk); + void updateChunkAsync(IChunkWrapper chunk); IFullDataSourceProvider getFileHandler(); - + AbstractSaveStructure getSaveStructure(); - - + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhServerLevel.java index 500c29eec..8ef80a7e5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhServerLevel.java @@ -5,9 +5,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapp public interface IDhServerLevel extends IDhLevel, GeneratedFullDataFileHandler.IOnWorldGenCompleteListener { - void serverTick(); - void doWorldGen(); + void serverTick(); + void doWorldGen(); - IServerLevelWrapper getServerLevelWrapper(); + IServerLevelWrapper getServerLevelWrapper(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IServerKeyedClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IServerKeyedClientLevel.java index 24577e59e..9452f0d23 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IServerKeyedClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IServerKeyedClientLevel.java @@ -5,7 +5,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp /** Enhances a {@link IClientLevelWrapper} with server provided level information. */ public interface IServerKeyedClientLevel extends IClientLevelWrapper { - /** Returns the level key, which is used to select the correct folder on the client. */ - String getServerLevelKey(); + /** Returns the level key, which is used to select the correct folder on the client. */ + String getServerLevelKey(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java index 168b0772a..4fa32e696 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java @@ -16,153 +16,157 @@ import org.apache.logging.log4j.Logger; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; -public class ServerLevelModule { - private static class WorldGenState - { - public final WorldGenerationQueue worldGenerationQueue; - WorldGenState(IDhServerLevel level) - { - IDhApiWorldGenerator worldGenerator = WorldGeneratorInjector.INSTANCE.get(level.getLevelWrapper()); - if (worldGenerator == null) - { - // no override generator is bound, use the Core world generator - worldGenerator = new BatchGenerator(level); - // binding the core generator won't prevent other mods from binding their own generators - // since core world generator's should have the lowest override priority - WorldGeneratorInjector.INSTANCE.bind(level.getLevelWrapper(), worldGenerator); - } - this.worldGenerationQueue = new WorldGenerationQueue(worldGenerator); - } - - CompletableFuture closeAsync(boolean doInterrupt) - { - return this.worldGenerationQueue.startClosing(true, doInterrupt) - .exceptionally(ex -> - { - LOGGER.error("Error closing generation queue", ex); - return null; - } - ).thenRun(this.worldGenerationQueue::close) - .exceptionally(ex -> - { - LOGGER.error("Error closing world gen", ex); - return null; - }); - } - - public void tick(DhBlockPos2D targetPosForGeneration) { - worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration); - } - } - - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public final IServerLevelWrapper levelWrapper; - public final IDhServerLevel parent; - public final AbstractSaveStructure saveStructure; - public final GeneratedFullDataFileHandler dataFileHandler; - public final AppliedConfigState worldGeneratorEnabledConfig; - private final AtomicReference worldGenStateRef = new AtomicReference<>(); - - public ServerLevelModule(IDhServerLevel parent, IServerLevelWrapper levelWrapper, AbstractSaveStructure saveStructure) - { - this.parent = parent; - this.levelWrapper = levelWrapper; - this.saveStructure = saveStructure; - this.dataFileHandler = new GeneratedFullDataFileHandler(parent, saveStructure); - this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Client.Advanced.WorldGenerator.enableDistantGeneration); - } - - //==============// - // tick methods // - //==============// - - - public void startWorldGen() - { - // create the new world generator - WorldGenState newWgs = new WorldGenState(parent); - if (!this.worldGenStateRef.compareAndSet(null, newWgs)) - { - LOGGER.warn("Failed to start world gen due to concurrency"); - newWgs.closeAsync(false); - } - dataFileHandler.addWorldGenCompleteListener(parent); - dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue); - } - - public void stopWorldGen() - { - WorldGenState worldGenState = this.worldGenStateRef.get(); - if (worldGenState == null) - { - LOGGER.warn("Attempted to stop world gen when it was not running"); - return; - } - - // shut down the world generator - while (!this.worldGenStateRef.compareAndSet(worldGenState, null)) - { - worldGenState = this.worldGenStateRef.get(); - if (worldGenState == null) - { - return; - } - } - dataFileHandler.clearGenerationQueue(); - worldGenState.closeAsync(true).join(); //TODO: Make it async. - dataFileHandler.removeWorldGenCompleteListener(parent); - } - - public boolean isWorldGenRunning() - { - return this.worldGenStateRef.get() != null; - } - - public void worldGenTick(DhBlockPos2D targetPosForGeneration) - { - WorldGenState worldGenState = this.worldGenStateRef.get(); - if (worldGenState != null) - { - // queue new world generation requests - worldGenState.tick(targetPosForGeneration); - } - } - - //===============// - // data handling // - //===============// - public void close() - { - // shutdown the world-gen - WorldGenState worldGenState = this.worldGenStateRef.get(); - if (worldGenState != null) - { - while (!this.worldGenStateRef.compareAndSet(worldGenState, null)) - { - worldGenState = this.worldGenStateRef.get(); - if (worldGenState == null) - { - break; - } - } - - if (worldGenState != null) - { - worldGenState.closeAsync(true).join(); //TODO: Make it async. - } - } - dataFileHandler.close(); - } - - - - - //=======================// - // misc helper functions // - //=======================// - - public void dumpRamUsage() - { - //TODO - } +public class ServerLevelModule +{ + private static class WorldGenState + { + public final WorldGenerationQueue worldGenerationQueue; + WorldGenState(IDhServerLevel level) + { + IDhApiWorldGenerator worldGenerator = WorldGeneratorInjector.INSTANCE.get(level.getLevelWrapper()); + if (worldGenerator == null) + { + // no override generator is bound, use the Core world generator + worldGenerator = new BatchGenerator(level); + // binding the core generator won't prevent other mods from binding their own generators + // since core world generator's should have the lowest override priority + WorldGeneratorInjector.INSTANCE.bind(level.getLevelWrapper(), worldGenerator); + } + this.worldGenerationQueue = new WorldGenerationQueue(worldGenerator); + } + + CompletableFuture closeAsync(boolean doInterrupt) + { + return this.worldGenerationQueue.startClosing(true, doInterrupt) + .exceptionally(ex -> + { + LOGGER.error("Error closing generation queue", ex); + return null; + } + ).thenRun(this.worldGenerationQueue::close) + .exceptionally(ex -> + { + LOGGER.error("Error closing world gen", ex); + return null; + }); + } + + public void tick(DhBlockPos2D targetPosForGeneration) + { + worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration); + } + + } + + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + public final IServerLevelWrapper levelWrapper; + public final IDhServerLevel parent; + public final AbstractSaveStructure saveStructure; + public final GeneratedFullDataFileHandler dataFileHandler; + public final AppliedConfigState worldGeneratorEnabledConfig; + private final AtomicReference worldGenStateRef = new AtomicReference<>(); + + public ServerLevelModule(IDhServerLevel parent, IServerLevelWrapper levelWrapper, AbstractSaveStructure saveStructure) + { + this.parent = parent; + this.levelWrapper = levelWrapper; + this.saveStructure = saveStructure; + this.dataFileHandler = new GeneratedFullDataFileHandler(parent, saveStructure); + this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Client.Advanced.WorldGenerator.enableDistantGeneration); + } + + //==============// + // tick methods // + //==============// + + + public void startWorldGen() + { + // create the new world generator + WorldGenState newWgs = new WorldGenState(parent); + if (!this.worldGenStateRef.compareAndSet(null, newWgs)) + { + LOGGER.warn("Failed to start world gen due to concurrency"); + newWgs.closeAsync(false); + } + dataFileHandler.addWorldGenCompleteListener(parent); + dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue); + } + + public void stopWorldGen() + { + WorldGenState worldGenState = this.worldGenStateRef.get(); + if (worldGenState == null) + { + LOGGER.warn("Attempted to stop world gen when it was not running"); + return; + } + + // shut down the world generator + while (!this.worldGenStateRef.compareAndSet(worldGenState, null)) + { + worldGenState = this.worldGenStateRef.get(); + if (worldGenState == null) + { + return; + } + } + dataFileHandler.clearGenerationQueue(); + worldGenState.closeAsync(true).join(); //TODO: Make it async. + dataFileHandler.removeWorldGenCompleteListener(parent); + } + + public boolean isWorldGenRunning() + { + return this.worldGenStateRef.get() != null; + } + + public void worldGenTick(DhBlockPos2D targetPosForGeneration) + { + WorldGenState worldGenState = this.worldGenStateRef.get(); + if (worldGenState != null) + { + // queue new world generation requests + worldGenState.tick(targetPosForGeneration); + } + } + + //===============// + // data handling // + //===============// + public void close() + { + // shutdown the world-gen + WorldGenState worldGenState = this.worldGenStateRef.get(); + if (worldGenState != null) + { + while (!this.worldGenStateRef.compareAndSet(worldGenState, null)) + { + worldGenState = this.worldGenStateRef.get(); + if (worldGenState == null) + { + break; + } + } + + if (worldGenState != null) + { + worldGenState.closeAsync(true).join(); //TODO: Make it async. + } + } + dataFileHandler.close(); + } + + + + + //=======================// + // misc helper functions // + //=======================// + + public void dumpRamUsage() + { + //TODO + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedLogger.java b/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedLogger.java index 8f52f8572..36a060b9a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedLogger.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedLogger.java @@ -135,4 +135,5 @@ public class ConfigBasedLogger { log(Level.TRACE, str, param); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedSpamLogger.java b/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedSpamLogger.java index 338033320..59216fbed 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedSpamLogger.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/logging/ConfigBasedSpamLogger.java @@ -202,4 +202,5 @@ public class ConfigBasedSpamLogger { logInc(Level.TRACE, str, param); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/logging/DhLoggerBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/logging/DhLoggerBuilder.java index 83a60d8ae..3587fce2a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/logging/DhLoggerBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/logging/DhLoggerBuilder.java @@ -43,14 +43,17 @@ public class DhLoggerBuilder { StackTraceElement[] stElements = Thread.currentThread().getStackTrace(); String callerClassName = "??"; - for (int i=1; i output); - @Override - public void close() { + @Override + public void close() + { boolean removed = SELF_UPDATE_MESSAGE_LIST.remove(this); } + } public static class StaticMessage extends Message @@ -65,6 +68,7 @@ public class F3Screen @Override public void printTo(List output) { output.addAll(Arrays.asList(this.lines)); } + } public static class DynamicMessage extends Message @@ -81,6 +85,7 @@ public class F3Screen list.add(message); } } + } public static class MultiDynamicMessage extends Message @@ -101,6 +106,7 @@ public class F3Screen } } } + } public static class NestedMessage extends Message @@ -120,6 +126,7 @@ public class F3Screen list.addAll(Arrays.asList(message)); } } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java index fd56c87fa..3c10d619d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java @@ -18,9 +18,9 @@ public abstract class NetworkEventSource implements AutoCloseable protected final MessageHandler messageHandler = new MessageHandler(); protected String closeReason = null; - - - + + + // public NetworkEventSource() // { // this.registerHandler(HelloMessage.class, (helloMessage, channelContext) -> diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/AckMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/AckMessage.java index b6d3a2811..8ca09f2c8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/AckMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/AckMessage.java @@ -10,13 +10,13 @@ import com.seibel.distanthorizons.core.network.protocol.MessageRegistry; */ public class AckMessage implements INetworkMessage { - public Class messageType; + public Class messageType; - public AckMessage() { } - public AckMessage(Class messageType) { this.messageType = messageType; } - + public AckMessage() { } + public AckMessage(Class messageType) { this.messageType = messageType; } + // @Override // public void encode(ByteBuf out) { out.writeInt(MessageRegistry.INSTANCE.getMessageId(this.messageType)); } // diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/CloseReasonMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/CloseReasonMessage.java index aa67d9bc9..b36b0ce5f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/CloseReasonMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/CloseReasonMessage.java @@ -12,7 +12,7 @@ public class CloseReasonMessage implements INetworkMessage public CloseReasonMessage() { } public CloseReasonMessage(String reason) { this.reason = reason; } - + // @Override // public void encode(ByteBuf out) { INetworkObject.encodeString(this.reason, out); } // diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/HelloMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/HelloMessage.java index d2e0a9ca9..62bd27a98 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/HelloMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/HelloMessage.java @@ -4,12 +4,12 @@ import com.seibel.distanthorizons.core.network.protocol.INetworkMessage; import com.seibel.distanthorizons.coreapi.ModInfo; //import io.netty.buffer.ByteBuf; -public class HelloMessage implements INetworkMessage +public class HelloMessage implements INetworkMessage { - public int version = ModInfo.PROTOCOL_VERSION; - - - + public int version = ModInfo.PROTOCOL_VERSION; + + + // @Override // public void encode(ByteBuf out) { out.writeInt(this.version); } // diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/PlayerUUIDMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/PlayerUUIDMessage.java index b29e8608b..4186f4470 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/PlayerUUIDMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/PlayerUUIDMessage.java @@ -7,13 +7,13 @@ import java.util.UUID; public class PlayerUUIDMessage implements INetworkMessage { - public UUID playerUUID; + public UUID playerUUID; - public PlayerUUIDMessage() { } - public PlayerUUIDMessage(UUID playerUUID) { this.playerUUID = playerUUID; } - + public PlayerUUIDMessage() { } + public PlayerUUIDMessage(UUID playerUUID) { this.playerUUID = playerUUID; } + // @Override // public void encode(ByteBuf out) // { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/RemotePlayerConfigMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/RemotePlayerConfigMessage.java index fb278e6f3..e219c6937 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/messages/RemotePlayerConfigMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/messages/RemotePlayerConfigMessage.java @@ -7,13 +7,13 @@ import com.seibel.distanthorizons.core.network.objects.RemotePlayer; public class RemotePlayerConfigMessage implements INetworkMessage { - public RemotePlayer.Payload payload; + public RemotePlayer.Payload payload; - public RemotePlayerConfigMessage() { } - public RemotePlayerConfigMessage(RemotePlayer.Payload payload) { this.payload = payload; } - + public RemotePlayerConfigMessage() { } + public RemotePlayerConfigMessage(RemotePlayer.Payload payload) { this.payload = payload; } + // @Override // public void encode(ByteBuf out) { this.payload.encode(out); } // diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/objects/RemotePlayer.java b/core/src/main/java/com/seibel/distanthorizons/core/network/objects/RemotePlayer.java index 2b2bf751d..ed719168a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/objects/RemotePlayer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/objects/RemotePlayer.java @@ -5,30 +5,30 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapp //import io.netty.buffer.ByteBuf; //import io.netty.channel.ChannelHandlerContext; -public class RemotePlayer +public class RemotePlayer { - public IServerPlayerWrapper serverPlayer; - public Payload payload; + public IServerPlayerWrapper serverPlayer; + public Payload payload; // public ChannelHandlerContext channelContext; - public RemotePlayer(IServerPlayerWrapper serverPlayer) { this.serverPlayer = serverPlayer; } + public RemotePlayer(IServerPlayerWrapper serverPlayer) { this.serverPlayer = serverPlayer; } - public static class Payload implements INetworkObject + public static class Payload implements INetworkObject { - // TODO Replace this example with useful fields, + // TODO Replace this example with useful fields, // this should include any information the server needs to know about the connected client - public int renderDistance; - - - + public int renderDistance; + + + // @Override // public void encode(ByteBuf out) { out.writeInt(this.renderDistance); } // // @Override // public void decode(ByteBuf in) { this.renderDistance = in.readInt(); } - } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/EMessageHandlerSide.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/EMessageHandlerSide.java index 6b8f6d760..f3076577c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/EMessageHandlerSide.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/EMessageHandlerSide.java @@ -6,6 +6,6 @@ package com.seibel.distanthorizons.core.network.protocol; */ public enum EMessageHandlerSide { - CLIENT, - SERVER + CLIENT, + SERVER } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/INetworkMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/INetworkMessage.java index 270baef88..d66c81ec1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/INetworkMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/INetworkMessage.java @@ -3,6 +3,6 @@ package com.seibel.distanthorizons.core.network.protocol; /** For now this is only used for constraining listeners */ public interface INetworkMessage extends INetworkObject { - + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/MessageRegistry.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/MessageRegistry.java index ea952c4ad..c9d2499e0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/MessageRegistry.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/MessageRegistry.java @@ -10,14 +10,14 @@ import java.util.function.Supplier; public class MessageRegistry { - public static final MessageRegistry INSTANCE = new MessageRegistry(); + public static final MessageRegistry INSTANCE = new MessageRegistry(); - private final Map> idToSupplier = new HashMap<>(); - private final BiMap, Integer> classToId = HashBiMap.create(); + private final Map> idToSupplier = new HashMap<>(); + private final BiMap, Integer> classToId = HashBiMap.create(); - private MessageRegistry() + private MessageRegistry() { // Note: Messages must have parameterless constructors @@ -34,16 +34,16 @@ public class MessageRegistry - public void registerMessage(Class clazz, Supplier supplier) + public void registerMessage(Class clazz, Supplier supplier) { - int id = this.idToSupplier.size() + 1; + int id = this.idToSupplier.size() + 1; this.idToSupplier.put(id, supplier); this.classToId.put(clazz, id); - } + } - public Class getMessageClassById(int messageId) { return this.classToId.inverse().get(messageId); } + public Class getMessageClassById(int messageId) { return this.classToId.inverse().get(messageId); } - public INetworkMessage createMessage(int messageId) throws IllegalArgumentException + public INetworkMessage createMessage(int messageId) throws IllegalArgumentException { try { @@ -55,8 +55,8 @@ public class MessageRegistry } } - public int getMessageId(INetworkMessage message) { return this.getMessageId(message.getClass()); } + public int getMessageId(INetworkMessage message) { return this.getMessageId(message.getClass()); } - public int getMessageId(Class messageClass) { return this.classToId.get(messageClass); } + public int getMessageId(Class messageClass) { return this.classToId.get(messageClass); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java index 52fe4fe77..6be986456 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkChannelInitializer.java @@ -4,17 +4,18 @@ package com.seibel.distanthorizons.core.network.protocol; //import io.netty.channel.socket.SocketChannel; //import io.netty.handler.codec.LengthFieldBasedFrameDecoder; //import io.netty.handler.codec.LengthFieldPrepender; + import org.jetbrains.annotations.NotNull; /** used when creating a network channel */ public class NetworkChannelInitializer //extends ChannelInitializer { - private final MessageHandler messageHandler; + private final MessageHandler messageHandler; - public NetworkChannelInitializer(MessageHandler messageHandler) { this.messageHandler = messageHandler; } - + public NetworkChannelInitializer(MessageHandler messageHandler) { this.messageHandler = messageHandler; } + // @Override // public void initChannel(@NotNull SocketChannel socketChannel) // { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkExceptionHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkExceptionHandler.java index 5b44e44da..a52d7b699 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkExceptionHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/protocol/NetworkExceptionHandler.java @@ -7,8 +7,8 @@ import org.apache.logging.log4j.Logger; public class NetworkExceptionHandler //extends ChannelInboundHandlerAdapter { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + // @Override // public void exceptionCaught(ChannelHandlerContext channelContext, Throwable cause) // { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java index a60618e12..666a37267 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.pos; import com.seibel.distanthorizons.core.enums.EDhDirection; @@ -24,97 +24,112 @@ import com.seibel.distanthorizons.core.util.LodUtil; import java.util.Objects; -public class DhBlockPos { - public static final boolean DO_CHECKS = false; - - // 26 bits wide as that just encompasses the maximum possible value - // of +- 30,000,000 blocks in each direction. Yes this packing method - // is how Minecraft packs it. - - // NOTE: Remember to ALWAYS check that DHBlockPos packing is EXACTLY - // the same as Minecraft's!!!! - public static final int PACKED_X_LENGTH = 26; - public static final int PACKED_Z_LENGTH = 26; - public static final int PACKED_Y_LENGTH = 12; - public static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L; - public static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L; - public static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L; - public static final int PACKED_Y_OFFSET = 0; - public static final int PACKED_Z_OFFSET = PACKED_Y_LENGTH; - public static final int PACKED_X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH; - - public final int x; - public final int y; - public final int z; - - public DhBlockPos(int x, int y, int z) { - this.x = x; - this.y = y; - this.z = z; - } - public DhBlockPos() { - this(0, 0, 0); - } - public DhBlockPos(DhBlockPos pos) { - this(pos.x, pos.y, pos.z); - } - - public DhBlockPos(DhBlockPos2D pos, int y) { - this(pos.x, y, pos.z); - } - - @Deprecated - public int getX() - { - return x; - } - @Deprecated - public int getY() - { - return y; - } - @Deprecated - public int getZ() - { - return z; - } - - public static long asLong(int x, int y, int z) { - if (DO_CHECKS) { - if ((x & ~PACKED_X_MASK) != 0) { - throw new IllegalArgumentException("x is out of range: " + x); - } - if ((y & ~PACKED_Y_MASK) != 0) { - throw new IllegalArgumentException("y is out of range: " + y); - } - if ((z & ~PACKED_Z_MASK) != 0) { - throw new IllegalArgumentException("z is out of range: " + z); - } - } - return ((long)x & PACKED_X_MASK) << PACKED_X_OFFSET | - ((long)y & PACKED_Y_MASK) << PACKED_Y_OFFSET | - ((long)z & PACKED_Z_MASK) << PACKED_Z_OFFSET; - } - - public static int getX(long packed) { // X is at the top - return (int)(packed <<(64 - PACKED_X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)); - } - public static int getY(long packed) { // Y is at the bottom - return (int)(packed <<(64 - PACKED_Y_OFFSET - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)); - } - public static int getZ(long packed) { // Z is at the middle - return (int)(packed <<(64 - PACKED_Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)); - } - public DhBlockPos(long packed) { - this(getX(packed), getY(packed), getZ(packed)); - } - - public long asLong() { - return asLong(x, y, z); - } - - public DhBlockPos offset(EDhDirection direction) { return this.offset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z); } - public DhBlockPos offset(int x, int y, int z) { return new DhBlockPos(this.x + x, this.y + y, this.z + z); } +public class DhBlockPos +{ + public static final boolean DO_CHECKS = false; + + // 26 bits wide as that just encompasses the maximum possible value + // of +- 30,000,000 blocks in each direction. Yes this packing method + // is how Minecraft packs it. + + // NOTE: Remember to ALWAYS check that DHBlockPos packing is EXACTLY + // the same as Minecraft's!!!! + public static final int PACKED_X_LENGTH = 26; + public static final int PACKED_Z_LENGTH = 26; + public static final int PACKED_Y_LENGTH = 12; + public static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L; + public static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L; + public static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L; + public static final int PACKED_Y_OFFSET = 0; + public static final int PACKED_Z_OFFSET = PACKED_Y_LENGTH; + public static final int PACKED_X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH; + + public final int x; + public final int y; + public final int z; + + public DhBlockPos(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + public DhBlockPos() + { + this(0, 0, 0); + } + public DhBlockPos(DhBlockPos pos) + { + this(pos.x, pos.y, pos.z); + } + + public DhBlockPos(DhBlockPos2D pos, int y) + { + this(pos.x, y, pos.z); + } + + @Deprecated + public int getX() + { + return x; + } + @Deprecated + public int getY() + { + return y; + } + @Deprecated + public int getZ() + { + return z; + } + + public static long asLong(int x, int y, int z) + { + if (DO_CHECKS) + { + if ((x & ~PACKED_X_MASK) != 0) + { + throw new IllegalArgumentException("x is out of range: " + x); + } + if ((y & ~PACKED_Y_MASK) != 0) + { + throw new IllegalArgumentException("y is out of range: " + y); + } + if ((z & ~PACKED_Z_MASK) != 0) + { + throw new IllegalArgumentException("z is out of range: " + z); + } + } + return ((long) x & PACKED_X_MASK) << PACKED_X_OFFSET | + ((long) y & PACKED_Y_MASK) << PACKED_Y_OFFSET | + ((long) z & PACKED_Z_MASK) << PACKED_Z_OFFSET; + } + + public static int getX(long packed) + { // X is at the top + return (int) (packed << (64 - PACKED_X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)); + } + public static int getY(long packed) + { // Y is at the bottom + return (int) (packed << (64 - PACKED_Y_OFFSET - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)); + } + public static int getZ(long packed) + { // Z is at the middle + return (int) (packed << (64 - PACKED_Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)); + } + public DhBlockPos(long packed) + { + this(getX(packed), getY(packed), getZ(packed)); + } + + public long asLong() + { + return asLong(x, y, z); + } + + public DhBlockPos offset(EDhDirection direction) { return this.offset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z); } + public DhBlockPos offset(int x, int y, int z) { return new DhBlockPos(this.x + x, this.y + y, this.z + z); } /** Limits the block position to a value between 0 and 15 (inclusive) */ public DhBlockPos convertToChunkRelativePos() @@ -133,45 +148,52 @@ public class DhBlockPos { /** * Can be used to quickly determine the rough distance between two points
- * or determine the taxi cab (manhattan) distance between two points.

+ * or determine the taxi cab (manhattan) distance between two points.

* - * Manhattan distance is equivalent to determining the distance between two street intersections, + * Manhattan distance is equivalent to determining the distance between two street intersections, * where you can only drive along each street, instead of directly to the other point. */ - public int getManhattanDistance(DhBlockPos otherPos) - { - return Math.abs(this.getX() - otherPos.getX()) + Math.abs(this.getY() - otherPos.getY()) + Math.abs(this.getZ() - otherPos.getZ()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DhBlockPos that = (DhBlockPos) o; - return x == that.x && y == that.y && z == that.z; - } - - @Override - public int hashCode() { - return Objects.hash(x, y, z); - } - @Override - public String toString() { - return "DHBlockPos[" + - "" + x + - ", " + y + - ", " + z + - ']'; - } - - public static void _DebugCheckPacker(int x, int y, int z, long expected) { - long packed = asLong(x, y, z); - if (packed != expected) { - throw new IllegalArgumentException("Packed values don't match: " + packed + " != " + expected); - } - DhBlockPos pos = new DhBlockPos(packed); - if (pos.getX() != x || pos.getY() != y || pos.getZ() != z) { - throw new IllegalArgumentException("Values after decode don't match: " + pos + " != " + x + ", " + y + ", " + z); - } - } + public int getManhattanDistance(DhBlockPos otherPos) + { + return Math.abs(this.getX() - otherPos.getX()) + Math.abs(this.getY() - otherPos.getY()) + Math.abs(this.getZ() - otherPos.getZ()); + } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DhBlockPos that = (DhBlockPos) o; + return x == that.x && y == that.y && z == that.z; + } + + @Override + public int hashCode() + { + return Objects.hash(x, y, z); + } + @Override + public String toString() + { + return "DHBlockPos[" + + "" + x + + ", " + y + + ", " + z + + ']'; + } + + public static void _DebugCheckPacker(int x, int y, int z, long expected) + { + long packed = asLong(x, y, z); + if (packed != expected) + { + throw new IllegalArgumentException("Packed values don't match: " + packed + " != " + expected); + } + DhBlockPos pos = new DhBlockPos(packed); + if (pos.getX() != x || pos.getY() != y || pos.getZ() != z) + { + throw new IllegalArgumentException("Values after decode don't match: " + pos + " != " + x + ", " + y + ", " + z); + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java index 7cd3efdda..8cb9ec35d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java @@ -2,62 +2,77 @@ package com.seibel.distanthorizons.core.pos; import com.seibel.distanthorizons.coreapi.util.MathUtil; -public class DhBlockPos2D { - public static final DhBlockPos2D ZERO = new DhBlockPos2D(0, 0); - public final int x; - public final int z; - public DhBlockPos2D(int x, int z) { - this.x = x; - this.z = z; - } - - public DhBlockPos2D(DhBlockPos blockPos) { - this.x = blockPos.x; - this.z = blockPos.z; - } - - public DhBlockPos2D add(DhBlockPos2D other) { - return new DhBlockPos2D(x + other.x, z + other.z); - } - - public DhBlockPos2D add(int offsetX, int offsetZ) { - return new DhBlockPos2D(x + offsetX, z + offsetZ); - } - - public DhBlockPos2D subtract(DhBlockPos2D other) { - return new DhBlockPos2D(x - other.x, z - other.z); - } - public double dist(DhBlockPos2D other) { - return Math.sqrt(Math.pow(x - other.x, 2) + Math.pow(z - other.z, 2)); - } - public long distSquared(DhBlockPos2D other) { - return MathUtil.pow2((long)x - other.x) + MathUtil.pow2((long)z - other.z); - } - - public Pos2D toPos2D() { - return new Pos2D(x, z); - } - - public static DhBlockPos2D fromPos2D(Pos2D pos) { - return new DhBlockPos2D(pos.x, pos.y); - } - - @Override - public String toString() { - return "(" + x + ", " + z + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof DhBlockPos2D) { - DhBlockPos2D other = (DhBlockPos2D)obj; - return x == other.x && z == other.z; - } - return false; - } - - @Override - public int hashCode() { - return Integer.hashCode(x) ^ Integer.hashCode(z); - } +public class DhBlockPos2D +{ + public static final DhBlockPos2D ZERO = new DhBlockPos2D(0, 0); + public final int x; + public final int z; + public DhBlockPos2D(int x, int z) + { + this.x = x; + this.z = z; + } + + public DhBlockPos2D(DhBlockPos blockPos) + { + this.x = blockPos.x; + this.z = blockPos.z; + } + + public DhBlockPos2D add(DhBlockPos2D other) + { + return new DhBlockPos2D(x + other.x, z + other.z); + } + + public DhBlockPos2D add(int offsetX, int offsetZ) + { + return new DhBlockPos2D(x + offsetX, z + offsetZ); + } + + public DhBlockPos2D subtract(DhBlockPos2D other) + { + return new DhBlockPos2D(x - other.x, z - other.z); + } + public double dist(DhBlockPos2D other) + { + return Math.sqrt(Math.pow(x - other.x, 2) + Math.pow(z - other.z, 2)); + } + public long distSquared(DhBlockPos2D other) + { + return MathUtil.pow2((long) x - other.x) + MathUtil.pow2((long) z - other.z); + } + + public Pos2D toPos2D() + { + return new Pos2D(x, z); + } + + public static DhBlockPos2D fromPos2D(Pos2D pos) + { + return new DhBlockPos2D(pos.x, pos.y); + } + + @Override + public String toString() + { + return "(" + x + ", " + z + ")"; + } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof DhBlockPos2D) + { + DhBlockPos2D other = (DhBlockPos2D) obj; + return x == other.x && z == other.z; + } + return false; + } + + @Override + public int hashCode() + { + return Integer.hashCode(x) ^ Integer.hashCode(z); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java index af74609b8..b8d12ea55 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java @@ -16,63 +16,63 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.pos; import java.util.Objects; public class DhChunkPos { - public final int x; // Low 32 bits - public final int z; // High 32 bits + public final int x; // Low 32 bits + public final int z; // High 32 bits /** cached to improve hashing speed */ public final int hashCode; - public DhChunkPos(int x, int z) + public DhChunkPos(int x, int z) { - this.x = x; - this.z = z; + this.x = x; + this.z = z; // custom hash, 7309 is a random prime this.hashCode = this.x * 7309 + this.z; - } - public DhChunkPos(DhBlockPos blockPos) + } + public DhChunkPos(DhBlockPos blockPos) { // >> 4 is the Same as div 16 this(blockPos.x >> 4, blockPos.z >> 4); - } - public DhChunkPos(DhBlockPos2D blockPos) + } + public DhChunkPos(DhBlockPos2D blockPos) { // >> 4 is the Same as div 16 this(blockPos.x >> 4, blockPos.z >> 4); - } + } public DhChunkPos(long packed) { this(getX(packed), getZ(packed)); } public DhBlockPos center() { return new DhBlockPos(8 + x << 4, 0, 8 + z << 4); } - public DhBlockPos corner() { return new DhBlockPos(x << 4, 0, z << 4); } - - public static long toLong(int x, int z) { return ((long)x & 0xFFFFFFFFL) << 32 | (long)z & 0xFFFFFFFFL; } - - public static int getX(long chunkPos) { return (int)(chunkPos >> 32); } - public static int getZ(long chunkPos) { return (int)(chunkPos & 0xFFFFFFFFL); } - - @Deprecated - public int getX() { return x; } - @Deprecated - public int getZ() { return z; } - - public int getMinBlockX() { return x << 4; } - public int getMinBlockZ() { return z << 4; } - - public DhBlockPos2D getMinBlockPos() { return new DhBlockPos2D(x<<4, z<<4); } - - public long getLong() { return toLong(x, z); } - - @Override + public DhBlockPos corner() { return new DhBlockPos(x << 4, 0, z << 4); } + + public static long toLong(int x, int z) { return ((long) x & 0xFFFFFFFFL) << 32 | (long) z & 0xFFFFFFFFL; } + + public static int getX(long chunkPos) { return (int) (chunkPos >> 32); } + public static int getZ(long chunkPos) { return (int) (chunkPos & 0xFFFFFFFFL); } + + @Deprecated + public int getX() { return x; } + @Deprecated + public int getZ() { return z; } + + public int getMinBlockX() { return x << 4; } + public int getMinBlockZ() { return z << 4; } + + public DhBlockPos2D getMinBlockPos() { return new DhBlockPos2D(x << 4, z << 4); } + + public long getLong() { return toLong(x, z); } + + @Override public boolean equals(Object obj) { if (this == obj) @@ -86,36 +86,36 @@ public class DhChunkPos else { DhChunkPos that = (DhChunkPos) obj; - return x == that.x && z == that.z; + return x == that.x && z == that.z; } } - - @Override - public int hashCode() { return this.hashCode; } - - @Override - public String toString() { return "C["+x+","+z+"]"; } + + @Override + public int hashCode() { return this.hashCode; } + + @Override + public String toString() { return "C[" + x + "," + z + "]"; } //=======================// // static helper methods // //=======================// - - public static void _DebugCheckPacker(int x, int z, long expected) + + public static void _DebugCheckPacker(int x, int z, long expected) { - long packed = toLong(x, z); + long packed = toLong(x, z); if (packed != expected) { - throw new IllegalArgumentException("Packed values don't match: "+packed+" != "+expected); + throw new IllegalArgumentException("Packed values don't match: " + packed + " != " + expected); } DhChunkPos pos = new DhChunkPos(packed); if (pos.x != x || pos.z != z) { - throw new IllegalArgumentException("Values after decode don't match: "+pos+" != "+x+", "+z); + throw new IllegalArgumentException("Values after decode don't match: " + pos + " != " + x + ", " + z); } - } + } /** @return true if testPos is within the area defined by the min and max positions. */ public static boolean isChunkPosBetween(DhChunkPos minChunkPos, DhChunkPos testPos, DhChunkPos maxChunkPos) @@ -127,7 +127,7 @@ public class DhChunkPos int maxChunkZ = Math.max(minChunkPos.z, maxChunkPos.z); return minChunkX <= testPos.x && testPos.x <= maxChunkX && - minChunkZ <= testPos.z && testPos.z <= maxChunkZ; + minChunkZ <= testPos.z && testPos.z <= maxChunkZ; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java index e1a21d547..0e103f52b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java @@ -9,7 +9,7 @@ import java.util.Objects; /** * A MC world position that is relative to a given detail level. - * + * * @author Leetom * @version 2022-11-6 */ @@ -37,12 +37,12 @@ public class DhLodPos implements Comparable // getters // //=========// - public DhLodUnit getX() { return new DhLodUnit(this.detailLevel, this.x); } - public DhLodUnit getZ() { return new DhLodUnit(this.detailLevel, this.z); } - + public DhLodUnit getX() { return new DhLodUnit(this.detailLevel, this.x); } + public DhLodUnit getZ() { return new DhLodUnit(this.detailLevel, this.z); } + // Get the width of this pos, measured in the mc block unit. (i.e. detail 0) - public int getBlockWidth() { return this.getWidthAtDetail((byte)0); } - + public int getBlockWidth() { return this.getWidthAtDetail((byte) 0); } + // Get the width of this pos, measured in the target detail level. public int getWidthAtDetail(byte targetLevel) { @@ -50,8 +50,8 @@ public class DhLodPos implements Comparable return BitShiftUtil.powerOfTwo(this.detailLevel - targetLevel); } - public DhBlockPos2D getCenterBlockPos() - { + public DhBlockPos2D getCenterBlockPos() + { return new DhBlockPos2D( this.getX().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()), this.getZ().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth())); @@ -63,19 +63,19 @@ public class DhLodPos implements Comparable { LodUtil.assertTrue(newDetail <= this.detailLevel); return new DhLodPos(newDetail, - this.x * BitShiftUtil.powerOfTwo(this.detailLevel - newDetail), + this.x * BitShiftUtil.powerOfTwo(this.detailLevel - newDetail), this.z * BitShiftUtil.powerOfTwo(this.detailLevel - newDetail)); } /** * Returns the DhLodPos 1 detail level lower

- * + * * Relative child positions returned for each index:
* 0 = (0,0)
* 1 = (1,0)
* 2 = (0,1)
* 3 = (1,1)
- * + * * @param child0to3 must be an int between 0 and 3 */ public DhLodPos getChildPosByIndex(int child0to3) throws IllegalArgumentException, IllegalStateException @@ -94,11 +94,11 @@ public class DhLodPos implements Comparable /** @see DhLodPos#getSectionPosWithSectionDetailLevel(byte) */ public DhLodPos getDhSectionRelativePositionForDetailLevel() throws IllegalArgumentException { return this.getDhSectionRelativePositionForDetailLevel(this.detailLevel); } - /** + /** * Returns a DhLodPos with the given detail level and an X/Z position somewhere between (0,0) and (63,63). * This is done to access specific sections from a {@link IFullDataSource} where LOD columns are stored * in 64 x 64 blocks. - * + * * @throws IllegalArgumentException if this position's detail level is lower than the output detail level */ public DhLodPos getDhSectionRelativePositionForDetailLevel(byte outputDetailLevel) throws IllegalArgumentException @@ -131,9 +131,9 @@ public class DhLodPos implements Comparable return new DhLodPos(outputDetailLevel, xRelativePos, zRelativePos); } - /** + /** * @param sectionDetailLevel This is different from the normal LOD Detail level, see {@link DhSectionPos} for more information - * @throws IllegalArgumentException if this position's detail level is lower than the output detail level + * @throws IllegalArgumentException if this position's detail level is lower than the output detail level */ public DhSectionPos getSectionPosWithSectionDetailLevel(byte sectionDetailLevel) throws IllegalArgumentException { @@ -194,7 +194,7 @@ public class DhLodPos implements Comparable if (width.detailLevel < this.detailLevel) throw new IllegalArgumentException("add called with width.detailLevel < pos detail"); - return new DhLodPos(this.detailLevel, + return new DhLodPos(this.detailLevel, this.x + width.createFromDetailLevel(this.detailLevel).numberOfLodSectionsWide, this.z + width.createFromDetailLevel(this.detailLevel).numberOfLodSectionsWide); } @@ -222,15 +222,15 @@ public class DhLodPos implements Comparable else { DhLodPos otherPos = (DhLodPos) obj; - return this.detailLevel == otherPos.detailLevel && this.x == otherPos.x && this.z == otherPos.z; + return this.detailLevel == otherPos.detailLevel && this.x == otherPos.x && this.z == otherPos.z; } } - @Override + @Override public int hashCode() { return Objects.hash(this.detailLevel, this.x, this.z); } - @Override - public int compareTo(@NotNull DhLodPos obj) + @Override + public int compareTo(@NotNull DhLodPos obj) { if (this.detailLevel != obj.detailLevel) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodUnit.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodUnit.java index b47d94186..e2f5642ce 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodUnit.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodUnit.java @@ -11,27 +11,27 @@ import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; public class DhLodUnit { /** The detail level of this LOD Unit */ - public final byte detailLevel; + public final byte detailLevel; /** How many LOD columns wide this LOD Unit represents */ - public final int numberOfLodSectionsWide; + public final int numberOfLodSectionsWide; - public DhLodUnit(byte detailLevel, int numberOfLodSectionsWide) + public DhLodUnit(byte detailLevel, int numberOfLodSectionsWide) { - this.detailLevel = detailLevel; - this.numberOfLodSectionsWide = numberOfLodSectionsWide; - } + this.detailLevel = detailLevel; + this.numberOfLodSectionsWide = numberOfLodSectionsWide; + } /** @return the size of this LOD unit in Minecraft blocks */ - public int toBlockWidth() { return BitShiftUtil.pow(this.numberOfLodSectionsWide, this.detailLevel); } + public int toBlockWidth() { return BitShiftUtil.pow(this.numberOfLodSectionsWide, this.detailLevel); } /** @return the LOD Unit relative to the given block width and detail level */ - public static DhLodUnit fromBlockWidth(int blockWidth, byte targetDetailLevel) { return new DhLodUnit(targetDetailLevel, Math.floorDiv(blockWidth, BitShiftUtil.powerOfTwo(targetDetailLevel))); } + public static DhLodUnit fromBlockWidth(int blockWidth, byte targetDetailLevel) { return new DhLodUnit(targetDetailLevel, Math.floorDiv(blockWidth, BitShiftUtil.powerOfTwo(targetDetailLevel))); } - /** - * if the targetDetailLevel and this object's detail are the same, - * this will be returned instead of creating a new object + /** + * if the targetDetailLevel and this object's detail are the same, + * this will be returned instead of creating a new object */ public DhLodUnit createFromDetailLevel(byte targetDetailLevel) { @@ -47,7 +47,7 @@ public class DhLodUnit } else { - return new DhLodUnit(targetDetailLevel, Math.floorDiv(this.numberOfLodSectionsWide, BitShiftUtil.powerOfTwo(targetDetailLevel - this.detailLevel))); + return new DhLodUnit(targetDetailLevel, Math.floorDiv(this.numberOfLodSectionsWide, BitShiftUtil.powerOfTwo(targetDetailLevel - this.detailLevel))); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java index 2edf44678..2351fea8b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java @@ -9,26 +9,26 @@ import java.util.function.Consumer; /** * The position object used to define LOD objects in the quad trees.

- * + * * A section contains 64 x 64 LOD columns at a given quality. * The Section detail level is different from the LOD detail level. * For the specifics of how they compare can be viewed in the constants {@link #SECTION_BLOCK_DETAIL_LEVEL}, * {@link #SECTION_CHUNK_DETAIL_LEVEL}, and {@link #SECTION_REGION_DETAIL_LEVEL}).

- * + * * Why does the smallest render section represent 2x2 MC chunks (section detail level 6)?
- * A section defines what unit the quad tree works in, because of that we don't want that unit to be too big or too small.
+ * A section defines what unit the quad tree works in, because of that we don't want that unit to be too big or too small.
* Too small, and we'll have 1,000s of sections running around, all needing individual files and render buffers.
* Too big, and the LOD dropoff will be very noticeable.
* With those thoughts in mind we decided on a smallest section size of 32 data points square (IE 2x2 chunks). - * + * * @author Leetom * @version 2022-11-6 */ public class DhSectionPos { - /** + /** * The lowest detail level a Section position can hold. - * This section DetailLevel holds 64 x 64 Block level (detail level 0) LODs. + * This section DetailLevel holds 64 x 64 Block level (detail level 0) LODs. */ public final static byte SECTION_MINIMUM_DETAIL_LEVEL = 6; @@ -84,8 +84,8 @@ public class DhSectionPos this.sectionX = dhLodPos.x; this.sectionZ = dhLodPos.z; } - - + + /** Returns the center for the highest detail level (0) */ public DhLodPos getCenter() { return this.getCenter((byte) 0); } // TODO why does this use detail level 0 instead of this object's detail level? public DhLodPos getCenter(byte returnDetailLevel) @@ -100,7 +100,7 @@ public class DhSectionPos byte detailLevelOffset = (byte) (this.sectionDetailLevel - returnDetailLevel); // we can't get the center of the position at block level, only attempt to get the position offset for detail levels above 0 // TODO should this also apply to detail level 1 or is it fine? - int positionOffset = 0; + int positionOffset = 0; if (this.sectionDetailLevel != 1 || returnDetailLevel != 0) { positionOffset = BitShiftUtil.powerOfTwo(detailLevelOffset - 1); @@ -123,7 +123,7 @@ public class DhSectionPos this.sectionZ * BitShiftUtil.powerOfTwo(offset)); } - public DhLodUnit getWidth() { return this.getWidth(this.sectionDetailLevel); } + public DhLodUnit getWidth() { return this.getWidth(this.sectionDetailLevel); } public DhLodUnit getWidth(byte returnDetailLevel) { LodUtil.assertTrue(returnDetailLevel <= this.sectionDetailLevel, "returnDetailLevel must be less than sectionDetail"); @@ -131,8 +131,9 @@ public class DhSectionPos return new DhLodUnit(this.sectionDetailLevel, BitShiftUtil.powerOfTwo(offset)); } - /** - * uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels + /** + * uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels + * * @return the new position closest to negative infinity with the new detail level */ public DhSectionPos convertToDetailLevel(byte newSectionDetailLevel) @@ -177,7 +178,7 @@ public class DhSectionPos callback.accept(this.getChildByIndex(i)); } } - + /** Applies the given consumer to all children of the position at the given section detail level. */ public void forEachChildAtLevel(byte sectionDetailLevel, Consumer callback) { @@ -221,14 +222,15 @@ public class DhSectionPos /** Serialize() is different from toString() as it must NEVER be changed, and should be in a short format */ public String serialize() { return "[" + this.sectionDetailLevel + ',' + this.sectionX + ',' + this.sectionZ + ']'; } - + @Nullable - public static DhSectionPos deserialize(String value) { + public static DhSectionPos deserialize(String value) + { if (value.charAt(0) != '[' || value.charAt(value.length() - 1) != ']') return null; String[] split = value.substring(1, value.length() - 1).split(","); if (split.length != 3) return null; return new DhSectionPos(Byte.parseByte(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])); - + } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/Pos2D.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/Pos2D.java index 369107829..485228474 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/Pos2D.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/Pos2D.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.pos; import com.seibel.distanthorizons.coreapi.util.MathUtil; @@ -47,9 +47,9 @@ public class Pos2D public double dist(Pos2D other) { return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2)); } public long distSquared(Pos2D other) { return MathUtil.pow2((long) this.x - other.x) + MathUtil.pow2((long) this.y - other.y); } - /** - * Returns the maximum distance along either the X or Z axis

- * + /** + * Returns the maximum distance along either the X or Z axis

+ * * Example chebyshev distance between X and every point around it:
* * 2 2 2 2 2
@@ -58,14 +58,14 @@ public class Pos2D * 2 1 1 1 2
* 2 2 2 2 2
*
- * */ + */ public int chebyshevDist(Pos2D other) { return Math.max(Math.abs(this.x - other.x), Math.abs(this.y - other.y)); } /** * Can be used to quickly determine the rough distance between two points
- * or determine the taxi cab (manhattan) distance between two points.

- * - * Manhattan distance is equivalent to determining the distance between two street intersections, + * or determine the taxi cab (manhattan) distance between two points.

+ * + * Manhattan distance is equivalent to determining the distance between two street intersections, * where you can only drive along each street, instead of directly to the other point. */ public int manhattanDist(Pos2D other) { return Math.abs(this.x - other.x) + Math.abs(this.y - other.y); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java index a96f22cfd..a12b92260 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/AbstractRenderBuffer.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.core.util.LodUtil; @@ -28,13 +28,13 @@ public abstract class AbstractRenderBuffer implements AutoCloseable // ====================================================================== // ====================== Methods for implementations =================== // ====================================================================== - + // ========== Called by render thread ========== /** @return true if something was rendered, false otherwise */ public abstract boolean renderOpaque(LodRenderer renderContext); /** @return true if something was rendered, false otherwise */ public abstract boolean renderTransparent(LodRenderer renderContext); - + // ========== Called by any thread. (thread safe) ========== /* Called by anyone. This method is allowed to throw exceptions, but @@ -49,13 +49,13 @@ public abstract class AbstractRenderBuffer implements AutoCloseable * thread), or by others when the object is not being used. (not in build, * upload, or render state). */ public abstract void close(); - - - + + + public static final int DEFAULT_MEMORY_ALLOCATION = (LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 3) * 8; public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; public static final int MAX_QUADS_PER_BUFFER = (1024 * 1024 * 1) / QUADS_BYTE_SIZE; public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE; - - + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java index 5369f2645..03cfe56a5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/DhApiRenderProxy.java @@ -9,7 +9,7 @@ import com.seibel.distanthorizons.core.world.AbstractDhWorld; /** * Used to interact with Distant Horizons' rendering systems. - * + * * @author James Seibel * @version 2023-2-8 */ @@ -19,7 +19,7 @@ public class DhApiRenderProxy implements IDhApiRenderProxy - private DhApiRenderProxy() { } + private DhApiRenderProxy() { } @@ -29,7 +29,7 @@ public class DhApiRenderProxy implements IDhApiRenderProxy AbstractDhWorld world = SharedApi.getAbstractDhWorld(); if (world == null) { - return DhApiResult.createFail("No world loaded"); + return DhApiResult.createFail("No world loaded"); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java index d2636d04b..6bf058f38 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java @@ -25,14 +25,14 @@ import java.util.concurrent.locks.ReentrantLock; */ public class LodQuadTree extends QuadTree implements AutoCloseable { - public static final byte TREE_LOWEST_DETAIL_LEVEL = ColumnRenderSource.SECTION_SIZE_OFFSET; + public static final byte TREE_LOWEST_DETAIL_LEVEL = ColumnRenderSource.SECTION_SIZE_OFFSET; private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public final int blockRenderDistanceRadius; - private final ILodRenderSourceProvider renderSourceProvider; + public final int blockRenderDistanceRadius; + private final ILodRenderSourceProvider renderSourceProvider; - /** + /** * This holds every {@link DhSectionPos} that should be reloaded next tick.
* This is a {@link ConcurrentLinkedQueue} because new sections can be added to this list via the world generator threads. */ @@ -55,18 +55,18 @@ public class LodQuadTree extends QuadTree implements AutoClose //==============// public LodQuadTree( - IDhClientLevel level, int viewDistanceInBlocks, - int initialPlayerBlockX, int initialPlayerBlockZ, + IDhClientLevel level, int viewDistanceInBlocks, + int initialPlayerBlockX, int initialPlayerBlockZ, ILodRenderSourceProvider provider) { super(viewDistanceInBlocks, new DhBlockPos2D(initialPlayerBlockX, initialPlayerBlockZ), TREE_LOWEST_DETAIL_LEVEL); - this.level = level; + this.level = level; this.renderSourceProvider = provider; - this.blockRenderDistanceRadius = viewDistanceInBlocks; + this.blockRenderDistanceRadius = viewDistanceInBlocks; this.horizontalScaleChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality, (newHorizontalScale) -> this.onHorizontalQualityChange()); - } + } @@ -74,11 +74,12 @@ public class LodQuadTree extends QuadTree implements AutoClose // tick update // //=============// - /** - * This function updates the quadTree based on the playerPos and the current game configs (static and global) - * @param playerPos the reference position for the player - */ - public void tick(DhBlockPos2D playerPos) + /** + * This function updates the quadTree based on the playerPos and the current game configs (static and global) + * + * @param playerPos the reference position for the player + */ + public void tick(DhBlockPos2D playerPos) { if (this.level == null) { @@ -132,11 +133,11 @@ public class LodQuadTree extends QuadTree implements AutoClose } catch (IndexOutOfBoundsException e) { /* the section is now out of bounds, it doesn't need to be reloaded */ } - + pos = pos.getParentPos(); } } - + // walk through each root node Iterator rootPosIterator = this.rootNodePosIterator(); while (rootPosIterator.hasNext()) @@ -189,7 +190,7 @@ public class LodQuadTree extends QuadTree implements AutoClose // handle enabling, loading, // // and disabling render sections // //===============================// - + // byte expectedDetailLevel = 6; // can be used instead of the following logic for testing byte expectedDetailLevel = this.calculateExpectedDetailLevel(playerPos, sectionPos); expectedDetailLevel += DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL; @@ -211,7 +212,7 @@ public class LodQuadTree extends QuadTree implements AutoClose boolean childSectionLoaded = this.recursivelyUpdateRenderSectionNode(playerPos, rootNode, childNode, childPos, canThisPosRender || parentRenderSectionIsEnabled); allChildrenSectionsAreLoaded = childSectionLoaded && allChildrenSectionsAreLoaded; } - + if (!allChildrenSectionsAreLoaded) { // not all child positions are loaded yet, or this section is out of render range @@ -239,13 +240,13 @@ public class LodQuadTree extends QuadTree implements AutoClose // surprisingly reloadPos() doesn't appear to be the culprit, maybe there is an issue with reloading/changing the full data source? //LOGGER.warn("Potential QuadTree concurrency issue. All child sections should be enabled and ready to render for pos: "+sectionPos); } - + // this section is now being rendered via its children return true; } } // TODO this should only equal the expected detail level, the (expectedDetailLevel-1) is a temporary fix to prevent corners from being cut out - else if (sectionPos.sectionDetailLevel == expectedDetailLevel || sectionPos.sectionDetailLevel == expectedDetailLevel-1) + else if (sectionPos.sectionDetailLevel == expectedDetailLevel || sectionPos.sectionDetailLevel == expectedDetailLevel - 1) { // this is the detail level we want to render // // prepare this section for rendering @@ -274,7 +275,7 @@ public class LodQuadTree extends QuadTree implements AutoClose } else { - throw new IllegalStateException("LodQuadTree shouldn't be updating renderSections below the expected detail level: ["+expectedDetailLevel+"]."); + throw new IllegalStateException("LodQuadTree shouldn't be updating renderSections below the expected detail level: [" + expectedDetailLevel + "]."); } } @@ -287,6 +288,7 @@ public class LodQuadTree extends QuadTree implements AutoClose /** * This method will compute the detail level based on player position and section pos * Override this method if you want to use a different algorithm + * * @param playerPos player position as a reference for calculating the detail level * @param sectionPos section position * @return detail level of this section pos @@ -301,7 +303,7 @@ public class LodQuadTree extends QuadTree implements AutoClose } - double maxDetailDistance = this.getDrawDistanceFromDetail(Byte.MAX_VALUE -1); + double maxDetailDistance = this.getDrawDistanceFromDetail(Byte.MAX_VALUE - 1); if (distance > maxDetailDistance) { return Byte.MAX_VALUE - 1; @@ -341,8 +343,8 @@ public class LodQuadTree extends QuadTree implements AutoClose // render data // //=============// - /** - * Re-creates the color, render data. + /** + * Re-creates the color, render data. * This method should be called after resource packs are changed or LOD settings are modified. */ public void clearRenderDataCache() @@ -382,7 +384,7 @@ public class LodQuadTree extends QuadTree implements AutoClose } } - /** + /** * Can be called whenever a render section's data needs to be refreshed.
* This should be called whenever a world generation task is completed or if the connected server has new data to show. */ @@ -416,10 +418,10 @@ public class LodQuadTree extends QuadTree implements AutoClose // base methods // //==============// - @Override + @Override public void close() { - LOGGER.info("Shutting down "+ LodQuadTree.class.getSimpleName()+"..."); + LOGGER.info("Shutting down " + LodQuadTree.class.getSimpleName() + "..."); this.horizontalScaleChangeListener.close(); @@ -434,7 +436,7 @@ public class LodQuadTree extends QuadTree implements AutoClose } } - LOGGER.info("Finished shutting down "+ LodQuadTree.class.getSimpleName()); + LOGGER.info("Finished shutting down " + LodQuadTree.class.getSimpleName()); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index a5c05de82..b743a07e7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -31,21 +31,21 @@ public class LodRenderSection implements IDebugRenderable private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public final DhSectionPos pos; + public final DhSectionPos pos; private boolean isRenderingEnabled = false; - /** - * If this is true, then {@link LodRenderSection#reload(ILodRenderSourceProvider)} was called while + /** + * If this is true, then {@link LodRenderSection#reload(ILodRenderSourceProvider)} was called while * a {@link ILodRenderSourceProvider} was already being loaded. */ private boolean reloadRenderSourceOnceLoaded = false; - + private ILodRenderSourceProvider renderSourceProvider = null; - private CompletableFuture renderSourceLoadFuture; + private CompletableFuture renderSourceLoadFuture; private ColumnRenderSource renderSource; - + private IDhClientLevel level = null; - + //FIXME: Temp Hack to prevent swapping buffers too quickly private long lastNs = -1; private long lastSwapLocalVersion = -1; @@ -54,14 +54,14 @@ public class LodRenderSection implements IDebugRenderable private static final long SWAP_TIMEOUT_IN_NS = 2_000000000L; /** 1 sec */ private static final long SWAP_BUSY_COLLISION_TIMEOUT_IN_NS = 1_000000000L; - + private CompletableFuture buildRenderBufferFuture = null; private final Reference inactiveRenderBufferRef = new Reference<>(); - + /** a reference is used so the render buffer can be swapped to and from the buffer builder */ public final AtomicReference activeRenderBufferRef = new AtomicReference<>(); private volatile boolean disposeActiveBuffer = false; - + private final QuadTree parentQuadTree; @@ -70,29 +70,30 @@ public class LodRenderSection implements IDebugRenderable // constructor // //=============// - public LodRenderSection(QuadTree parentQuadTree, DhSectionPos pos) - { + public LodRenderSection(QuadTree parentQuadTree, DhSectionPos pos) + { this.pos = pos; this.parentQuadTree = parentQuadTree; - + DebugRenderer.register(this); } - + public void debugRender(DebugRenderer debugRenderer) { Color color = Color.red; - + if (this.renderSourceProvider == null) color = Color.black; - + if (this.renderSourceLoadFuture != null) color = Color.yellow; - - if (renderSource != null) { + + if (renderSource != null) + { color = Color.blue; if (buildRenderBufferFuture != null) color = Color.magenta; if (canRenderNow()) color = Color.cyan; if (canRenderNow() && isRenderingEnabled) color = Color.green; } - + debugRenderer.renderBox(new DebugRenderer.Box(this.pos, 400, 8f, Objects.hashCode(this), 0.1f, color)); } @@ -102,7 +103,7 @@ public class LodRenderSection implements IDebugRenderable // rendering // //===========// - public void enableRendering() + public void enableRendering() { // FIXME this is a temporary fix for sections not building the first time, // this may cause LODs to flash when first loading @@ -134,7 +135,7 @@ public class LodRenderSection implements IDebugRenderable this.level = level; if (this.renderSourceProvider == null) { - LOGGER.warn("LodRenderSection ["+this.pos+"] called loadRenderSource with a empty source provider"); + LOGGER.warn("LodRenderSection [" + this.pos + "] called loadRenderSource with a empty source provider"); return; } // don't re-load or double load the render source @@ -146,7 +147,7 @@ public class LodRenderSection implements IDebugRenderable this.startLoadRenderSourceAsync(); } - public void reload(ILodRenderSourceProvider renderDataProvider) + public void reload(ILodRenderSourceProvider renderDataProvider) { // debug rendering if (this.pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) @@ -163,7 +164,7 @@ public class LodRenderSection implements IDebugRenderable this.renderSourceProvider = renderDataProvider; if (this.renderSourceProvider == null) { - LOGGER.warn("LodRenderSection ["+this.pos+"] called reload with a empty source provider"); + LOGGER.warn("LodRenderSection [" + this.pos + "] called reload with a empty source provider"); return; } @@ -199,17 +200,17 @@ public class LodRenderSection implements IDebugRenderable this.renderSourceLoadFuture = null; }); } - + //========================// // getters and properties // //========================// - - /** This can return true before the render data is loaded */ - public boolean isRenderingEnabled() { return this.isRenderingEnabled; } - public ColumnRenderSource getRenderSource() { return this.renderSource; } + /** This can return true before the render data is loaded */ + public boolean isRenderingEnabled() { return this.isRenderingEnabled; } + + public ColumnRenderSource getRenderSource() { return this.renderSource; } public boolean canRenderNow() { @@ -222,19 +223,19 @@ public class LodRenderSection implements IDebugRenderable return this.renderSource != null && ( - ( - // if true; either this section represents empty chunks or un-generated chunks. - // Either way, there isn't any data to render, but this should be considered "loaded" - this.renderSource.isEmpty() - ) - || - ( - // check if the buffers have been loaded - this.activeRenderBufferRef.get() != null - ) + ( + // if true; either this section represents empty chunks or un-generated chunks. + // Either way, there isn't any data to render, but this should be considered "loaded" + this.renderSource.isEmpty() + ) + || + ( + // check if the buffers have been loaded + this.activeRenderBufferRef.get() != null + ) ); } - + //================// // Render Methods // //================// @@ -268,7 +269,7 @@ public class LodRenderSection implements IDebugRenderable return adjacentRenderSections; } - + private void tellNeighborsUpdated() { LodRenderSection[] adjacentRenderSections = this.getNeighbors(); @@ -280,25 +281,26 @@ public class LodRenderSection implements IDebugRenderable } } } - + /** @return true if this section is loaded and set to render */ public boolean canBuildBuffer() { return this.renderSource != null && this.buildRenderBufferFuture == null && !this.renderSource.isEmpty() && this.isBufferOutdated(); } private boolean isBufferOutdated() { return this.neighborUpdated || (this.renderSource.localVersion.get() - this.lastSwapLocalVersion) > 0; } /** @return true if this section is loaded and set to render */ public boolean canSwapBuffer() { return this.buildRenderBufferFuture != null && this.buildRenderBufferFuture.isDone(); } - - - + + + /** * Try and swap in new render buffer for this section. Note that before this call, there should be no other * places storing or referencing the render buffer. + * * @return True if the swap was successful. False if swap is not needed or if it is in progress. */ public boolean tryBuildAndSwapBuffer() { // delete the existing buffer if it should be disposed - if (this.disposeActiveBuffer && this.activeRenderBufferRef.get() != null) + if (this.disposeActiveBuffer && this.activeRenderBufferRef.get() != null) { this.disposeActiveBuffer = false; this.activeRenderBufferRef.getAndSet(null).close(); @@ -314,10 +316,10 @@ public class LodRenderSection implements IDebugRenderable if (this.pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) { DebugRenderer.makeParticle( - new DebugRenderer.BoxParticle( - new DebugRenderer.Box(this.pos, 32f, 64f, 0.2f, Color.yellow), - 0.5, 16f - ) + new DebugRenderer.BoxParticle( + new DebugRenderer.Box(this.pos, 32f, 64f, 0.2f, Color.yellow), + 0.5, 16f + ) ); } @@ -332,7 +334,7 @@ public class LodRenderSection implements IDebugRenderable LodRenderSection[] adjacentRenderSections = this.getNeighbors(); - ColumnRenderSource[] adjacentSources = new ColumnRenderSource[EDhDirection.ADJ_DIRECTIONS.length]; + ColumnRenderSource[] adjacentSources = new ColumnRenderSource[EDhDirection.ADJ_DIRECTIONS.length]; for (int i = 0; i < EDhDirection.ADJ_DIRECTIONS.length; i++) { LodRenderSection adj = adjacentRenderSections[i]; @@ -347,7 +349,7 @@ public class LodRenderSection implements IDebugRenderable // attempt to swap in the buffer - if (this.canSwapBuffer()) + if (this.canSwapBuffer()) { this.lastNs = System.nanoTime(); ColumnRenderBuffer newBuffer; @@ -361,7 +363,7 @@ public class LodRenderSection implements IDebugRenderable return false; } - LodUtil.assertTrue(newBuffer.buffersUploaded, "The buffer future for "+this.pos+" returned an un-built buffer."); + LodUtil.assertTrue(newBuffer.buffersUploaded, "The buffer future for " + this.pos + " returned an un-built buffer."); ColumnRenderBuffer oldBuffer = this.activeRenderBufferRef.getAndSet(newBuffer); if (oldBuffer != null) { @@ -397,16 +399,16 @@ public class LodRenderSection implements IDebugRenderable // base methods // //==============// - public String toString() - { - return "LodRenderSection{" + - "pos=" + this.pos + - ", lodRenderSource=" + this.renderSource + - ", loadFuture=" + this.renderSourceLoadFuture + - ", isRenderEnabled=" + this.isRenderingEnabled + - '}'; - } - + public String toString() + { + return "LodRenderSection{" + + "pos=" + this.pos + + ", lodRenderSource=" + this.renderSource + + ", loadFuture=" + this.renderSourceLoadFuture + + ", isRenderEnabled=" + this.isRenderingEnabled + + '}'; + } + public void dispose() { this.disposeRenderData(); @@ -416,7 +418,7 @@ public class LodRenderSection implements IDebugRenderable this.activeRenderBufferRef.get().close(); } } - + public synchronized void disposeRenderData() // synchronized is a band-aid solution to prevent a rare bug where the future isn't canceled in the right order { this.disposeRenderBuffer(); @@ -427,13 +429,13 @@ public class LodRenderSection implements IDebugRenderable this.renderSourceLoadFuture = null; } } - + public void disposeRenderBuffer() { this.cancelBuildBuffer(); this.disposeActiveBuffer = true; } - + public void markBufferDirty() { this.lastSwapLocalVersion = -1; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 6a4f063dd..cfa5ce0f9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -15,8 +15,8 @@ import java.util.Iterator; import java.util.ListIterator; import java.util.concurrent.atomic.AtomicBoolean; -/** - * This object tells the {@link LodRenderer} what buffers to render +/** + * This object tells the {@link LodRenderer} what buffers to render * TODO rename this class, maybe RenderBufferOrganizer or something more specific? */ public class RenderBufferHandler @@ -28,10 +28,10 @@ public class RenderBufferHandler // TODO: Make sorting go into the update loop instead of the render loop as it doesn't need to be done every frame private SortedArraySet loadedNearToFarBuffers = null; - + private final AtomicBoolean rebuildAllBuffers = new AtomicBoolean(false); - - + + public RenderBufferHandler(LodQuadTree lodQuadTree) { this.lodQuadTree = lodQuadTree; } @@ -98,20 +98,21 @@ public class RenderBufferHandler axisDirections[2] = xDir; } } - + Pos2D cPos = lodQuadTree.getCenterBlockPos().toPos2D(); - + // Now that we have the axis directions, we can sort the render list Comparator farToNearComparator = (loadedBufferA, loadedBufferB) -> { Pos2D aPos = loadedBufferA.pos.getCenter().getCenterBlockPos().toPos2D(); Pos2D bPos = loadedBufferB.pos.getCenter().getCenterBlockPos().toPos2D(); - if (true) { + if (true) + { int aManhattanDistance = aPos.manhattanDist(cPos); int bManhattanDistance = bPos.manhattanDist(cPos); return bManhattanDistance - aManhattanDistance; } - + for (EDhDirection axisDirection : axisDirections) { if (axisDirection.getAxis().isVertical()) @@ -146,7 +147,7 @@ public class RenderBufferHandler // Build the sorted list this.loadedNearToFarBuffers = new SortedArraySet<>((a, b) -> -farToNearComparator.compare(a, b)); // TODO is the comparator named wrong? - + // Update the sections boolean rebuildAllBuffers = this.rebuildAllBuffers.getAndSet(false); Iterator> nodeIterator = this.lodQuadTree.nodeIterator(); @@ -158,7 +159,7 @@ public class RenderBufferHandler LodRenderSection renderSection = node.value; try { - + if (renderSection != null) { if (rebuildAllBuffers) @@ -166,7 +167,7 @@ public class RenderBufferHandler renderSection.markBufferDirty(); } renderSection.tryBuildAndSwapBuffer(); - + if (renderSection.isRenderingEnabled()) { AbstractRenderBuffer buffer = renderSection.activeRenderBufferRef.get(); @@ -179,18 +180,18 @@ public class RenderBufferHandler } catch (Exception e) { - LOGGER.error("Error updating QuadTree render source at "+renderSection.pos+".", e); + LOGGER.error("Error updating QuadTree render source at " + renderSection.pos + ".", e); renderSection.markBufferDirty(); } } } - public void renderOpaque(LodRenderer renderContext) + public void renderOpaque(LodRenderer renderContext) { //TODO: Directional culling this.loadedNearToFarBuffers.forEach(loadedBuffer -> loadedBuffer.buffer.renderOpaque(renderContext)); } - public void renderTransparent(LodRenderer renderContext) + public void renderTransparent(LodRenderer renderContext) { //TODO: Directional culling ListIterator iter = this.loadedNearToFarBuffers.listIterator(this.loadedNearToFarBuffers.size()); @@ -200,14 +201,14 @@ public class RenderBufferHandler loadedBuffer.buffer.renderTransparent(renderContext); } } - + public void MarkAllBuffersDirty() { rebuildAllBuffers.set(true); } - - public void close() + + public void close() { Iterator> nodeIterator = this.lodQuadTree.nodeIterator(); while (nodeIterator.hasNext()) @@ -236,6 +237,7 @@ public class RenderBufferHandler this.buffer = buffer; this.pos = pos; } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/FogSettings.java b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/FogSettings.java index a5051dae6..2c9544f02 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/FogSettings.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/FogSettings.java @@ -30,10 +30,10 @@ import java.util.Objects; */ public class FogSettings { - /** a FogSetting object with 0 for every value */ - public static final FogSettings EMPTY = new FogSettings(0, 0, 0, 0,0, EFogFalloff.LINEAR); - - + /** a FogSetting object with 0 for every value */ + public static final FogSettings EMPTY = new FogSettings(0, 0, 0, 0, 0, EFogFalloff.LINEAR); + + public final double start; public final double end; public final double min; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java index ae94ca2d9..de38029f5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java @@ -53,16 +53,16 @@ public class LodFogConfig public final float heightFogHeight; final boolean drawNearFog; - + // TODO: Move these out of here public final int earthCurveRatio; - + // Noise Values public final boolean noiseEnable; public final int noiseSteps; public final float noiseIntensity; public final int noiseDropoff; - + public static LodFogConfig generateFogConfig() { @@ -79,13 +79,13 @@ public class LodFogConfig { // TODO: Move these out of here earthCurveRatio = Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get(); - + noiseEnable = Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseEnabled.get(); noiseSteps = Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseSteps.get(); noiseIntensity = Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseIntensity.get().floatValue(); noiseDropoff = Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseDropoff.get(); - - + + if (fogDrawMode != EFogDrawMode.FOG_DISABLED) { EFogDistance fogDistance = Config.Client.Advanced.Graphics.Fog.distance.get(); @@ -125,7 +125,7 @@ public class LodFogConfig Config.Client.Advanced.Graphics.Fog.AdvancedFog.HeightFog.heightFogDensity.get(), Config.Client.Advanced.Graphics.Fog.AdvancedFog.HeightFog.heightFogFalloff.get() ); - + heightFogMode = Config.Client.Advanced.Graphics.Fog.AdvancedFog.HeightFog.heightFogMode.get(); if (heightFogMode.basedOnCamera) @@ -190,65 +190,65 @@ public class LodFogConfig // Generate method: float getNearFogThickness(float dist); str.append("" + - "float getNearFogThickness(float dist) \n" + - "{ \n" + - " return linearFog(dist, nearFogStart, nearFogLength, 0.0, 1.0); \n" + - "} \n"); + "float getNearFogThickness(float dist) \n" + + "{ \n" + + " return linearFog(dist, nearFogStart, nearFogLength, 0.0, 1.0); \n" + + "} \n"); if (farFogSetting == null) { str.append("\n" + - "float getFarFogThickness(float dist) { return 0.0; } \n" + - "float getHeightFogThickness(float dist) { return 0.0; } \n" + - "float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) { return 0.0; } \n" + - "float calculateHeightFogDepth(float vertical, float realY) { return 0.0; } \n" + - "float mixFogThickness(float near, float far, float height) \n" + - "{ \n" + + "float getFarFogThickness(float dist) { return 0.0; } \n" + + "float getHeightFogThickness(float dist) { return 0.0; } \n" + + "float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) { return 0.0; } \n" + + "float calculateHeightFogDepth(float vertical, float realY) { return 0.0; } \n" + + "float mixFogThickness(float near, float far, float height) \n" + + "{ \n" + (drawNearFog ? "return 1.0-near;" : "return 0.0;") + - "} \n\n"); + "} \n\n"); } else { // Generate method: float getFarFogThickness(float dist); str.append("" + - "float getFarFogThickness(float dist) \n" + - "{ \n" + + "float getFarFogThickness(float dist) \n" + + "{ \n" + getFarFogMethod(farFogSetting.fogType) + "\n" + - "} \n"); + "} \n"); // Generate method: float getHeightFogThickness(float dist); str.append("" + - "float getHeightFogThickness(float dist) \n" + - "{ \n"+ + "float getHeightFogThickness(float dist) \n" + + "{ \n" + (heightFogSetting != null ? getHeightFogMethod(heightFogSetting.fogType) : " return 0.0;") + "\n" + - "} \n"); + "} \n"); // Generate method: float calculateHeightFogDepth(float vertical, float realY); str.append("" + - "float calculateHeightFogDepth(float vertical, float realY) \n" + - "{ \n" + + "float calculateHeightFogDepth(float vertical, float realY) \n" + + "{ \n" + (heightFogSetting != null ? getHeightDepthMethod(heightFogMode, heightFogHeight) : " return 0.0;") + "\n" + - "} \n"); + "} \n"); // Generate method: calculateFarFogDepth(float horizontal, float dist, float nearFogStart); str.append("" + - "float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) \n" + - "{ \n" + - " return " + (heightFogMixMode == EHeightFogMixMode.BASIC ? - "(dist - nearFogStart)/(1.0 - nearFogStart);" : - "(horizontal - nearFogStart)/(1.0 - nearFogStart);") + - "} \n"); + "float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) \n" + + "{ \n" + + " return " + (heightFogMixMode == EHeightFogMixMode.BASIC ? + "(dist - nearFogStart)/(1.0 - nearFogStart);" : + "(horizontal - nearFogStart)/(1.0 - nearFogStart);") + + "} \n"); // Generate method: float mixFogThickness(float near, float far, float height); str.append("" + - "float mixFogThickness(float near, float far, float height) \n" + - "{ \n" + + "float mixFogThickness(float near, float far, float height) \n" + + "{ \n" + getMixFogLine(heightFogMixMode, drawNearFog) + "\n" + - "} \n"); + "} \n"); } } @@ -269,18 +269,18 @@ public class LodFogConfig FogSettings activeHeightFogSetting = this.heightFogSetting != null ? this.heightFogSetting : FogSettings.EMPTY; str.append("\n" + - "#define farFogStart " + activeFarFogSetting.start + "\n" + - "#define farFogLength " + (activeFarFogSetting.end - activeFarFogSetting.start) + "\n" + - "#define farFogMin " + activeFarFogSetting.min + "\n" + - "#define farFogRange " + (activeFarFogSetting.max - activeFarFogSetting.min) + "\n" + - "#define farFogDensity " + activeFarFogSetting.density + "\n" + - "\n" + - "#define heightFogStart " + activeHeightFogSetting.start + "\n" + - "#define heightFogLength " + (activeHeightFogSetting.end - activeHeightFogSetting.start) + "\n" + - "#define heightFogMin " + activeHeightFogSetting.min + "\n" + - "#define heightFogRange " + (activeHeightFogSetting.max - activeHeightFogSetting.min) + "\n" + - "#define heightFogDensity " + activeHeightFogSetting.density + "\n" + - "\n"); + "#define farFogStart " + activeFarFogSetting.start + "\n" + + "#define farFogLength " + (activeFarFogSetting.end - activeFarFogSetting.start) + "\n" + + "#define farFogMin " + activeFarFogSetting.min + "\n" + + "#define farFogRange " + (activeFarFogSetting.max - activeFarFogSetting.min) + "\n" + + "#define farFogDensity " + activeFarFogSetting.density + "\n" + + "\n" + + "#define heightFogStart " + activeHeightFogSetting.start + "\n" + + "#define heightFogLength " + (activeHeightFogSetting.end - activeHeightFogSetting.start) + "\n" + + "#define heightFogMin " + activeHeightFogSetting.min + "\n" + + "#define heightFogRange " + (activeHeightFogSetting.max - activeHeightFogSetting.min) + "\n" + + "#define heightFogDensity " + activeHeightFogSetting.density + "\n" + + "\n"); str.append("// =======RUNTIME END======== //\n"); return str; @@ -290,15 +290,15 @@ public class LodFogConfig { switch (fogType) { - case LINEAR: - return "return linearFog(dist, farFogStart, farFogLength, farFogMin, farFogRange);\n"; - case EXPONENTIAL: - return "return exponentialFog(dist, farFogStart, farFogLength, farFogMin, farFogRange, farFogDensity);\n"; - case EXPONENTIAL_SQUARED: - return "return exponentialSquaredFog(dist, farFogStart, farFogLength, farFogMin, farFogRange, farFogDensity);\n"; - - default: - throw new IllegalArgumentException("FogType [" + fogType + "] not implemented for [getFarFogMethod]."); + case LINEAR: + return "return linearFog(dist, farFogStart, farFogLength, farFogMin, farFogRange);\n"; + case EXPONENTIAL: + return "return exponentialFog(dist, farFogStart, farFogLength, farFogMin, farFogRange, farFogDensity);\n"; + case EXPONENTIAL_SQUARED: + return "return exponentialSquaredFog(dist, farFogStart, farFogLength, farFogMin, farFogRange, farFogDensity);\n"; + + default: + throw new IllegalArgumentException("FogType [" + fogType + "] not implemented for [getFarFogMethod]."); } } @@ -307,7 +307,7 @@ public class LodFogConfig String str = ""; if (!heightMode.basedOnCamera) { - str = " vertical = realY - (" + heightFogHeight + ");\n"; + str = " vertical = realY - (" + heightFogHeight + ");\n"; } if (heightMode.below && heightMode.above) @@ -338,15 +338,15 @@ public class LodFogConfig { switch (fogType) { - case LINEAR: - return " return linearFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange);\n"; - case EXPONENTIAL: - return " return exponentialFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange, heightFogDensity);\n"; - case EXPONENTIAL_SQUARED: - return " return exponentialSquaredFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange, heightFogDensity);\n"; - - default: - throw new IllegalArgumentException("FogType [" + fogType + "] not implemented for [getHeightFogMethod]."); + case LINEAR: + return " return linearFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange);\n"; + case EXPONENTIAL: + return " return exponentialFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange, heightFogDensity);\n"; + case EXPONENTIAL_SQUARED: + return " return exponentialSquaredFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange, heightFogDensity);\n"; + + default: + throw new IllegalArgumentException("FogType [" + fogType + "] not implemented for [getHeightFogMethod]."); } } @@ -360,72 +360,72 @@ public class LodFogConfig switch (heightFogMode) { - case BASIC: - case IGNORE_HEIGHT: - if (drawNearFog) - str += "max(1.0-near, far);\n"; - else - str += "near * far;\n"; - break; - - case ADDITION: - if (drawNearFog) - str += "max(1.0-near, far + height);\n"; - else - str += "near * (far + height);\n"; - break; - - case MAX: - if (drawNearFog) - str += "max(1.0-near, max(far, height));\n"; - else - str += "near * max(far, height);\n"; - break; - - case INVERSE_MULTIPLY: - if (drawNearFog) - str += "max(1.0-near, 1.0 - (1.0-far)*(1.0-height));\n"; - else - str += "near * (1.0 - (1.0-far)*(1.0-height));\n"; - break; - - case MULTIPLY: - if (drawNearFog) - str += "max(1.0-near, far*height);\n"; - else - str += "near * far * height;\n"; - break; - - case LIMITED_ADDITION: - if (drawNearFog) - str += "max(1.0-near, far + max(far, height));\n"; - else - str += "near * (far + max(far, height));\n"; - break; - - case MULTIPLY_ADDITION: - if (drawNearFog) - str += "max(1.0-near, far + far*height);\n"; - else - str += "near * (far + far*height);\n"; - break; - - case INVERSE_MULTIPLY_ADDITION: - if (drawNearFog) - str += "max(1.0-near, far + 1.0 - (1.0-far)*(1.0-height));\n"; - else - str += "near * (far + 1.0 - (1.0-far)*(1.0-height));\n"; - break; - - case AVERAGE: - if (drawNearFog) - str += "max(1.0-near, far*0.5 + height*0.5);\n"; - else - str += "near * (far*0.5 + height*0.5);\n"; - break; - - default: - throw new IllegalArgumentException("FogType [" + heightFogMode + "] not implemented for [getMixFogMethod]."); + case BASIC: + case IGNORE_HEIGHT: + if (drawNearFog) + str += "max(1.0-near, far);\n"; + else + str += "near * far;\n"; + break; + + case ADDITION: + if (drawNearFog) + str += "max(1.0-near, far + height);\n"; + else + str += "near * (far + height);\n"; + break; + + case MAX: + if (drawNearFog) + str += "max(1.0-near, max(far, height));\n"; + else + str += "near * max(far, height);\n"; + break; + + case INVERSE_MULTIPLY: + if (drawNearFog) + str += "max(1.0-near, 1.0 - (1.0-far)*(1.0-height));\n"; + else + str += "near * (1.0 - (1.0-far)*(1.0-height));\n"; + break; + + case MULTIPLY: + if (drawNearFog) + str += "max(1.0-near, far*height);\n"; + else + str += "near * far * height;\n"; + break; + + case LIMITED_ADDITION: + if (drawNearFog) + str += "max(1.0-near, far + max(far, height));\n"; + else + str += "near * (far + max(far, height));\n"; + break; + + case MULTIPLY_ADDITION: + if (drawNearFog) + str += "max(1.0-near, far + far*height);\n"; + else + str += "near * (far + far*height);\n"; + break; + + case INVERSE_MULTIPLY_ADDITION: + if (drawNearFog) + str += "max(1.0-near, far + 1.0 - (1.0-far)*(1.0-height));\n"; + else + str += "near * (far + 1.0 - (1.0-far)*(1.0-height));\n"; + break; + + case AVERAGE: + if (drawNearFog) + str += "max(1.0-near, far*0.5 + height*0.5);\n"; + else + str += "near * (far*0.5 + height*0.5);\n"; + break; + + default: + throw new IllegalArgumentException("FogType [" + heightFogMode + "] not implemented for [getMixFogMethod]."); } return str; @@ -462,4 +462,5 @@ public class LodFogConfig { return Objects.hash(farFogSetting, heightFogSetting, heightFogMixMode, heightFogMode, heightFogHeight, drawNearFog, earthCurveRatio, noiseEnable, noiseSteps, noiseIntensity, noiseDropoff); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLEnums.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLEnums.java index 92f6fd46e..093f8137d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLEnums.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLEnums.java @@ -16,212 +16,224 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.render.glObject; import static org.lwjgl.opengl.GL46.*; // Turns GL int enums back to readable strings -public class GLEnums { - - public static String getString(int glEnum) { - // blend stuff - switch (glEnum) { - case GL_ZERO: - return "GL_ZERO"; - case GL_ONE: - return "GL_ONE"; - case GL_SRC_COLOR: - return "GL_SRC_COLOR"; - case GL_ONE_MINUS_SRC_COLOR: - return "GL_ONE_MINUS_SRC_COLOR"; - case GL_DST_COLOR: - return "GL_DST_COLOR"; - case GL_ONE_MINUS_DST_COLOR: - return "GL_ONE_MINUS_DST_COLOR"; - case GL_SRC_ALPHA: - return "GL_SRC_ALPHA"; - case GL_ONE_MINUS_SRC_ALPHA: - return "GL_ONE_MINUS_SRC_ALPHA"; - case GL_DST_ALPHA: - return "GL_DST_ALPHA"; - case GL_ONE_MINUS_DST_ALPHA: - return "GL_ONE_MINUS_DST_ALPHA"; - case GL_CONSTANT_COLOR: - return "GL_CONSTANT_COLOR"; - case GL_ONE_MINUS_CONSTANT_COLOR: - return "GL_ONE_MINUS_CONSTANT_COLOR"; - case GL_CONSTANT_ALPHA: - return "GL_CONSTANT_ALPHA"; - case GL_ONE_MINUS_CONSTANT_ALPHA: - return "GL_ONE_MINUS_CONSTANT_ALPHA"; - default: - } - - // shader stuff - switch (glEnum) { - case GL_VERTEX_SHADER: - return "GL_VERTEX_SHADER"; - case GL_GEOMETRY_SHADER: - return "GL_GEOMETRY_SHADER"; - case GL_FRAGMENT_SHADER: - return "GL_FRAGMENT_SHADER"; - default: - } - - // stencil stuff - switch (glEnum) { - case GL_KEEP: - return "GL_KEEP"; - case GL_ZERO: - return "GL_ZERO"; - case GL_REPLACE: - return "GL_REPLACE"; - case GL_INCR: - return "GL_INCR"; - case GL_DECR: - return "GL_DECR"; - case GL_INVERT: - return "GL_INVERT"; - case GL_INCR_WRAP: - return "GL_INCR_WRAP"; - case GL_DECR_WRAP: - return "GL_DECR_WRAP"; - default: - } - - // depth stuff - switch (glEnum) { - case GL_NEVER: - return "GL_NEVER"; - case GL_LESS: - return "GL_LESS"; - case GL_EQUAL: - return "GL_EQUAL"; - case GL_LEQUAL: - return "GL_LEQUAL"; - case GL_GREATER: - return "GL_GREATER"; - case GL_NOTEQUAL: - return "GL_NOTEQUAL"; - case GL_GEQUAL: - return "GL_GEQUAL"; - case GL_ALWAYS: - return "GL_ALWAYS"; - default: - } - - // Texture binding points - switch (glEnum) { - case GL_TEXTURE0: - return "GL_TEXTURE0"; - case GL_TEXTURE1: - return "GL_TEXTURE1"; - case GL_TEXTURE2: - return "GL_TEXTURE2"; - case GL_TEXTURE3: - return "GL_TEXTURE3"; - case GL_TEXTURE4: - return "GL_TEXTURE4"; - case GL_TEXTURE5: - return "GL_TEXTURE5"; - case GL_TEXTURE6: - return "GL_TEXTURE6"; - case GL_TEXTURE7: - return "GL_TEXTURE7"; - case GL_TEXTURE8: - return "GL_TEXTURE8"; - case GL_TEXTURE9: - return "GL_TEXTURE9"; - case GL_TEXTURE10: - return "GL_TEXTURE10"; - case GL_TEXTURE11: - return "GL_TEXTURE11"; - case GL_TEXTURE12: - return "GL_TEXTURE12"; - case GL_TEXTURE13: - return "GL_TEXTURE13"; - case GL_TEXTURE14: - return "GL_TEXTURE14"; - case GL_TEXTURE15: - return "GL_TEXTURE15"; - case GL_TEXTURE16: - return "GL_TEXTURE16"; - case GL_TEXTURE17: - return "GL_TEXTURE17"; - case GL_TEXTURE18: - return "GL_TEXTURE18"; - case GL_TEXTURE19: - return "GL_TEXTURE19"; - case GL_TEXTURE20: - return "GL_TEXTURE20"; - case GL_TEXTURE21: - return "GL_TEXTURE21"; - case GL_TEXTURE22: - return "GL_TEXTURE22"; - case GL_TEXTURE23: - return "GL_TEXTURE23"; - case GL_TEXTURE24: - return "GL_TEXTURE24"; - case GL_TEXTURE25: - return "GL_TEXTURE25"; - case GL_TEXTURE26: - return "GL_TEXTURE26"; - case GL_TEXTURE27: - return "GL_TEXTURE27"; - case GL_TEXTURE28: - return "GL_TEXTURE28"; - case GL_TEXTURE29: - return "GL_TEXTURE29"; - case GL_TEXTURE30: - return "GL_TEXTURE30"; - case GL_TEXTURE31: - return "GL_TEXTURE31"; - default: - } - - // Polygon modes - switch (glEnum) { - case GL_POINT: - return "GL_POINT"; - case GL_LINE: - return "GL_LINE"; - case GL_FILL: - return "GL_FILL"; - default: - } - - // Culling modes - switch (glEnum) { - case GL_FRONT: - return "GL_FRONT"; - case GL_BACK: - return "GL_BACK"; - case GL_FRONT_AND_BACK: - return "GL_FRONT_AND_BACK"; - default: - } - - return "GL_UNKNOWN(" + glEnum + ")"; - } - - public static int getTypeSize(int glTypeEnum) { - switch (glTypeEnum) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - return 1; - case GL_SHORT: - case GL_UNSIGNED_SHORT: - return 2; - case GL_INT: - case GL_UNSIGNED_INT: - return 4; - case GL_FLOAT: - return 4; - case GL_DOUBLE: - return 8; - default: - throw new IllegalArgumentException("Unknown type enum: " + getString(glTypeEnum)); - } - } +public class GLEnums +{ + + public static String getString(int glEnum) + { + // blend stuff + switch (glEnum) + { + case GL_ZERO: + return "GL_ZERO"; + case GL_ONE: + return "GL_ONE"; + case GL_SRC_COLOR: + return "GL_SRC_COLOR"; + case GL_ONE_MINUS_SRC_COLOR: + return "GL_ONE_MINUS_SRC_COLOR"; + case GL_DST_COLOR: + return "GL_DST_COLOR"; + case GL_ONE_MINUS_DST_COLOR: + return "GL_ONE_MINUS_DST_COLOR"; + case GL_SRC_ALPHA: + return "GL_SRC_ALPHA"; + case GL_ONE_MINUS_SRC_ALPHA: + return "GL_ONE_MINUS_SRC_ALPHA"; + case GL_DST_ALPHA: + return "GL_DST_ALPHA"; + case GL_ONE_MINUS_DST_ALPHA: + return "GL_ONE_MINUS_DST_ALPHA"; + case GL_CONSTANT_COLOR: + return "GL_CONSTANT_COLOR"; + case GL_ONE_MINUS_CONSTANT_COLOR: + return "GL_ONE_MINUS_CONSTANT_COLOR"; + case GL_CONSTANT_ALPHA: + return "GL_CONSTANT_ALPHA"; + case GL_ONE_MINUS_CONSTANT_ALPHA: + return "GL_ONE_MINUS_CONSTANT_ALPHA"; + default: + } + + // shader stuff + switch (glEnum) + { + case GL_VERTEX_SHADER: + return "GL_VERTEX_SHADER"; + case GL_GEOMETRY_SHADER: + return "GL_GEOMETRY_SHADER"; + case GL_FRAGMENT_SHADER: + return "GL_FRAGMENT_SHADER"; + default: + } + + // stencil stuff + switch (glEnum) + { + case GL_KEEP: + return "GL_KEEP"; + case GL_ZERO: + return "GL_ZERO"; + case GL_REPLACE: + return "GL_REPLACE"; + case GL_INCR: + return "GL_INCR"; + case GL_DECR: + return "GL_DECR"; + case GL_INVERT: + return "GL_INVERT"; + case GL_INCR_WRAP: + return "GL_INCR_WRAP"; + case GL_DECR_WRAP: + return "GL_DECR_WRAP"; + default: + } + + // depth stuff + switch (glEnum) + { + case GL_NEVER: + return "GL_NEVER"; + case GL_LESS: + return "GL_LESS"; + case GL_EQUAL: + return "GL_EQUAL"; + case GL_LEQUAL: + return "GL_LEQUAL"; + case GL_GREATER: + return "GL_GREATER"; + case GL_NOTEQUAL: + return "GL_NOTEQUAL"; + case GL_GEQUAL: + return "GL_GEQUAL"; + case GL_ALWAYS: + return "GL_ALWAYS"; + default: + } + + // Texture binding points + switch (glEnum) + { + case GL_TEXTURE0: + return "GL_TEXTURE0"; + case GL_TEXTURE1: + return "GL_TEXTURE1"; + case GL_TEXTURE2: + return "GL_TEXTURE2"; + case GL_TEXTURE3: + return "GL_TEXTURE3"; + case GL_TEXTURE4: + return "GL_TEXTURE4"; + case GL_TEXTURE5: + return "GL_TEXTURE5"; + case GL_TEXTURE6: + return "GL_TEXTURE6"; + case GL_TEXTURE7: + return "GL_TEXTURE7"; + case GL_TEXTURE8: + return "GL_TEXTURE8"; + case GL_TEXTURE9: + return "GL_TEXTURE9"; + case GL_TEXTURE10: + return "GL_TEXTURE10"; + case GL_TEXTURE11: + return "GL_TEXTURE11"; + case GL_TEXTURE12: + return "GL_TEXTURE12"; + case GL_TEXTURE13: + return "GL_TEXTURE13"; + case GL_TEXTURE14: + return "GL_TEXTURE14"; + case GL_TEXTURE15: + return "GL_TEXTURE15"; + case GL_TEXTURE16: + return "GL_TEXTURE16"; + case GL_TEXTURE17: + return "GL_TEXTURE17"; + case GL_TEXTURE18: + return "GL_TEXTURE18"; + case GL_TEXTURE19: + return "GL_TEXTURE19"; + case GL_TEXTURE20: + return "GL_TEXTURE20"; + case GL_TEXTURE21: + return "GL_TEXTURE21"; + case GL_TEXTURE22: + return "GL_TEXTURE22"; + case GL_TEXTURE23: + return "GL_TEXTURE23"; + case GL_TEXTURE24: + return "GL_TEXTURE24"; + case GL_TEXTURE25: + return "GL_TEXTURE25"; + case GL_TEXTURE26: + return "GL_TEXTURE26"; + case GL_TEXTURE27: + return "GL_TEXTURE27"; + case GL_TEXTURE28: + return "GL_TEXTURE28"; + case GL_TEXTURE29: + return "GL_TEXTURE29"; + case GL_TEXTURE30: + return "GL_TEXTURE30"; + case GL_TEXTURE31: + return "GL_TEXTURE31"; + default: + } + + // Polygon modes + switch (glEnum) + { + case GL_POINT: + return "GL_POINT"; + case GL_LINE: + return "GL_LINE"; + case GL_FILL: + return "GL_FILL"; + default: + } + + // Culling modes + switch (glEnum) + { + case GL_FRONT: + return "GL_FRONT"; + case GL_BACK: + return "GL_BACK"; + case GL_FRONT_AND_BACK: + return "GL_FRONT_AND_BACK"; + default: + } + + return "GL_UNKNOWN(" + glEnum + ")"; + } + + public static int getTypeSize(int glTypeEnum) + { + switch (glTypeEnum) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return 1; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return 2; + case GL_INT: + case GL_UNSIGNED_INT: + return 4; + case GL_FLOAT: + return 4; + case GL_DOUBLE: + return 8; + default: + throw new IllegalArgumentException("Unknown type enum: " + getString(glTypeEnum)); + } + } + } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java index 8ab297696..f5d935993 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java @@ -56,17 +56,17 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftCli * https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
* https://learnopengl.com/Advanced-OpenGL/Advanced-Data
* https://www.slideshare.net/CassEveritt/approaching-zero-driver-overhead

- * + * * https://gamedev.stackexchange.com/questions/91995/edit-vbo-data-or-create-a-new-one
* https://stackoverflow.com/questions/63509735/massive-performance-loss-with-glmapbuffer

- * + * * @author James Seibel * @version 2022-10-1 */ public class GLProxy { public static final boolean OVERRIDE_VANILLA_GL_LOGGER = ModInfo.IS_DEV_BUILD; - + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build()); @@ -74,7 +74,7 @@ public class GLProxy private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); public static final ConfigBasedLogger GL_LOGGER = new ConfigBasedLogger(LogManager.getLogger(GLProxy.class), () -> Config.Client.Advanced.Logging.logRendererGLEvent.get()); - + private static GLProxy instance = null; /** Minecraft's GLFW window */ @@ -86,28 +86,28 @@ public class GLProxy public final long lodBuilderGlContext; /** the LodBuilder's GL capabilities */ public final GLCapabilities lodBuilderGlCapabilities; - + /** the proxyWorker's GLFW window */ public final long proxyWorkerGlContext; /** the proxyWorker's GL capabilities */ public final GLCapabilities proxyWorkerGlCapabilities; - + public boolean namedObjectSupported = false; // ~OpenGL 4.5 (UNUSED CURRENTLY) public boolean bufferStorageSupported = false; // ~OpenGL 4.4 public boolean VertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3 private final EGpuUploadMethod preferredUploadMethod; - + public final GLMessage.Builder vanillaDebugMessageBuilder = GLMessage.Builder.DEFAULT_MESSAGE_BUILDER; public final GLMessage.Builder lodBuilderDebugMessageBuilder = GLMessage.Builder.DEFAULT_MESSAGE_BUILDER; public final GLMessage.Builder proxyWorkerDebugMessageBuilder = GLMessage.Builder.DEFAULT_MESSAGE_BUILDER; - + private GLProxy() throws IllegalStateException { - // this must be created on minecraft's render context to work correctly - + // this must be created on minecraft's render context to work correctly + GL_LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error."); GL_LOGGER.info("Lod Render OpenGL version [" + GL11.glGetString(GL11.GL_VERSION) + "]."); @@ -135,11 +135,11 @@ public class GLProxy // See full requirement at above. String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GLProxy.class.getSimpleName() - + " and discovered this GPU doesn't meet the OpenGL requirements. Sorry I couldn't tell you sooner :(\n"+ - "Additional info:\n"+supportedVersionInfo; + + " and discovered this GPU doesn't meet the OpenGL requirements. Sorry I couldn't tell you sooner :(\n" + + "Additional info:\n" + supportedVersionInfo; MC.crashMinecraft(errorMessage, new UnsupportedOperationException("Distant Horizon OpenGL requirements not met")); } - GL_LOGGER.info("minecraftGlCapabilities:\n"+getVersionInfo(minecraftGlCapabilities)); + GL_LOGGER.info("minecraftGlCapabilities:\n" + getVersionInfo(minecraftGlCapabilities)); if (OVERRIDE_VANILLA_GL_LOGGER) { @@ -179,7 +179,7 @@ public class GLProxy GLFW.glfwMakeContextCurrent(lodBuilderGlContext); // set and log the capabilities lodBuilderGlCapabilities = GL.createCapabilities(); - GL_LOGGER.info("lodBuilderGlCapabilities:\n"+getVersionInfo(lodBuilderGlCapabilities)); + GL_LOGGER.info("lodBuilderGlCapabilities:\n" + getVersionInfo(lodBuilderGlCapabilities)); // override the GL logger GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream(GLProxy::logMessage, lodBuilderDebugMessageBuilder), true)); // clear the context for the next stage @@ -193,7 +193,8 @@ public class GLProxy // create the proxyWorker's context proxyWorkerGlContext = GLFW.glfwCreateWindow(64, 48, "LOD proxy worker Window", 0L, minecraftGlContext); - if (proxyWorkerGlContext == 0) { + if (proxyWorkerGlContext == 0) + { GL_LOGGER.error("ERROR: Failed to create GLFW context for OpenGL 3.2 with" + " Forward Compat Core Profile! Your OS may have not been able to support it!"); throw new UnsupportedOperationException("Forward Compat Core Profile 3.2 creation failure"); @@ -202,12 +203,12 @@ public class GLProxy GLFW.glfwMakeContextCurrent(proxyWorkerGlContext); // set and log the capabilities proxyWorkerGlCapabilities = GL.createCapabilities(); - GL_LOGGER.info("proxyWorkerGlCapabilities:\n"+getVersionInfo(lodBuilderGlCapabilities)); + GL_LOGGER.info("proxyWorkerGlCapabilities:\n" + getVersionInfo(lodBuilderGlCapabilities)); // override the GL logger GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream(GLProxy::logMessage, proxyWorkerDebugMessageBuilder), true)); // clear the context for the next stage GLFW.glfwMakeContextCurrent(0L); - + //======================// @@ -245,7 +246,7 @@ public class GLProxy preferredUploadMethod = bufferStorageSupported ? EGpuUploadMethod.BUFFER_STORAGE : EGpuUploadMethod.DATA; } GL_LOGGER.info("GPU Vendor [" + vendor + "], Preferred upload method is [" + preferredUploadMethod + "]."); - + //==========// @@ -253,7 +254,7 @@ public class GLProxy //==========// // Since this is created on the render thread, make sure the Minecraft context is used in the end - setGlContext(EGLProxyContext.MINECRAFT); + setGlContext(EGLProxyContext.MINECRAFT); // GLProxy creation success GL_LOGGER.info(GLProxy.class.getSimpleName() + " creation successful. OpenGL smiles upon you this day."); @@ -270,33 +271,33 @@ public class GLProxy // we don't have to change the context, we are already there. if (currentContext == newContext) return; - + long contextPointer; GLCapabilities newGlCapabilities = null; // get the pointer(s) for this context switch (newContext) { - case LOD_BUILDER: - contextPointer = lodBuilderGlContext; - newGlCapabilities = lodBuilderGlCapabilities; - break; - - case MINECRAFT: - contextPointer = minecraftGlContext; - newGlCapabilities = minecraftGlCapabilities; - break; - - case PROXY_WORKER: - contextPointer = proxyWorkerGlContext; - newGlCapabilities = proxyWorkerGlCapabilities; - break; + case LOD_BUILDER: + contextPointer = lodBuilderGlContext; + newGlCapabilities = lodBuilderGlCapabilities; + break; - default: // default should never happen, it is just here to make the compiler happy - case NONE: - // 0L is equivalent to null - contextPointer = 0L; - break; + case MINECRAFT: + contextPointer = minecraftGlContext; + newGlCapabilities = minecraftGlCapabilities; + break; + + case PROXY_WORKER: + contextPointer = proxyWorkerGlContext; + newGlCapabilities = proxyWorkerGlCapabilities; + break; + + default: // default should never happen, it is just here to make the compiler happy + case NONE: + // 0L is equivalent to null + contextPointer = 0L; + break; } GLFW.glfwMakeContextCurrent(contextPointer); @@ -361,7 +362,7 @@ public class GLProxy return method == EGpuUploadMethod.AUTO ? preferredUploadMethod : method; } - /** + /** * Asynchronously calls the given runnable on proxy's OpenGL context. * Useful for creating/destroying OpenGL objects in a thread * that doesn't normally have access to a OpenGL context.
@@ -430,8 +431,8 @@ public class GLProxy { return "Your OpenGL support:\n" + "openGL version 3.2+: " + c.OpenGL32 + " <- REQUIRED\n" + - "Vertex Attribute Buffer Binding: " + (c.glVertexAttribBinding!=0) + " <- optional improvement\n" + - "Buffer Storage: " + (c.glBufferStorage!=0) + " <- optional improvement\n" + + "Vertex Attribute Buffer Binding: " + (c.glVertexAttribBinding != 0) + " <- optional improvement\n" + + "Buffer Storage: " + (c.glBufferStorage != 0) + " <- optional improvement\n" + "If you noticed that your computer supports higher OpenGL versions" + " but not the required version, try running the game in compatibility mode." + " (How you turn that on, I have no clue~)"; @@ -462,7 +463,7 @@ public class GLProxy { GLMessage.ESeverity s = msg.severity; if (msg.type == GLMessage.EType.ERROR || - msg.type == GLMessage.EType.UNDEFINED_BEHAVIOR) + msg.type == GLMessage.EType.UNDEFINED_BEHAVIOR) { GL_LOGGER.error("GL ERROR {} from {}: {}", msg.id, msg.source, msg.message); throw new RuntimeException("GL ERROR: " + msg.toString()); @@ -471,18 +472,18 @@ public class GLProxy RuntimeException e = new RuntimeException("GL MESSAGE: " + msg.toString()); switch (s) { - case HIGH: - GL_LOGGER.error("{}", e); - break; - case MEDIUM: - GL_LOGGER.warn("{}", e); - break; - case LOW: - GL_LOGGER.info("{}", e); - break; - case NOTIFICATION: - GL_LOGGER.debug("{}", e); - break; + case HIGH: + GL_LOGGER.error("{}", e); + break; + case MEDIUM: + GL_LOGGER.warn("{}", e); + break; + case LOW: + GL_LOGGER.info("{}", e); + break; + case NOTIFICATION: + GL_LOGGER.debug("{}", e); + break; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java index 0fea71d7a..e3055723b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLState.java @@ -16,139 +16,139 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.render.glObject; import org.lwjgl.opengl.GL32; -public class GLState +public class GLState { - public int prog; - public int vao; - public int vbo; - public int ebo; - public int fbo; - public int text; - public int activeTex; - public int text0; - public boolean blend; - public int blendSrc; - public int blendDst; - public boolean depth; - public boolean depthWrite; - public int depthFunc; - public boolean stencil; - public int stencilFunc; - public int stencilRef; - public int stencilMask; - public int[] view; - public boolean cull; - public int cullMode; - public int polyMode; + public int prog; + public int vao; + public int vbo; + public int ebo; + public int fbo; + public int text; + public int activeTex; + public int text0; + public boolean blend; + public int blendSrc; + public int blendDst; + public boolean depth; + public boolean depthWrite; + public int depthFunc; + public boolean stencil; + public int stencilFunc; + public int stencilRef; + public int stencilMask; + public int[] view; + public boolean cull; + public int cullMode; + public int polyMode; public GLState() { this.saveState(); } - public void saveState() - { - this.prog = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM); - this.vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING); - this.vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING); - this.ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING); - this.fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING); - this.text = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); - this.activeTex = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE); - GL32.glActiveTexture(GL32.GL_TEXTURE0); - this.text0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); - GL32.glActiveTexture(this.activeTex); - this.blend = GL32.glIsEnabled(GL32.GL_BLEND); - this.blendSrc = GL32.glGetInteger(GL32.GL_BLEND_SRC); - this.blendDst = GL32.glGetInteger(GL32.GL_BLEND_DST); - this.depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST); - this.depthWrite = GL32.glGetInteger(GL32.GL_DEPTH_WRITEMASK) == GL32.GL_TRUE; - this.depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC); - this.stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST); - this.stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC); - this.stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF); - this.stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK); - this.view = new int[4]; - GL32.glGetIntegerv(GL32.GL_VIEWPORT, this.view); - this.cull = GL32.glIsEnabled(GL32.GL_CULL_FACE); - this.cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE); - this.polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE); - } - - @Override - public String toString() - { - return "GLState{"+ - "prog="+this.prog+", vao="+this.vao+", vbo="+this.vbo+", ebo="+this.ebo+", fbo="+this.fbo + - ", text="+GLEnums.getString(this.text)+"@"+this.activeTex+", text0="+GLEnums.getString(this.text0) + - ", blend="+this.blend+", blendMode="+GLEnums.getString(this.blendSrc)+","+GLEnums.getString(this.blendDst) + - ", depth="+this.depth + - ", depthFunc="+GLEnums.getString(this.depthFunc)+", stencil="+this.stencil+", stencilFunc=" + - GLEnums.getString(this.stencilFunc)+", stencilRef="+this.stencilRef+", stencilMask="+this.stencilMask + - ", view={x:"+this.view[0]+", y:"+this.view[1] + - ", w:"+this.view[2]+", h:"+this.view[3]+"}"+", cull="+this.cull+", cullMode=" - + GLEnums.getString(this.cullMode)+", polyMode="+GLEnums.getString(this.polyMode) + - '}'; - } - - public void restore() - { - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fbo); - if (this.blend) - { - GL32.glEnable(GL32.GL_BLEND); - } - else - { - GL32.glDisable(GL32.GL_BLEND); - } + public void saveState() + { + this.prog = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM); + this.vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING); + this.vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING); + this.ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING); + this.fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING); + this.text = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); + this.activeTex = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE); + GL32.glActiveTexture(GL32.GL_TEXTURE0); + this.text0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); + GL32.glActiveTexture(this.activeTex); + this.blend = GL32.glIsEnabled(GL32.GL_BLEND); + this.blendSrc = GL32.glGetInteger(GL32.GL_BLEND_SRC); + this.blendDst = GL32.glGetInteger(GL32.GL_BLEND_DST); + this.depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST); + this.depthWrite = GL32.glGetInteger(GL32.GL_DEPTH_WRITEMASK) == GL32.GL_TRUE; + this.depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC); + this.stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST); + this.stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC); + this.stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF); + this.stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK); + this.view = new int[4]; + GL32.glGetIntegerv(GL32.GL_VIEWPORT, this.view); + this.cull = GL32.glIsEnabled(GL32.GL_CULL_FACE); + this.cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE); + this.polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE); + } + + @Override + public String toString() + { + return "GLState{" + + "prog=" + this.prog + ", vao=" + this.vao + ", vbo=" + this.vbo + ", ebo=" + this.ebo + ", fbo=" + this.fbo + + ", text=" + GLEnums.getString(this.text) + "@" + this.activeTex + ", text0=" + GLEnums.getString(this.text0) + + ", blend=" + this.blend + ", blendMode=" + GLEnums.getString(this.blendSrc) + "," + GLEnums.getString(this.blendDst) + + ", depth=" + this.depth + + ", depthFunc=" + GLEnums.getString(this.depthFunc) + ", stencil=" + this.stencil + ", stencilFunc=" + + GLEnums.getString(this.stencilFunc) + ", stencilRef=" + this.stencilRef + ", stencilMask=" + this.stencilMask + + ", view={x:" + this.view[0] + ", y:" + this.view[1] + + ", w:" + this.view[2] + ", h:" + this.view[3] + "}" + ", cull=" + this.cull + ", cullMode=" + + GLEnums.getString(this.cullMode) + ", polyMode=" + GLEnums.getString(this.polyMode) + + '}'; + } + + public void restore() + { + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fbo); + if (this.blend) + { + GL32.glEnable(GL32.GL_BLEND); + } + else + { + GL32.glDisable(GL32.GL_BLEND); + } - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.text0); - GL32.glActiveTexture(this.activeTex); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.text); - GL32.glBindVertexArray(this.vao); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.vbo); - GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, this.ebo); - GL32.glUseProgram(this.prog); - - GL32.glDepthMask(this.depthWrite); - GL32.glBlendFunc(this.blendSrc, this.blendDst); - if (this.depth) - { - GL32.glEnable(GL32.GL_DEPTH_TEST); - } - else - { - GL32.glDisable(GL32.GL_DEPTH_TEST); - } - GL32.glDepthFunc(this.depthFunc); + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.text0); + GL32.glActiveTexture(this.activeTex); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.text); + GL32.glBindVertexArray(this.vao); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.vbo); + GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, this.ebo); + GL32.glUseProgram(this.prog); - if (this.stencil) - { - GL32.glEnable(GL32.GL_STENCIL_TEST); - } - else - { - GL32.glDisable(GL32.GL_STENCIL_TEST); - } - GL32.glStencilFunc(this.stencilFunc, this.stencilRef, this.stencilMask); + GL32.glDepthMask(this.depthWrite); + GL32.glBlendFunc(this.blendSrc, this.blendDst); + if (this.depth) + { + GL32.glEnable(GL32.GL_DEPTH_TEST); + } + else + { + GL32.glDisable(GL32.GL_DEPTH_TEST); + } + GL32.glDepthFunc(this.depthFunc); - GL32.glViewport(this.view[0], this.view[1], this.view[2], this.view[3]); - if (this.cull) - { - GL32.glEnable(GL32.GL_CULL_FACE); - } - else - { - GL32.glDisable(GL32.GL_CULL_FACE); - } - GL32.glCullFace(this.cullMode); - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode); - } - + if (this.stencil) + { + GL32.glEnable(GL32.GL_STENCIL_TEST); + } + else + { + GL32.glDisable(GL32.GL_STENCIL_TEST); + } + GL32.glStencilFunc(this.stencilFunc, this.stencilRef, this.stencilMask); + + GL32.glViewport(this.view[0], this.view[1], this.view[2], this.view[3]); + if (this.cull) + { + GL32.glEnable(GL32.GL_CULL_FACE); + } + else + { + GL32.glDisable(GL32.GL_CULL_FACE); + } + GL32.glCullFace(this.cullMode); + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/LightmapTexture.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/LightmapTexture.java index 61f45c79b..9c83f417a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/LightmapTexture.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/LightmapTexture.java @@ -16,37 +16,43 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.render.glObject; import org.lwjgl.opengl.GL32; -public class LightmapTexture { +public class LightmapTexture +{ public int id; - public LightmapTexture() { + public LightmapTexture() + { id = GL32.glGenTextures(); bind(); } - public void bind() { + public void bind() + { GL32.glBindTexture(GL32.GL_TEXTURE_2D, id); } - public void unbind() { + public void unbind() + { GL32.glBindTexture(GL32.GL_TEXTURE_2D, 0); } - - public void free() { + + public void free() + { GL32.glDeleteTextures(id); } - + // private int[] testArray; - public void fillData(int lightMapWidth, int lightMapHeight, int[] pixels) { + public void fillData(int lightMapWidth, int lightMapHeight, int[] pixels) + { GL32.glDeleteTextures(id); id = GL32.glGenTextures(); GL32.glBindTexture(GL32.GL_TEXTURE_2D, id); - if (pixels.length != lightMapWidth*lightMapHeight) + if (pixels.length != lightMapWidth * lightMapHeight) throw new RuntimeException("Lightmap Width*Height not equal to pixels provided!"); // comment me out to see when the lightmap is changing @@ -67,7 +73,7 @@ public class LightmapTexture { MC.sendChatMessage(same + " " + badIndex); */ // comment this line out to prevent uploading the new lightmap - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA, lightMapWidth*lightMapHeight, + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA, lightMapWidth * lightMapHeight, 1, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_BYTE, pixels); GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_BORDER); GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_BORDER); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java index 9d472807b..8e0d0ed26 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java @@ -16,183 +16,209 @@ import java.util.concurrent.atomic.AtomicInteger; public class GLBuffer implements AutoCloseable { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); - - public static final double BUFFER_EXPANSION_MULTIPLIER = 1.3; - public static final double BUFFER_SHRINK_TRIGGER = BUFFER_EXPANSION_MULTIPLIER * BUFFER_EXPANSION_MULTIPLIER; - public static AtomicInteger count = new AtomicInteger(0); - - protected int id; - public final int getId() { - return id; - } - protected int size = 0; - public int getSize() { - return size; - } - protected boolean bufferStorage; - public final boolean isBufferStorage() { - return bufferStorage; - } - protected boolean isMapped = false; - - - public GLBuffer(boolean isBufferStorage) - { - create(isBufferStorage); - } - - - // Should be override by subclasses - public int getBufferBindingTarget() { - return GL32.GL_COPY_READ_BUFFER; - } - - public void bind() { - GL32.glBindBuffer(getBufferBindingTarget(), id); - } - public void unbind() { - GL32.glBindBuffer(getBufferBindingTarget(), 0); - } - - protected void create(boolean asBufferStorage) { - LodUtil.assertTrue(GLProxy.getInstance().getGlContext() != EGLProxyContext.NONE, - "Thread [{}] tried to create a GLBuffer outside a OpenGL context.", Thread.currentThread()); - this.id = GL32.glGenBuffers(); - this.bufferStorage = asBufferStorage; - count.getAndIncrement(); - } - - //DEBUG USE - //private StackTraceElement[] firstCloseCallStack = null; - protected void destroy(boolean async) { - LodUtil.assertTrue(this.id != 0, "Buffer double close!"); - if (async && GLProxy.getInstance().getGlContext() != EGLProxyContext.PROXY_WORKER) { - GLProxy.getInstance().recordOpenGlCall(() -> destroy((false))); - } else { - GL32.glDeleteBuffers(id); - //firstCloseCallStack = Thread.currentThread().getStackTrace(); - id = 0; - size = 0; - if (count.decrementAndGet()==0) - LOGGER.info("All GLBuffer is freed."); - } - } - - // Requires already binded - protected void uploadBufferStorage(ByteBuffer bb, int bufferStorageHint) { - LodUtil.assertTrue(bufferStorage, "Buffer is not bufferStorage but its trying to use bufferStorage upload method!"); - int bbSize = bb.limit() - bb.position(); - destroy(false); - create(true); - bind(); - GL44.glBufferStorage(getBufferBindingTarget(), bb, bufferStorageHint); - size = bbSize; - } - - // Requires already binded - protected void uploadBufferData(ByteBuffer bb, int bufferDataHint) { - LodUtil.assertTrue(!bufferStorage, "Buffer is bufferStorage but its trying to use bufferData upload method!"); - int bbSize = bb.limit() - bb.position(); - GL32.glBufferData(getBufferBindingTarget(), bb, bufferDataHint); - size = bbSize; - } - - // Requires already binded - protected void uploadSubData(ByteBuffer bb, int maxExpansionSize, int bufferDataHint) { - LodUtil.assertTrue(!bufferStorage, "Buffer is bufferStorage but its trying to use subData upload method!"); - int bbSize = bb.limit() - bb.position(); - if (size < bbSize || size > bbSize * BUFFER_SHRINK_TRIGGER) { - int newSize = (int) (bbSize * BUFFER_EXPANSION_MULTIPLIER); - if (newSize > maxExpansionSize) newSize = maxExpansionSize; - GL32.glBufferData(getBufferBindingTarget(), newSize, bufferDataHint); - size = newSize; - } - GL32.glBufferSubData(getBufferBindingTarget(), 0, bb); - } - - // Requires already binded - public void uploadBuffer(ByteBuffer bb, EGpuUploadMethod uploadMethod, int maxExpansionSize, int bufferHint) { - LodUtil.assertTrue(!uploadMethod.useEarlyMapping, "UploadMethod signal that this should use Mapping instead of uploadBuffer!"); - int bbSize = bb.limit()-bb.position(); - LodUtil.assertTrue(bbSize <= maxExpansionSize, "maxExpansionSize is {} but buffer size is {}!", maxExpansionSize, bbSize); - GLProxy.GL_LOGGER.debug("Uploading buffer with {}.", new UnitBytes(bbSize)); - // If size is zero, just ignore it. - if (bbSize == 0) return; - boolean useBuffStorage = uploadMethod.useBufferStorage; - if (useBuffStorage != bufferStorage) { - destroy(false); - create(useBuffStorage); - bind(); - } - switch (uploadMethod) { - case AUTO: - LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!"); - case BUFFER_STORAGE: - uploadBufferStorage(bb, bufferHint); - break; - case DATA: - uploadBufferData(bb, bufferHint); - break; - case SUB_DATA: - uploadSubData(bb, maxExpansionSize, bufferHint); - break; - default: - LodUtil.assertNotReach("Unknown GpuUploadMethod!"); - } - } - - public ByteBuffer mapBuffer(int targetSize, EGpuUploadMethod uploadMethod, int maxExpensionSize, int bufferHint, int mapFlags) { - LodUtil.assertTrue(targetSize != 0, "MapBuffer targetSize is 0"); - LodUtil.assertTrue(uploadMethod.useEarlyMapping, "Upload method must be one that use early mappings in order to call mapBuffer"); - LodUtil.assertTrue(!isMapped, "Buffer is already mapped"); - - boolean useBuffStorage = uploadMethod.useBufferStorage; - if (useBuffStorage != bufferStorage) { - destroy(false); - create(useBuffStorage); - } - bind(); - ByteBuffer vboBuffer; - - if (size < targetSize || size > targetSize * BUFFER_SHRINK_TRIGGER) { - int newSize = (int) (targetSize * BUFFER_EXPANSION_MULTIPLIER); - if (newSize > maxExpensionSize) newSize = maxExpensionSize; - size = newSize; - if (bufferStorage) { - GL32.glDeleteBuffers(id); - id = GL32.glGenBuffers(); - GL32.glBindBuffer(getBufferBindingTarget(), id); - GL32.glBindBuffer(getBufferBindingTarget(), id); - GL44.glBufferStorage(getBufferBindingTarget(), newSize, bufferHint); - } else { - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, newSize, bufferHint); - } - } - - vboBuffer = GL32.glMapBufferRange(GL32.GL_ARRAY_BUFFER, 0, targetSize, mapFlags); - isMapped = true; - return vboBuffer; - } - - // Requires already binded - public void unmapBuffer() - { - LodUtil.assertTrue(isMapped, "Buffer is not mapped"); - bind(); - GL32.glUnmapBuffer(getBufferBindingTarget()); - isMapped = false; - } - - @Override - public void close() - { - destroy(true); - } - - @Override - public String toString() { - return (bufferStorage ? "" : "Static-")+ getClass().getSimpleName() + - "[id:"+id+",size:"+size+(isMapped?",MAPPED" : "")+"]"; - } + private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); + + public static final double BUFFER_EXPANSION_MULTIPLIER = 1.3; + public static final double BUFFER_SHRINK_TRIGGER = BUFFER_EXPANSION_MULTIPLIER * BUFFER_EXPANSION_MULTIPLIER; + public static AtomicInteger count = new AtomicInteger(0); + + protected int id; + public final int getId() + { + return id; + } + protected int size = 0; + public int getSize() + { + return size; + } + protected boolean bufferStorage; + public final boolean isBufferStorage() + { + return bufferStorage; + } + protected boolean isMapped = false; + + + public GLBuffer(boolean isBufferStorage) + { + create(isBufferStorage); + } + + + // Should be override by subclasses + public int getBufferBindingTarget() + { + return GL32.GL_COPY_READ_BUFFER; + } + + public void bind() + { + GL32.glBindBuffer(getBufferBindingTarget(), id); + } + public void unbind() + { + GL32.glBindBuffer(getBufferBindingTarget(), 0); + } + + protected void create(boolean asBufferStorage) + { + LodUtil.assertTrue(GLProxy.getInstance().getGlContext() != EGLProxyContext.NONE, + "Thread [{}] tried to create a GLBuffer outside a OpenGL context.", Thread.currentThread()); + this.id = GL32.glGenBuffers(); + this.bufferStorage = asBufferStorage; + count.getAndIncrement(); + } + + //DEBUG USE + //private StackTraceElement[] firstCloseCallStack = null; + protected void destroy(boolean async) + { + LodUtil.assertTrue(this.id != 0, "Buffer double close!"); + if (async && GLProxy.getInstance().getGlContext() != EGLProxyContext.PROXY_WORKER) + { + GLProxy.getInstance().recordOpenGlCall(() -> destroy((false))); + } + else + { + GL32.glDeleteBuffers(id); + //firstCloseCallStack = Thread.currentThread().getStackTrace(); + id = 0; + size = 0; + if (count.decrementAndGet() == 0) + LOGGER.info("All GLBuffer is freed."); + } + } + + // Requires already binded + protected void uploadBufferStorage(ByteBuffer bb, int bufferStorageHint) + { + LodUtil.assertTrue(bufferStorage, "Buffer is not bufferStorage but its trying to use bufferStorage upload method!"); + int bbSize = bb.limit() - bb.position(); + destroy(false); + create(true); + bind(); + GL44.glBufferStorage(getBufferBindingTarget(), bb, bufferStorageHint); + size = bbSize; + } + + // Requires already binded + protected void uploadBufferData(ByteBuffer bb, int bufferDataHint) + { + LodUtil.assertTrue(!bufferStorage, "Buffer is bufferStorage but its trying to use bufferData upload method!"); + int bbSize = bb.limit() - bb.position(); + GL32.glBufferData(getBufferBindingTarget(), bb, bufferDataHint); + size = bbSize; + } + + // Requires already binded + protected void uploadSubData(ByteBuffer bb, int maxExpansionSize, int bufferDataHint) + { + LodUtil.assertTrue(!bufferStorage, "Buffer is bufferStorage but its trying to use subData upload method!"); + int bbSize = bb.limit() - bb.position(); + if (size < bbSize || size > bbSize * BUFFER_SHRINK_TRIGGER) + { + int newSize = (int) (bbSize * BUFFER_EXPANSION_MULTIPLIER); + if (newSize > maxExpansionSize) newSize = maxExpansionSize; + GL32.glBufferData(getBufferBindingTarget(), newSize, bufferDataHint); + size = newSize; + } + GL32.glBufferSubData(getBufferBindingTarget(), 0, bb); + } + + // Requires already binded + public void uploadBuffer(ByteBuffer bb, EGpuUploadMethod uploadMethod, int maxExpansionSize, int bufferHint) + { + LodUtil.assertTrue(!uploadMethod.useEarlyMapping, "UploadMethod signal that this should use Mapping instead of uploadBuffer!"); + int bbSize = bb.limit() - bb.position(); + LodUtil.assertTrue(bbSize <= maxExpansionSize, "maxExpansionSize is {} but buffer size is {}!", maxExpansionSize, bbSize); + GLProxy.GL_LOGGER.debug("Uploading buffer with {}.", new UnitBytes(bbSize)); + // If size is zero, just ignore it. + if (bbSize == 0) return; + boolean useBuffStorage = uploadMethod.useBufferStorage; + if (useBuffStorage != bufferStorage) + { + destroy(false); + create(useBuffStorage); + bind(); + } + switch (uploadMethod) + { + case AUTO: + LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!"); + case BUFFER_STORAGE: + uploadBufferStorage(bb, bufferHint); + break; + case DATA: + uploadBufferData(bb, bufferHint); + break; + case SUB_DATA: + uploadSubData(bb, maxExpansionSize, bufferHint); + break; + default: + LodUtil.assertNotReach("Unknown GpuUploadMethod!"); + } + } + + public ByteBuffer mapBuffer(int targetSize, EGpuUploadMethod uploadMethod, int maxExpensionSize, int bufferHint, int mapFlags) + { + LodUtil.assertTrue(targetSize != 0, "MapBuffer targetSize is 0"); + LodUtil.assertTrue(uploadMethod.useEarlyMapping, "Upload method must be one that use early mappings in order to call mapBuffer"); + LodUtil.assertTrue(!isMapped, "Buffer is already mapped"); + + boolean useBuffStorage = uploadMethod.useBufferStorage; + if (useBuffStorage != bufferStorage) + { + destroy(false); + create(useBuffStorage); + } + bind(); + ByteBuffer vboBuffer; + + if (size < targetSize || size > targetSize * BUFFER_SHRINK_TRIGGER) + { + int newSize = (int) (targetSize * BUFFER_EXPANSION_MULTIPLIER); + if (newSize > maxExpensionSize) newSize = maxExpensionSize; + size = newSize; + if (bufferStorage) + { + GL32.glDeleteBuffers(id); + id = GL32.glGenBuffers(); + GL32.glBindBuffer(getBufferBindingTarget(), id); + GL32.glBindBuffer(getBufferBindingTarget(), id); + GL44.glBufferStorage(getBufferBindingTarget(), newSize, bufferHint); + } + else + { + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, newSize, bufferHint); + } + } + + vboBuffer = GL32.glMapBufferRange(GL32.GL_ARRAY_BUFFER, 0, targetSize, mapFlags); + isMapped = true; + return vboBuffer; + } + + // Requires already binded + public void unmapBuffer() + { + LodUtil.assertTrue(isMapped, "Buffer is not mapped"); + bind(); + GL32.glUnmapBuffer(getBufferBindingTarget()); + isMapped = false; + } + + @Override + public void close() + { + destroy(true); + } + + @Override + public String toString() + { + return (bufferStorage ? "" : "Static-") + getClass().getSimpleName() + + "[id:" + id + ",size:" + size + (isMapped ? ",MAPPED" : "") + "]"; + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java index e50b6cf48..5a2adfc12 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java @@ -24,7 +24,7 @@ import org.lwjgl.opengl.GL32; /** * This is a container for a OpenGL * VBO (Vertex Buffer Object). - * + * * @author James Seibel * @version 11-20-2021 */ @@ -38,20 +38,23 @@ public class GLElementBuffer extends GLBuffer public int getIndicesCount() { return indicesCount; } protected int type = GL32.GL_UNSIGNED_INT; public int getType() { return type; } - + public GLElementBuffer(boolean isBufferStorage) { super(isBufferStorage); } - + @Override - public void destroy(boolean async) { + public void destroy(boolean async) + { super.destroy(async); indicesCount = 0; } - + @Override - public int getBufferBindingTarget() { + public int getBufferBindingTarget() + { return GL32.GL_ELEMENT_ARRAY_BUFFER; } + } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java index 3516fe8be..5ec603bfd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java @@ -28,7 +28,7 @@ import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; /** * This is a container for a OpenGL * VBO (Vertex Buffer Object). - * + * * @author James Seibel * @version 11-20-2021 */ @@ -47,28 +47,32 @@ public class GLVertexBuffer extends GLBuffer { super(isBufferStorage); } - + @Override - public void destroy(boolean async) { + public void destroy(boolean async) + { super.destroy(async); vertexCount = 0; } - + @Override - public int getBufferBindingTarget() { + public int getBufferBindingTarget() + { return GL32.GL_ARRAY_BUFFER; } - public void uploadBuffer(ByteBuffer bb, int vertCount, EGpuUploadMethod uploadMethod, int maxExpensionSize) { + public void uploadBuffer(ByteBuffer bb, int vertCount, EGpuUploadMethod uploadMethod, int maxExpensionSize) + { if (vertCount < 0) throw new IllegalArgumentException("VertCount is negative!"); // If size is zero, just ignore it. - if (bb.limit()-bb.position() != 0) { + if (bb.limit() - bb.position() != 0) + { boolean useBuffStorage = uploadMethod.useBufferStorage; super.uploadBuffer(bb, uploadMethod, maxExpensionSize, useBuffStorage ? 0 : GL32.GL_STATIC_DRAW); } vertexCount = vertCount; } - + public ByteBuffer mapBuffer(int targetSize, EGpuUploadMethod uploadMethod, int maxExpensionSize) { return super.mapBuffer(targetSize, uploadMethod, maxExpensionSize, @@ -76,4 +80,5 @@ public class GLVertexBuffer extends GLBuffer uploadMethod.useEarlyMapping ? GL32.GL_DYNAMIC_DRAW : GL32.GL_STATIC_DRAW, GL32.GL_MAP_WRITE_BIT | GL32.GL_MAP_UNSYNCHRONIZED_BIT | GL32.GL_MAP_INVALIDATE_BUFFER_BIT); } + } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/QuadElementBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/QuadElementBuffer.java index 75c6cd3f1..5fcbe7677 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/QuadElementBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/QuadElementBuffer.java @@ -13,118 +13,143 @@ import java.nio.ByteOrder; public class QuadElementBuffer extends GLElementBuffer { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); - - - public QuadElementBuffer() { - super(GLProxy.getInstance().bufferStorageSupported); - } - - public int getCapacity() { - return super.getSize() / GLEnums.getTypeSize(getType()); - } - - private static void buildBufferByte(int quadCount, ByteBuffer buffer) { - for (int i = 0; i < quadCount; i++) { - int vIndex = i * 4; - // First triangle - buffer.put((byte) (vIndex)); - buffer.put((byte) (vIndex + 1)); - buffer.put((byte) (vIndex + 2)); - // Second triangle - buffer.put((byte) (vIndex + 2)); - buffer.put((byte) (vIndex + 3)); - buffer.put((byte) (vIndex)); - } - if (buffer.hasRemaining()) { - throw new IllegalStateException("QuadElementBuffer is not full somehow after building"); - } - buffer.rewind(); - } - private static void buildBufferShort(int quadCount, ByteBuffer buffer) { - for (int i = 0; i < quadCount; i++) { - int vIndex = i * 4; - // First triangle - buffer.putShort((short) (vIndex)); - buffer.putShort((short) (vIndex + 1)); - buffer.putShort((short) (vIndex + 2)); - // Second triangle - buffer.putShort((short) (vIndex + 2)); - buffer.putShort((short) (vIndex + 3)); - buffer.putShort((short) (vIndex)); - } - if (buffer.hasRemaining()) { - throw new IllegalStateException("QuadElementBuffer is not full somehow after building"); - } - buffer.rewind(); - } - private static void buildBufferInt(int quadCount, ByteBuffer buffer) { - for (int i = 0; i < quadCount; i++) { - int vIndex = i * 4; - // First triangle - buffer.putInt(vIndex); - buffer.putInt(vIndex + 1); - buffer.putInt(vIndex + 2); - // Second triangle - buffer.putInt(vIndex + 2); - buffer.putInt(vIndex + 3); - buffer.putInt(vIndex); - } - if (buffer.hasRemaining()) { - throw new IllegalStateException("QuadElementBuffer is not full somehow after building"); - } - buffer.rewind(); - } - - private static void buildBuffer(int quadCount, ByteBuffer buffer, int type) { - switch (type) { - case GL32.GL_UNSIGNED_BYTE: - buildBufferByte(quadCount, buffer); - break; - case GL32.GL_UNSIGNED_SHORT: - buildBufferShort(quadCount, buffer); - break; - case GL32.GL_UNSIGNED_INT: - buildBufferInt(quadCount, buffer); - break; - default: - throw new IllegalStateException("Unknown type: " + type); - } - } - - public void reserve(int quadCount) { - if (quadCount < 0) { - throw new IllegalArgumentException("quadCount must be greater than 0"); - } - if (quadCount == 0) return; // FIXME: This doesn't happens yet, but just add this since everything will break if it does - indicesCount = quadCount * 6; // 2 triangles per quad - if (indicesCount >= getCapacity() && indicesCount < getCapacity() * BUFFER_SHRINK_TRIGGER) { - return; - } - int vertexCount = quadCount * 4; // 4 vertices per quad - GLProxy gl = GLProxy.getInstance(); - - if (vertexCount < 255) { // Reserve 1 for the reset index - type = GL32.GL_UNSIGNED_BYTE; - } else if (vertexCount < 65535) { // Reserve 1 for the reset index - type = GL32.GL_UNSIGNED_SHORT; - } else { - type = GL32.GL_UNSIGNED_INT; - } - LOGGER.info("Quad IBO Resizing from [" + getCapacity() + "] to [" + quadCount + "]" + " with type: " + - GLEnums.getString(type)); - - ByteBuffer buffer = ByteBuffer.allocateDirect(indicesCount * GLEnums.getTypeSize(type)).order(ByteOrder.nativeOrder()); - buildBuffer(quadCount, buffer, type); - if (!gl.bufferStorageSupported) { - - bind(); - super.uploadBuffer(buffer, EGpuUploadMethod.DATA, - indicesCount * GLEnums.getTypeSize(type), GL32.GL_STATIC_DRAW); - } else { - bind(); - super.uploadBuffer(buffer, EGpuUploadMethod.BUFFER_STORAGE, - indicesCount * GLEnums.getTypeSize(type), 0); - } - } + private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); + + + public QuadElementBuffer() + { + super(GLProxy.getInstance().bufferStorageSupported); + } + + public int getCapacity() + { + return super.getSize() / GLEnums.getTypeSize(getType()); + } + + private static void buildBufferByte(int quadCount, ByteBuffer buffer) + { + for (int i = 0; i < quadCount; i++) + { + int vIndex = i * 4; + // First triangle + buffer.put((byte) (vIndex)); + buffer.put((byte) (vIndex + 1)); + buffer.put((byte) (vIndex + 2)); + // Second triangle + buffer.put((byte) (vIndex + 2)); + buffer.put((byte) (vIndex + 3)); + buffer.put((byte) (vIndex)); + } + if (buffer.hasRemaining()) + { + throw new IllegalStateException("QuadElementBuffer is not full somehow after building"); + } + buffer.rewind(); + } + private static void buildBufferShort(int quadCount, ByteBuffer buffer) + { + for (int i = 0; i < quadCount; i++) + { + int vIndex = i * 4; + // First triangle + buffer.putShort((short) (vIndex)); + buffer.putShort((short) (vIndex + 1)); + buffer.putShort((short) (vIndex + 2)); + // Second triangle + buffer.putShort((short) (vIndex + 2)); + buffer.putShort((short) (vIndex + 3)); + buffer.putShort((short) (vIndex)); + } + if (buffer.hasRemaining()) + { + throw new IllegalStateException("QuadElementBuffer is not full somehow after building"); + } + buffer.rewind(); + } + private static void buildBufferInt(int quadCount, ByteBuffer buffer) + { + for (int i = 0; i < quadCount; i++) + { + int vIndex = i * 4; + // First triangle + buffer.putInt(vIndex); + buffer.putInt(vIndex + 1); + buffer.putInt(vIndex + 2); + // Second triangle + buffer.putInt(vIndex + 2); + buffer.putInt(vIndex + 3); + buffer.putInt(vIndex); + } + if (buffer.hasRemaining()) + { + throw new IllegalStateException("QuadElementBuffer is not full somehow after building"); + } + buffer.rewind(); + } + + private static void buildBuffer(int quadCount, ByteBuffer buffer, int type) + { + switch (type) + { + case GL32.GL_UNSIGNED_BYTE: + buildBufferByte(quadCount, buffer); + break; + case GL32.GL_UNSIGNED_SHORT: + buildBufferShort(quadCount, buffer); + break; + case GL32.GL_UNSIGNED_INT: + buildBufferInt(quadCount, buffer); + break; + default: + throw new IllegalStateException("Unknown type: " + type); + } + } + + public void reserve(int quadCount) + { + if (quadCount < 0) + { + throw new IllegalArgumentException("quadCount must be greater than 0"); + } + if (quadCount == 0) return; // FIXME: This doesn't happens yet, but just add this since everything will break if it does + indicesCount = quadCount * 6; // 2 triangles per quad + if (indicesCount >= getCapacity() && indicesCount < getCapacity() * BUFFER_SHRINK_TRIGGER) + { + return; + } + int vertexCount = quadCount * 4; // 4 vertices per quad + GLProxy gl = GLProxy.getInstance(); + + if (vertexCount < 255) + { // Reserve 1 for the reset index + type = GL32.GL_UNSIGNED_BYTE; + } + else if (vertexCount < 65535) + { // Reserve 1 for the reset index + type = GL32.GL_UNSIGNED_SHORT; + } + else + { + type = GL32.GL_UNSIGNED_INT; + } + LOGGER.info("Quad IBO Resizing from [" + getCapacity() + "] to [" + quadCount + "]" + " with type: " + + GLEnums.getString(type)); + + ByteBuffer buffer = ByteBuffer.allocateDirect(indicesCount * GLEnums.getTypeSize(type)).order(ByteOrder.nativeOrder()); + buildBuffer(quadCount, buffer, type); + if (!gl.bufferStorageSupported) + { + + bind(); + super.uploadBuffer(buffer, EGpuUploadMethod.DATA, + indicesCount * GLEnums.getTypeSize(type), GL32.GL_STATIC_DRAW); + } + else + { + bind(); + super.uploadBuffer(buffer, EGpuUploadMethod.BUFFER_STORAGE, + indicesCount * GLEnums.getTypeSize(type), 0); + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/Shader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/Shader.java index b14a9cf03..d2ce874c1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/Shader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/Shader.java @@ -32,40 +32,43 @@ import org.lwjgl.opengl.GL32; /** * This object holds a OpenGL reference to a shader * and allows for reading in and compiling a shader file. - * + * * @author James Seibel * @version 11-8-2021 */ public class Shader -{ +{ /** OpenGL shader ID */ public final int id; - /** Creates a shader with specified type. + /** + * Creates a shader with specified type. + * * @param type Either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER. * @param path File path of the shader * @param absoluteFilePath If false the file path is relative to the resource jar folder. - * @throws RuntimeException if the shader fails to compile + * @throws RuntimeException if the shader fails to compile */ public Shader(int type, String path, boolean absoluteFilePath) { - GLProxy.GL_LOGGER.info("Loading shader at "+path); + GLProxy.GL_LOGGER.info("Loading shader at " + path); // Create an empty shader object id = GL32.glCreateShader(type); StringBuilder source = loadFile(path, absoluteFilePath, new StringBuilder()); GL32.glShaderSource(id, source); - + GL32.glCompileShader(id); // check if the shader compiled int status = GL32.glGetShaderi(id, GL32.GL_COMPILE_STATUS); - if (status != GL32.GL_TRUE) { - String message = "Shader compiler error. Details: "+GL32.glGetShaderInfoLog(id); + if (status != GL32.GL_TRUE) + { + String message = "Shader compiler error. Details: " + GL32.glGetShaderInfoLog(id); free(); // important! throw new RuntimeException(message); } - GLProxy.GL_LOGGER.info("Shader at "+path+" loaded sucessfully."); + GLProxy.GL_LOGGER.info("Shader at " + path + " loaded sucessfully."); } - + public Shader(int type, String sourceString) { GLProxy.GL_LOGGER.info("Loading shader with type: {}", type); @@ -73,37 +76,44 @@ public class Shader // Create an empty shader object id = GL32.glCreateShader(type); GL32.glShaderSource(id, sourceString); - + GL32.glCompileShader(id); // check if the shader compiled int status = GL32.glGetShaderi(id, GL32.GL_COMPILE_STATUS); - if (status != GL32.GL_TRUE) { - - String message = "Shader compiler error. Details: "+GL32.glGetShaderInfoLog(id); - message += "\nSource:\n"+sourceString; + if (status != GL32.GL_TRUE) + { + + String message = "Shader compiler error. Details: " + GL32.glGetShaderInfoLog(id); + message += "\nSource:\n" + sourceString; free(); // important! throw new RuntimeException(message); } GLProxy.GL_LOGGER.info("Shader loaded sucessfully."); } - + // REMEMBER to always free the resource! - public void free() { + public void free() + { GL32.glDeleteShader(id); } - public static StringBuilder loadFile(String path, boolean absoluteFilePath, StringBuilder stringBuilder) { + public static StringBuilder loadFile(String path, boolean absoluteFilePath, StringBuilder stringBuilder) + { try { // open the file InputStream in; - if (absoluteFilePath) { + if (absoluteFilePath) + { // Throws FileNotFoundException in = new FileInputStream(path); // Note: this should use OS path seperator - } else { + } + else + { in = Shader.class.getClassLoader().getResourceAsStream(path); // Note: path seperator should be '/' - if (in == null) { - throw new FileNotFoundException("Shader file not found in resource: "+path); + if (in == null) + { + throw new FileNotFoundException("Shader file not found in resource: " + path); } } BufferedReader reader = new BufferedReader(new InputStreamReader(in)); @@ -111,7 +121,9 @@ public class Shader // read in the file String line; while ((line = reader.readLine()) != null) + { stringBuilder.append(line).append("\n"); + } } catch (IOException e) { @@ -119,4 +131,5 @@ public class Shader } return stringBuilder; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java index aad26f415..ec81ca757 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java @@ -39,7 +39,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3f; * and contains a few methods that can be used with OpenGL shader programs. * The reason for many of these simple wrapper methods is as reminders of what * can (and needs to be) done with a shader program. - * + * * @author James Seibel * @version 11-26-2021 */ @@ -47,10 +47,12 @@ public class ShaderProgram { /** Stores the handle of the program. */ public final int id; - + // TODO: A better way to set the fragData output name - /** Creates a shader program. - * This will bind ShaderProgram */ + /** + * Creates a shader program. + * This will bind ShaderProgram + */ public ShaderProgram(String vert, String frag, String fragDataOutputName, String[] attributes) { this( @@ -59,52 +61,59 @@ public class ShaderProgram fragDataOutputName, attributes ); } - - public ShaderProgram(Supplier vert, Supplier frag, String fragDataOutputName, String[] attributes) { + + public ShaderProgram(Supplier vert, Supplier frag, String fragDataOutputName, String[] attributes) + { this( new ArrayList<>(Arrays.asList(vert)), new ArrayList<>(Arrays.asList(frag)), attributes ); } - - - public ShaderProgram(List> vert, List> frag, String[] attributes) { + + + public ShaderProgram(List> vert, List> frag, String[] attributes) + { id = GL32.glCreateProgram(); - - for (Supplier v : vert) { + + for (Supplier v : vert) + { Shader vertShader = new Shader(GL32.GL_VERTEX_SHADER, v.get()); GL32.glAttachShader(this.id, vertShader.id); vertShader.free(); // important! } - - for (Supplier f : frag) { + + for (Supplier f : frag) + { Shader fragShader = new Shader(GL32.GL_FRAGMENT_SHADER, f.get()); GL32.glAttachShader(this.id, fragShader.id); fragShader.free(); // important! } - - for (int i = 0; i < attributes.length; i++) { + + for (int i = 0; i < attributes.length; i++) + { GL32.glBindAttribLocation(id, i, attributes[i]); } GL32.glLinkProgram(this.id); - + int status = GL32.glGetProgrami(this.id, GL32.GL_LINK_STATUS); - if (status != GL32.GL_TRUE) { + if (status != GL32.GL_TRUE) + { String message = "Shader Link Error. Details: " + GL32.glGetProgramInfoLog(this.id); free(); // important! throw new RuntimeException(message); } GL32.glUseProgram(id); // This HAVE to be a direct call to prevent calling the overloaded version } - + /** This will bind ShaderProgram */ public void bind() { GL32.glUseProgram(id); } /** This will unbind ShaderProgram */ - public void unbind() { + public void unbind() + { GL32.glUseProgram(0); } @@ -114,18 +123,19 @@ public class ShaderProgram GL32.glDeleteProgram(id); } - /** WARNING: Slow native call! Cache it if possible! + /** + * WARNING: Slow native call! Cache it if possible! * Gets the location of an attribute variable with specified name. * Calls GL20.glGetAttribLocation(id, name) * * @param name Attribute name - * @throws RuntimeException if attribute not found * @return Location of the attribute + * @throws RuntimeException if attribute not found */ public int getAttributeLocation(CharSequence name) { int i = GL32.glGetAttribLocation(id, name); - if (i==-1) throw new RuntimeException("Attribute name not found: "+name); + if (i == -1) throw new RuntimeException("Attribute name not found: " + name); return i; } // Same as above but without throwing errors. @@ -134,63 +144,64 @@ public class ShaderProgram { return GL32.glGetAttribLocation(id, name); } - - /** WARNING: Slow native call! Cache it if possible! + + /** + * WARNING: Slow native call! Cache it if possible! * Gets the location of a uniform variable with specified name. * Calls GL20.glGetUniformLocation(id, name) * * @param name Uniform name - * @throws RuntimeException if uniform not found * @return Location of the Uniform + * @throws RuntimeException if uniform not found */ public int getUniformLocation(CharSequence name) { int i = GL32.glGetUniformLocation(id, name); - if (i==-1) + if (i == -1) { - throw new RuntimeException("Uniform name not found: "+name); + throw new RuntimeException("Uniform name not found: " + name); } return i; } - + // Same as above but without throwing errors. // Return -1 if uniform doesn't exist or has been optimized out public int tryGetUniformLocation(CharSequence name) { return GL32.glGetUniformLocation(id, name); } - + /** Requires ShaderProgram binded. */ public void setUniform(int location, boolean value) { // This use -1 for false as that equals all one set GL32.glUniform1i(location, value ? 1 : 0); } - + /** Requires ShaderProgram binded. */ public void setUniform(int location, int value) { GL32.glUniform1i(location, value); } - + /** Requires ShaderProgram binded. */ public void setUniform(int location, float value) { GL32.glUniform1f(location, value); } - + /** Requires ShaderProgram binded. */ public void setUniform(int location, Vec3f value) { GL32.glUniform3f(location, value.x, value.y, value.z); } - + /** Requires ShaderProgram binded. */ public void setUniform(int location, Vec3d value) { GL32.glUniform3f(location, (float) value.x, (float) value.y, (float) value.z); } - + /** Requires ShaderProgram binded. */ public void setUniform(int location, Mat4f value) { @@ -202,8 +213,10 @@ public class ShaderProgram } } - /** Converts the color's RGBA values into values between 0 and 1. - * Requires ShaderProgram binded. */ + /** + * Converts the color's RGBA values into values between 0 and 1. + * Requires ShaderProgram binded. + */ public void setUniform(int location, Color value) { GL32.glUniform4f(location, value.getRed() / 256.0f, value.getGreen() / 256.0f, value.getBlue() / 256.0f, value.getAlpha() / 256.0f); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttribute.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttribute.java index a0764e27c..37bc18b3a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttribute.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttribute.java @@ -23,96 +23,122 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.coreapi.util.MathUtil; import org.lwjgl.opengl.GL32; -public abstract class VertexAttribute { +public abstract class VertexAttribute +{ - public static final class VertexPointer { + public static final class VertexPointer + { public final int elementCount; public final int glType; public final boolean normalized; public final int byteSize; public final boolean useInteger; - public VertexPointer(int elementCount, int glType, boolean normalized, int byteSize, boolean useInteger) { + public VertexPointer(int elementCount, int glType, boolean normalized, int byteSize, boolean useInteger) + { this.elementCount = elementCount; this.glType = glType; this.normalized = normalized; this.byteSize = byteSize; this.useInteger = useInteger; } - public VertexPointer(int elementCount, int glType, boolean normalized, int byteSize) { + public VertexPointer(int elementCount, int glType, boolean normalized, int byteSize) + { this(elementCount, glType, normalized, byteSize, false); } - private static int _align(int bytes) { - return MathUtil.ceilDiv(bytes, 4)*4; + private static int _align(int bytes) + { + return MathUtil.ceilDiv(bytes, 4) * 4; } - public static VertexPointer addFloatPointer(boolean normalized) { + public static VertexPointer addFloatPointer(boolean normalized) + { return new VertexPointer(1, GL32.GL_FLOAT, normalized, 4); } - public static VertexPointer addVec2Pointer(boolean normalized) { + public static VertexPointer addVec2Pointer(boolean normalized) + { return new VertexPointer(2, GL32.GL_FLOAT, normalized, 8); } - public static VertexPointer addVec3Pointer(boolean normalized) { + public static VertexPointer addVec3Pointer(boolean normalized) + { return new VertexPointer(3, GL32.GL_FLOAT, normalized, 12); } - public static VertexPointer addVec4Pointer(boolean normalized) { + public static VertexPointer addVec4Pointer(boolean normalized) + { return new VertexPointer(4, GL32.GL_FLOAT, normalized, 16); } - public static VertexPointer addUnsignedBytePointer(boolean normalized, boolean useInteger) { + public static VertexPointer addUnsignedBytePointer(boolean normalized, boolean useInteger) + { return new VertexPointer(1, GL32.GL_UNSIGNED_BYTE, normalized, 4, useInteger); // Always aligned to 4 bytes } - public static VertexPointer addUnsignedBytesPointer(int elementCount, boolean normalized, boolean useInteger) { + public static VertexPointer addUnsignedBytesPointer(int elementCount, boolean normalized, boolean useInteger) + { return new VertexPointer(elementCount, GL32.GL_UNSIGNED_BYTE, normalized, _align(elementCount), useInteger); // aligned to 4 bytes } - public static VertexPointer addUnsignedShortsPointer(int elementCount, boolean normalized, boolean useInteger) { - return new VertexPointer(elementCount, GL32.GL_UNSIGNED_SHORT, normalized, _align(elementCount*2), useInteger); + public static VertexPointer addUnsignedShortsPointer(int elementCount, boolean normalized, boolean useInteger) + { + return new VertexPointer(elementCount, GL32.GL_UNSIGNED_SHORT, normalized, _align(elementCount * 2), useInteger); } - public static VertexPointer addShortsPointer(int elementCount, boolean normalized, boolean useInteger) { - return new VertexPointer(elementCount, GL32.GL_SHORT, normalized, _align(elementCount*2), useInteger); + public static VertexPointer addShortsPointer(int elementCount, boolean normalized, boolean useInteger) + { + return new VertexPointer(elementCount, GL32.GL_SHORT, normalized, _align(elementCount * 2), useInteger); } - public static VertexPointer addIntPointer(boolean normalized, boolean useInteger) { + public static VertexPointer addIntPointer(boolean normalized, boolean useInteger) + { return new VertexPointer(1, GL32.GL_INT, normalized, 4, useInteger); } - public static VertexPointer addIvec2Pointer(boolean normalized, boolean useInteger) { + public static VertexPointer addIvec2Pointer(boolean normalized, boolean useInteger) + { return new VertexPointer(2, GL32.GL_INT, normalized, 8, useInteger); } - public static VertexPointer addIvec3Pointer(boolean normalized, boolean useInteger) { + public static VertexPointer addIvec3Pointer(boolean normalized, boolean useInteger) + { return new VertexPointer(3, GL32.GL_INT, normalized, 12, useInteger); } - public static VertexPointer addIvec4Pointer(boolean normalized, boolean useInteger) { + public static VertexPointer addIvec4Pointer(boolean normalized, boolean useInteger) + { return new VertexPointer(4, GL32.GL_INT, normalized, 16, useInteger); } + } - + /** Stores the handle of the VertexAttribute. */ public final int id; // This will bind VertexAttribute - protected VertexAttribute() { + protected VertexAttribute() + { id = GL32.glGenVertexArrays(); GL32.glBindVertexArray(id); } - - public static VertexAttribute create() { - if (GLProxy.getInstance().VertexAttributeBufferBindingSupported) { + + public static VertexAttribute create() + { + if (GLProxy.getInstance().VertexAttributeBufferBindingSupported) + { return new VertexAttributePostGL43(); - } else { + } + else + { return new VertexAttributePreGL43(); } } - + // This will bind VertexAttribute - public void bind() { + public void bind() + { GL32.glBindVertexArray(id); } // This will unbind VertexAttribute - public void unbind() { + public void unbind() + { GL32.glBindVertexArray(0); } // REMEMBER to always free the resource! - public void free() { + public void free() + { GL32.glDeleteVertexArrays(id); } @@ -128,4 +154,5 @@ public abstract class VertexAttribute { public abstract void setVertexAttribute(int bindingPoint, int attributeIndex, VertexPointer attribute); // Requires VertexAttribute binded public abstract void completeAndCheck(int expectedStrideSize); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttributePostGL43.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttributePostGL43.java index 8e7c3b4d0..140de644b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttributePostGL43.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/VertexAttributePostGL43.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.render.glObject.vertexAttribute; import com.seibel.distanthorizons.core.render.glObject.GLProxy; @@ -30,66 +30,79 @@ import org.lwjgl.opengl.GL43; // Since I no longer needs to implement binding points, I also no // longer needs to keep track of Pointers. -public final class VertexAttributePostGL43 extends VertexAttribute { - +public final class VertexAttributePostGL43 extends VertexAttribute +{ + int numberOfBindingPoints = 0; int strideSize = 0; - + // This will bind VertexAttribute - public VertexAttributePostGL43() { + public VertexAttributePostGL43() + { super(); // also bind VertexAttribute } @Override // Requires VertexAttribute binded, VertexBuffer binded - public void bindBufferToAllBindingPoint(int buffer) { - for (int i=0; i. */ - + package com.seibel.distanthorizons.core.render.glObject.vertexAttribute; import java.util.ArrayList; @@ -28,7 +28,8 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy; import org.lwjgl.opengl.GL32; -public final class VertexAttributePreGL43 extends VertexAttribute { +public final class VertexAttributePreGL43 extends VertexAttribute +{ // I tried to use as much raw arrays as possible as those lookups // happens every frame, and the speed directly effects fps @@ -39,9 +40,10 @@ public final class VertexAttributePreGL43 extends VertexAttribute { TreeMap> bindingPointsToIndexBuilder; ArrayList pointersBuilder; - + // This will bind VertexAttribute - public VertexAttributePreGL43() { + public VertexAttributePreGL43() + { super(); // also bind VertexAttribute bindingPointsToIndexBuilder = new TreeMap>(); pointersBuilder = new ArrayList(); @@ -49,13 +51,17 @@ public final class VertexAttributePreGL43 extends VertexAttribute { @Override // Requires VertexAttribute binded, VertexBuffer binded - public void bindBufferToAllBindingPoint(int buffer) { - for (int i=0; i intArray = bindingPointsToIndexBuilder.computeIfAbsent(bindingPoint, k -> new TreeSet()); intArray.add(attributeIndex); - while (pointersBuilder.size() <= attributeIndex) { + while (pointersBuilder.size() <= attributeIndex) + { // This is dumb, but ArrayList doesn't have a resize, And this code // should only be ran when it's building the Vertex Attribute anyways. pointersBuilder.add(null); } pointersBuilder.set(attributeIndex, attribute); } - + @Override // Requires VertexAttribute binded - public void completeAndCheck(int expectedStrideSize) { + public void completeAndCheck(int expectedStrideSize) + { int maxBindPointNumber = bindingPointsToIndexBuilder.lastKey(); - bindingPointsToIndex = new int[maxBindPointNumber+1][]; + bindingPointsToIndex = new int[maxBindPointNumber + 1][]; bindingPointsToIndexBuilder.forEach((Integer i, TreeSet set) -> { bindingPointsToIndex[i] = new int[set.size()]; Iterator iter = set.iterator(); - for (int j = 0; j ELoggerMode.LOG_ALL_TO_CHAT); - public static final ConfigBasedSpamLogger spamLogger = new ConfigBasedSpamLogger( - LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT, 1); - private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - // A box from 0,0,0 to 1,1,1 - private static final float[] box_vertices = { - // Pos x y z - 0, 0, 0, - 1, 0, 0, - 1, 1, 0, - 0, 1, 0, - 0, 0, 1, - 1, 0, 1, - 1, 1, 1, - 0, 1, 1, - }; - - private static final int[] box_outline_indices = { - 0, 1, - 1, 2, - 2, 3, - 3, 0, - - 4, 5, - 5, 6, - 6, 7, - 7, 4, - - 0, 4, - 1, 5, - 2, 6, - 3, 7, - }; - - public static final class Box { - public Vec3f a; - public Vec3f b; - public Color color; - - public Box(Vec3f a, Vec3f b, Color color) { - this.a = a; - this.b = b; - this.color = color; - } - - public Box(Vec3f a, Vec3f b, Color color, Vec3f margin) { - this.a = a; - this.a.add(margin); - this.b = b; - this.b.subtract(margin); - this.color = color; - } - - public Box(DhLodPos pos, float minY, float maxY, float marginPercent, Color color) { - DhBlockPos2D blockMin = pos.getCornerBlockPos(); - DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth()); - float edge = pos.getBlockWidth() * marginPercent; - Vec3f a = new Vec3f(blockMin.x + edge, minY, blockMin.z + edge); - Vec3f b = new Vec3f(blockMax.x - edge, maxY, blockMax.z - edge); - this.a = a; - this.b = b; - this.color = color; - } - - public Box(DhLodPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) { - float hashY = ((float)hash.hashCode() / Integer.MAX_VALUE) * yDiff; - DhBlockPos2D blockMin = pos.getCornerBlockPos(); - DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth()); - float edge = pos.getBlockWidth() * marginPercent; - Vec3f a = new Vec3f(blockMin.x + edge, hashY, blockMin.z + edge); - Vec3f b = new Vec3f(blockMax.x - edge, hashY, blockMax.z - edge); - this.a = a; - this.b = b; - this.color = color; - } - - public Box(DhSectionPos pos, float minY, float maxY, float marginPercent, Color color) { - this(pos.getSectionBBoxPos(), minY, maxY, marginPercent, color); - } - - public Box(DhSectionPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) { - this(pos.getSectionBBoxPos(), y, yDiff, hash, marginPercent, color); - } - } - - ShaderProgram basicShader; - GLVertexBuffer boxBuffer; - GLElementBuffer boxOutlineBuffer; - VertexAttribute va; - boolean init = false; - - private final LinkedList> renderers = new LinkedList<>(); - - public static final class BoxParticle implements Comparable { - public Box box; - public long startTime; - public long duration; - public float yChange; - - public BoxParticle(Box box, long startTime, long duration, float yChange) { - this.box = box; - this.startTime = startTime; - this.duration = duration; - this.yChange = yChange; - } - - public BoxParticle(Box box, long ns, float yChange) { - this(box, System.nanoTime(), ns, yChange); - } - - public BoxParticle(Box box, double s, float yChange) { - this(box, System.nanoTime(), (long)(s * 1000000000), yChange); - } - - @Override - public int compareTo(@NotNull DebugRenderer.BoxParticle o) { - return Long.compare(startTime + duration, o.startTime + o.duration); - } - - Box getBox() { - long now = System.nanoTime(); - float percent = (now - startTime) / (float)duration; - percent = (float)Math.pow(percent, 4); - float yDiff = yChange * percent; - return new Box(new Vec3f(box.a.x, box.a.y + yDiff, box.a.z), new Vec3f(box.b.x, box.b.y + yDiff, box.b.z), box.color); - } - - boolean isDead(long time) { - return time - startTime > duration; - } - } - - public static final class BoxWithLife implements IDebugRenderable, Closeable { - public Box box; - public BoxParticle particaleOnClose; - - public BoxWithLife(Box box, long ns, float yChange, Color deathColor) { - this.box = box; - this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), -1, ns, yChange); - DebugRenderer.register(this); - } - - public BoxWithLife(Box box, long ns, float yChange) { - this(box, ns, yChange, box.color); - } - - public BoxWithLife(Box box, double s, float yChange, Color deathColor) { - this.box = box; - this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), s, yChange); - } - - public BoxWithLife(Box box, double s, float yChange) { - this(box, s, yChange, box.color); - } - - @Override - public void debugRender(DebugRenderer r) { - r.renderBox(box); - } - - @Override - public void close() { - makeParticle(new BoxParticle(particaleOnClose.getBox(), System.nanoTime(), particaleOnClose.duration, particaleOnClose.yChange)); - DebugRenderer.unregister(this); - } - } - - private final PriorityBlockingQueue particles = new PriorityBlockingQueue<>(); - - public static void unregister(IDebugRenderable r) { - if (INSTANCE == null) return; - INSTANCE.removeRenderer(r); - } - - public static void makeParticle(BoxParticle particle) { - if (INSTANCE == null) return; - if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return; - INSTANCE.particles.add(particle); - } - - private void removeRenderer(IDebugRenderable r) { - synchronized (renderers) { - Iterator> it = renderers.iterator(); - while (it.hasNext()) { - WeakReference ref = it.next(); - if (ref.get() == null) { - it.remove(); - continue; - } - if (ref.get() == r) { - it.remove(); - return; - } - } - } - } - - public void init() { - if (init) return; - init = true; - va = VertexAttribute.create(); - va.bind(); - // Pos\ - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec3Pointer(false)); - va.completeAndCheck(Float.BYTES * 3); - basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", - "fragColor", new String[]{"vPosition"}); - createBuffer(); - } - - private void createBuffer() { - ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(box_vertices); - buffer.rewind(); - boxBuffer = new GLVertexBuffer(false); - boxBuffer.bind(); - boxBuffer.uploadBuffer(buffer, 8, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - - buffer = ByteBuffer.allocateDirect(box_outline_indices.length * Integer.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asIntBuffer().put(box_outline_indices); - buffer.rewind(); - boxOutlineBuffer = new GLElementBuffer(false); - boxOutlineBuffer.bind(); - boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - } - - public void addRenderer(IDebugRenderable r) { - if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return; - synchronized (renderers) { - renderers.add(new WeakReference<>(r)); - } - } - - public static void register(IDebugRenderable r) { - if (INSTANCE == null) return; - INSTANCE.addRenderer(r); - } - - private Mat4f transform_this_frame; - private Vec3f camf; - - public void renderBox(Box box) { - Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - camf.x, box.a.y - camf.y, box.a.z - camf.z); - boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); - Mat4f t = transform_this_frame.copy(); - t.multiply(boxTransform); - basicShader.setUniform(basicShader.getUniformLocation("transform"), t); - basicShader.setUniform(basicShader.getUniformLocation("uColor"), box.color); - GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0); - } - - public void render(Mat4f transform) { - if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return; - - transform_this_frame = transform; - Vec3d cam = MC_RENDER.getCameraExactPosition(); - camf = new Vec3f((float)cam.x, (float)cam.y, (float)cam.z); - - GLState state = new GLState(); - init(); - - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight()); - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE); - //GL32.glLineWidth(2); - GL32.glEnable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_STENCIL_TEST); - GL32.glDisable(GL32.GL_BLEND); - GL32.glDisable(GL32.GL_SCISSOR_TEST); - - basicShader.bind(); - va.bind(); - va.bindBufferToAllBindingPoint(boxBuffer.getId()); - - boxOutlineBuffer.bind(); - - synchronized (renderers) - { - Iterator> it = renderers.iterator(); - while (it.hasNext()) { - WeakReference ref = it.next(); - IDebugRenderable r = ref.get(); - if (r == null) { - it.remove(); - continue; - } - r.debugRender(this); - } - } - - BoxParticle head = null; - while ((head = particles.poll()) != null && head.isDead(System.nanoTime())) {} - if (head != null) { - particles.add(head); - } - particles.forEach(b -> renderBox(b.getBox())); - - state.restore(); - } - - +public class DebugRenderer +{ + public static DebugRenderer INSTANCE = new DebugRenderer(); + public DebugRenderer() { } + + public static final ConfigBasedLogger logger = new ConfigBasedLogger( + LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT); + public static final ConfigBasedSpamLogger spamLogger = new ConfigBasedSpamLogger( + LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT, 1); + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + // A box from 0,0,0 to 1,1,1 + private static final float[] box_vertices = { + // Pos x y z + 0, 0, 0, + 1, 0, 0, + 1, 1, 0, + 0, 1, 0, + 0, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 1, 1, + }; + + private static final int[] box_outline_indices = { + 0, 1, + 1, 2, + 2, 3, + 3, 0, + + 4, 5, + 5, 6, + 6, 7, + 7, 4, + + 0, 4, + 1, 5, + 2, 6, + 3, 7, + }; + + public static final class Box + { + public Vec3f a; + public Vec3f b; + public Color color; + + public Box(Vec3f a, Vec3f b, Color color) + { + this.a = a; + this.b = b; + this.color = color; + } + + public Box(Vec3f a, Vec3f b, Color color, Vec3f margin) + { + this.a = a; + this.a.add(margin); + this.b = b; + this.b.subtract(margin); + this.color = color; + } + + public Box(DhLodPos pos, float minY, float maxY, float marginPercent, Color color) + { + DhBlockPos2D blockMin = pos.getCornerBlockPos(); + DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth()); + float edge = pos.getBlockWidth() * marginPercent; + Vec3f a = new Vec3f(blockMin.x + edge, minY, blockMin.z + edge); + Vec3f b = new Vec3f(blockMax.x - edge, maxY, blockMax.z - edge); + this.a = a; + this.b = b; + this.color = color; + } + + public Box(DhLodPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) + { + float hashY = ((float) hash.hashCode() / Integer.MAX_VALUE) * yDiff; + DhBlockPos2D blockMin = pos.getCornerBlockPos(); + DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth()); + float edge = pos.getBlockWidth() * marginPercent; + Vec3f a = new Vec3f(blockMin.x + edge, hashY, blockMin.z + edge); + Vec3f b = new Vec3f(blockMax.x - edge, hashY, blockMax.z - edge); + this.a = a; + this.b = b; + this.color = color; + } + + public Box(DhSectionPos pos, float minY, float maxY, float marginPercent, Color color) + { + this(pos.getSectionBBoxPos(), minY, maxY, marginPercent, color); + } + + public Box(DhSectionPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) + { + this(pos.getSectionBBoxPos(), y, yDiff, hash, marginPercent, color); + } + + } + + ShaderProgram basicShader; + GLVertexBuffer boxBuffer; + GLElementBuffer boxOutlineBuffer; + VertexAttribute va; + boolean init = false; + + private final LinkedList> renderers = new LinkedList<>(); + + public static final class BoxParticle implements Comparable + { + public Box box; + public long startTime; + public long duration; + public float yChange; + + public BoxParticle(Box box, long startTime, long duration, float yChange) + { + this.box = box; + this.startTime = startTime; + this.duration = duration; + this.yChange = yChange; + } + + public BoxParticle(Box box, long ns, float yChange) + { + this(box, System.nanoTime(), ns, yChange); + } + + public BoxParticle(Box box, double s, float yChange) + { + this(box, System.nanoTime(), (long) (s * 1000000000), yChange); + } + + @Override + public int compareTo(@NotNull DebugRenderer.BoxParticle o) + { + return Long.compare(startTime + duration, o.startTime + o.duration); + } + + Box getBox() + { + long now = System.nanoTime(); + float percent = (now - startTime) / (float) duration; + percent = (float) Math.pow(percent, 4); + float yDiff = yChange * percent; + return new Box(new Vec3f(box.a.x, box.a.y + yDiff, box.a.z), new Vec3f(box.b.x, box.b.y + yDiff, box.b.z), box.color); + } + + boolean isDead(long time) + { + return time - startTime > duration; + } + + } + + public static final class BoxWithLife implements IDebugRenderable, Closeable + { + public Box box; + public BoxParticle particaleOnClose; + + public BoxWithLife(Box box, long ns, float yChange, Color deathColor) + { + this.box = box; + this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), -1, ns, yChange); + DebugRenderer.register(this); + } + + public BoxWithLife(Box box, long ns, float yChange) + { + this(box, ns, yChange, box.color); + } + + public BoxWithLife(Box box, double s, float yChange, Color deathColor) + { + this.box = box; + this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), s, yChange); + } + + public BoxWithLife(Box box, double s, float yChange) + { + this(box, s, yChange, box.color); + } + + @Override + public void debugRender(DebugRenderer r) + { + r.renderBox(box); + } + + @Override + public void close() + { + makeParticle(new BoxParticle(particaleOnClose.getBox(), System.nanoTime(), particaleOnClose.duration, particaleOnClose.yChange)); + DebugRenderer.unregister(this); + } + + } + + private final PriorityBlockingQueue particles = new PriorityBlockingQueue<>(); + + public static void unregister(IDebugRenderable r) + { + if (INSTANCE == null) return; + INSTANCE.removeRenderer(r); + } + + public static void makeParticle(BoxParticle particle) + { + if (INSTANCE == null) return; + if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return; + INSTANCE.particles.add(particle); + } + + private void removeRenderer(IDebugRenderable r) + { + synchronized (renderers) + { + Iterator> it = renderers.iterator(); + while (it.hasNext()) + { + WeakReference ref = it.next(); + if (ref.get() == null) + { + it.remove(); + continue; + } + if (ref.get() == r) + { + it.remove(); + return; + } + } + } + } + + public void init() + { + if (init) return; + init = true; + va = VertexAttribute.create(); + va.bind(); + // Pos\ + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec3Pointer(false)); + va.completeAndCheck(Float.BYTES * 3); + basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", + "fragColor", new String[]{"vPosition"}); + createBuffer(); + } + + private void createBuffer() + { + ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(box_vertices); + buffer.rewind(); + boxBuffer = new GLVertexBuffer(false); + boxBuffer.bind(); + boxBuffer.uploadBuffer(buffer, 8, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); + + buffer = ByteBuffer.allocateDirect(box_outline_indices.length * Integer.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asIntBuffer().put(box_outline_indices); + buffer.rewind(); + boxOutlineBuffer = new GLElementBuffer(false); + boxOutlineBuffer.bind(); + boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + } + + public void addRenderer(IDebugRenderable r) + { + if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return; + synchronized (renderers) + { + renderers.add(new WeakReference<>(r)); + } + } + + public static void register(IDebugRenderable r) + { + if (INSTANCE == null) return; + INSTANCE.addRenderer(r); + } + + private Mat4f transform_this_frame; + private Vec3f camf; + + public void renderBox(Box box) + { + Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - camf.x, box.a.y - camf.y, box.a.z - camf.z); + boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); + Mat4f t = transform_this_frame.copy(); + t.multiply(boxTransform); + basicShader.setUniform(basicShader.getUniformLocation("transform"), t); + basicShader.setUniform(basicShader.getUniformLocation("uColor"), box.color); + GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0); + } + + public void render(Mat4f transform) + { + if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return; + + transform_this_frame = transform; + Vec3d cam = MC_RENDER.getCameraExactPosition(); + camf = new Vec3f((float) cam.x, (float) cam.y, (float) cam.z); + + GLState state = new GLState(); + init(); + + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); + GL32.glViewport(0, 0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight()); + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE); + //GL32.glLineWidth(2); + GL32.glEnable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_STENCIL_TEST); + GL32.glDisable(GL32.GL_BLEND); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + + basicShader.bind(); + va.bind(); + va.bindBufferToAllBindingPoint(boxBuffer.getId()); + + boxOutlineBuffer.bind(); + + synchronized (renderers) + { + Iterator> it = renderers.iterator(); + while (it.hasNext()) + { + WeakReference ref = it.next(); + IDebugRenderable r = ref.get(); + if (r == null) + { + it.remove(); + continue; + } + r.debugRender(this); + } + } + + BoxParticle head = null; + while ((head = particles.poll()) != null && head.isDead(System.nanoTime())) + { + } + if (head != null) + { + particles.add(head); + } + particles.forEach(b -> renderBox(b.getBox())); + + state.restore(); + } + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/IDebugRenderable.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/IDebugRenderable.java index 2285fad1b..2cdcda546 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/IDebugRenderable.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/IDebugRenderable.java @@ -1,5 +1,7 @@ package com.seibel.distanthorizons.core.render.renderer; -public interface IDebugRenderable { - void debugRender(DebugRenderer r); +public interface IDebugRenderable +{ + void debugRender(DebugRenderer r); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index 7cdf96b5b..b32469d15 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -43,58 +43,59 @@ public class LodRenderProgram extends ShaderProgram private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class); public final VertexAttribute vao; - + // Uniforms public final int combinedMatUniform; public final int modelOffsetUniform; public final int worldYOffsetUniform; - + public final int mircoOffsetUniform; - + public final int earthRadiusUniform; - + public final int lightMapUniform; - + // Fog Uniforms - + // Noise Uniforms public final int noiseEnabledUniform; public final int noiseStepsUniform; public final int noiseIntensityUniform; public final int noiseDropoffUniform; - + // Debug Uniform public final int whiteWorldUniform; - + private final LodFogConfig fogConfig; - + // This will bind VertexAttribute - public LodRenderProgram(LodFogConfig fogConfig) { - super(() -> Shader.loadFile(fogConfig.earthCurveRatio!=0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH, + public LodRenderProgram(LodFogConfig fogConfig) + { + super(() -> Shader.loadFile(fogConfig.earthCurveRatio != 0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH, false, new StringBuilder()).toString(), () -> Shader.loadFile(FRAGMENT_SHADER_PATH, false, new StringBuilder()).toString(), - "fragColor", new String[] { "vPosition", "color" }); + "fragColor", new String[]{"vPosition", "color"}); this.fogConfig = fogConfig; - + combinedMatUniform = getUniformLocation("combinedMatrix"); modelOffsetUniform = getUniformLocation("modelOffset"); worldYOffsetUniform = tryGetUniformLocation("worldYOffset"); mircoOffsetUniform = getUniformLocation("mircoOffset"); earthRadiusUniform = tryGetUniformLocation("earthRadius"); - + lightMapUniform = getUniformLocation("lightMap"); - - + + // Noise Uniforms noiseEnabledUniform = getUniformLocation("noiseEnabled"); noiseStepsUniform = getUniformLocation("noiseSteps"); noiseIntensityUniform = getUniformLocation("noiseIntensity"); noiseDropoffUniform = getUniformLocation("noiseDropoff"); - + // Debug Uniform whiteWorldUniform = getUniformLocation("whiteWorld"); - - + + // TODO: Add better use of the LODFormat thing int vertexByteCount = LodUtil.LOD_VERTEX_FORMAT.getByteSize(); if (GLProxy.getInstance().VertexAttributeBufferBindingSupported) @@ -107,23 +108,26 @@ public class LodRenderProgram extends ShaderProgram //vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addVec3Pointer(false)); // 4+4+4 vao.setVertexAttribute(0, 1, VertexAttribute.VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 //vao.setVertexAttribute(0, lightAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(2, false)); // +4 due to how it aligns - try { + try + { vao.completeAndCheck(vertexByteCount); - } catch (RuntimeException e) { + } + catch (RuntimeException e) + { System.out.println(LodUtil.LOD_VERTEX_FORMAT); throw e; } - + if (earthRadiusUniform != -1) setUniform(earthRadiusUniform, /*6371KM*/ 6371000.0f / fogConfig.earthCurveRatio); - + // Noise Uniforms setUniform(noiseEnabledUniform, fogConfig.noiseEnable); setUniform(noiseStepsUniform, fogConfig.noiseSteps); setUniform(noiseIntensityUniform, fogConfig.noiseIntensity); setUniform(noiseDropoffUniform, fogConfig.noiseDropoff); } - + // If not usable, return a new LodFogConfig to be constructed public LodFogConfig isShaderUsable() // TODO replace with a config listener, look at LodFogConfig for more info { @@ -136,50 +140,56 @@ public class LodRenderProgram extends ShaderProgram } // Override ShaderProgram.bind() - public void bind() { + public void bind() + { super.bind(); vao.bind(); } // Override ShaderProgram.unbind() - public void unbind() { + public void unbind() + { super.unbind(); vao.unbind(); } // Override ShaderProgram.free() - public void free() { + public void free() + { vao.free(); super.free(); } - public void bindVertexBuffer(int vbo) { + public void bindVertexBuffer(int vbo) + { vao.bindBufferToAllBindingPoint(vbo); } - public void unbindVertexBuffer() { + public void unbindVertexBuffer() + { vao.unbindBuffersFromAllBindingPoint(); } public void fillUniformData(Mat4f combinedMatrix, int lightmapBindPoint, int worldYOffset, int vanillaDrawDistance) { - super.bind(); + super.bind(); vanillaDrawDistance += 32; // Give it a 2 chunk boundary for near fog. // uniforms setUniform(combinedMatUniform, combinedMatrix); setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset - + // setUniform(skyLightUniform, skyLight); setUniform(lightMapUniform, lightmapBindPoint); - - if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float)worldYOffset); + + if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) worldYOffset); // Debug setUniform(whiteWorldUniform, Config.Client.Advanced.Debugging.enableWhiteWorld.get()); - + } - - public void setModelPos(Vec3f modelPos) { + + public void setModelPos(Vec3f modelPos) + { setUniform(modelOffsetUniform, modelPos); } - + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 1e545c80c..ee57e425e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -61,19 +61,19 @@ public class LodRenderer public static final ConfigBasedLogger EVENT_LOGGER = new ConfigBasedLogger(LogManager.getLogger(LodRenderer.class), () -> Config.Client.Advanced.Logging.logRendererBufferEvent.get()); public static ConfigBasedSpamLogger tickLogger = new ConfigBasedSpamLogger(LogManager.getLogger(LodRenderer.class), - () -> Config.Client.Advanced.Logging.logRendererBufferEvent.get(),1); + () -> Config.Client.Advanced.Logging.logRendererBufferEvent.get(), 1); public static final boolean ENABLE_DRAW_LAG_SPIKE_LOGGING = false; public static final boolean ENABLE_DUMP_GL_STATE = true; public static final long DRAW_LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS); - + public static final boolean ENABLE_IBO = true; - + // TODO make these private, the LOD Builder can get these variables from the config itself public static boolean transparencyEnabled = true; public static boolean fakeOceanFloor = true; - - public void setupOffset(DhBlockPos pos) + + public void setupOffset(DhBlockPos pos) { Vec3d cam = MC_RENDER.getCameraExactPosition(); Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z)); @@ -81,18 +81,18 @@ public class LodRenderer this.shaderProgram.bind(); this.shaderProgram.setModelPos(modelPos); } - + public void drawVbo(GLVertexBuffer vbo) { vbo.bind(); this.shaderProgram.bindVertexBuffer(vbo.getId()); - GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount()/4)*6, // TODO what does the 4 and 6 here represent? + GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount() / 4) * 6, // TODO what does the 4 and 6 here represent? this.quadIBO.getType(), 0); vbo.unbind(); } public Vec3f getLookVector() { return MC_RENDER.getLookAtVector(); } - - + + public static class LagSpikeCatcher { long timer = System.nanoTime(); @@ -103,31 +103,33 @@ public class LodRenderer { if (!ENABLE_DRAW_LAG_SPIKE_LOGGING) { - return; + return; } this.timer = System.nanoTime() - this.timer; if (this.timer > DRAW_LAG_SPIKE_THRESHOLD_NS) - { + { //4 ms EVENT_LOGGER.debug("NOTE: " + source + " took " + Duration.ofNanos(this.timer) + "!"); } } + } + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - + public EDebugRendering previousDebugMode = null; public final RenderBufferHandler bufferHandler; - + // The shader program LodRenderProgram shaderProgram = null; public QuadElementBuffer quadIBO = null; public boolean isSetupComplete = false; - + public LodRenderer(RenderBufferHandler bufferHandler) { this.bufferHandler = bufferHandler; } - + private boolean rendererClosed = false; public void close() { @@ -137,18 +139,18 @@ public class LodRenderer return; } - EVENT_LOGGER.info("Shutting down "+LodRenderer.class.getSimpleName()+"..."); + EVENT_LOGGER.info("Shutting down " + LodRenderer.class.getSimpleName() + "..."); this.rendererClosed = true; GLProxy.getInstance().recordOpenGlCall(this::cleanup); this.bufferHandler.close(); - EVENT_LOGGER.info("Finished shutting down "+LodRenderer.class.getSimpleName()); + EVENT_LOGGER.info("Finished shutting down " + LodRenderer.class.getSimpleName()); } - + public void drawLODs(Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, float partialTicks, IProfilerWrapper profiler) { - if (this.rendererClosed) + if (this.rendererClosed) { EVENT_LOGGER.error("drawLODs() called after close()!"); return; @@ -160,7 +162,7 @@ public class LodRenderer GLState minecraftGlState = new GLState(); if (ENABLE_DUMP_GL_STATE) { - tickLogger.debug("Saving GL state: "+minecraftGlState); + tickLogger.debug("Saving GL state: " + minecraftGlState); } drawSaveGLState.end("drawSaveGLState"); @@ -322,17 +324,17 @@ public class LodRenderer /** Setup all render objects - REQUIRES to be in render thread */ private void setup() { - if (this.isSetupComplete) + if (this.isSetupComplete) { EVENT_LOGGER.warn("Renderer setup called but it has already completed setup!"); return; } - if (!GLProxy.hasInstance()) + if (!GLProxy.hasInstance()) { EVENT_LOGGER.warn("Renderer setup called but GLProxy has not yet been setup!"); return; } - + EVENT_LOGGER.info("Setting up renderer"); this.isSetupComplete = true; this.shaderProgram = new LodRenderProgram(LodFogConfig.generateFogConfig()); // TODO this doesn't actually use the fog config @@ -343,7 +345,7 @@ public class LodRenderer } EVENT_LOGGER.info("Renderer setup complete"); } - + private Color getFogColor(float partialTicks) { Color fogColor; @@ -360,25 +362,25 @@ public class LodRenderer return fogColor; } private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); } - + //======================// // Cleanup Functions // //======================// - - /** + + /** * cleanup and free all render objects. REQUIRES to be in render thread - * (Many objects are Native, outside of JVM, and need manual cleanup) - */ - private void cleanup() + * (Many objects are Native, outside of JVM, and need manual cleanup) + */ + private void cleanup() { - if (!this.isSetupComplete) + if (!this.isSetupComplete) { EVENT_LOGGER.warn("Renderer cleanup called but Renderer has not completed setup!"); return; } - if (!GLProxy.hasInstance()) + if (!GLProxy.hasInstance()) { EVENT_LOGGER.warn("Renderer Cleanup called but the GLProxy has never been initalized!"); return; @@ -393,4 +395,5 @@ public class LodRenderer } EVENT_LOGGER.info("Renderer Cleanup Complete"); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java index 63735ae92..1cefef683 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.render.renderer; import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod; @@ -38,100 +38,108 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; -public class TestRenderer { - - public TestRenderer() {} - - public static final ConfigBasedLogger logger = new ConfigBasedLogger( - LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT); - public static final ConfigBasedSpamLogger spamLogger = new ConfigBasedSpamLogger( - LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT, 1); - private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - ShaderProgram basicShader; - GLVertexBuffer sameContextBuffer; - GLVertexBuffer sharedContextBuffer; - VertexAttribute va; - boolean init = false; - - public void init() { - if (init) return; - logger.info("init"); - init = true; - va = VertexAttribute.create(); - va.bind(); - // Pos - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - // Color - va.setVertexAttribute(0, 1, VertexAttribute.VertexPointer.addVec4Pointer(false)); - va.completeAndCheck(Float.BYTES * 6); - basicShader = new ShaderProgram("shaders/test/vert.vert", "shaders/test/frag.frag", - "fragColor", new String[]{"vPosition", "color"}); - createBuffer(); - } - - // Render a square with uv color - private static final float[] vertices = { - // PosX,Y, ColorR,G,B,A - -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.4f, -0.4f, 1.0f, 0.0f, 0.0f, 1.0f, - 0.3f, 0.3f, 1.0f, 1.0f, 0.0f, 0.0f, - -0.2f, 0.2f, 0.0f, 1.0f, 1.0f, 1.0f - }; - - private static GLVertexBuffer createTextingBuffer() { - ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES); - // Fill buffer with the vertices. - buffer = buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(vertices); - buffer.rewind(); - GLVertexBuffer vbo = new GLVertexBuffer(false); - vbo.bind(); - vbo.uploadBuffer(buffer, 4, EGpuUploadMethod.DATA, vertices.length * Float.BYTES); - return vbo; - } - - private void createBuffer() { - GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); - GLProxy.ensureAllGLJobCompleted(); - sameContextBuffer = createTextingBuffer(); - } - - public void render() { - spamLogger.debug("rendering"); - - GLState state = new GLState(); - init(); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight()); - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); - GL32.glDisable(GL32.GL_CULL_FACE); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_STENCIL_TEST); - GL32.glDisable(GL32.GL_BLEND); - //GL32.glDisable(GL32.GL_SCISSOR_TEST); - - basicShader.bind(); - va.bind(); - - // Switch between the two buffers per second - if (System.currentTimeMillis() % 2000 < 1000) { - sameContextBuffer.bind(); - va.bindBufferToAllBindingPoint(sameContextBuffer.getId()); - spamLogger.debug("same context buffer"); - } else { - sameContextBuffer.bind(); - va.bindBufferToAllBindingPoint(sharedContextBuffer.getId()); - spamLogger.debug("shared context buffer"); - } - // Render the square - GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4); - GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); - - state.restore(); - spamLogger.incLogTries(); - } - - - +public class TestRenderer +{ + + public TestRenderer() { } + + public static final ConfigBasedLogger logger = new ConfigBasedLogger( + LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT); + public static final ConfigBasedSpamLogger spamLogger = new ConfigBasedSpamLogger( + LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT, 1); + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + ShaderProgram basicShader; + GLVertexBuffer sameContextBuffer; + GLVertexBuffer sharedContextBuffer; + VertexAttribute va; + boolean init = false; + + public void init() + { + if (init) return; + logger.info("init"); + init = true; + va = VertexAttribute.create(); + va.bind(); + // Pos + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + // Color + va.setVertexAttribute(0, 1, VertexAttribute.VertexPointer.addVec4Pointer(false)); + va.completeAndCheck(Float.BYTES * 6); + basicShader = new ShaderProgram("shaders/test/vert.vert", "shaders/test/frag.frag", + "fragColor", new String[]{"vPosition", "color"}); + createBuffer(); + } + + // Render a square with uv color + private static final float[] vertices = { + // PosX,Y, ColorR,G,B,A + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, + 0.4f, -0.4f, 1.0f, 0.0f, 0.0f, 1.0f, + 0.3f, 0.3f, 1.0f, 1.0f, 0.0f, 0.0f, + -0.2f, 0.2f, 0.0f, 1.0f, 1.0f, 1.0f + }; + + private static GLVertexBuffer createTextingBuffer() + { + ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES); + // Fill buffer with the vertices. + buffer = buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(vertices); + buffer.rewind(); + GLVertexBuffer vbo = new GLVertexBuffer(false); + vbo.bind(); + vbo.uploadBuffer(buffer, 4, EGpuUploadMethod.DATA, vertices.length * Float.BYTES); + return vbo; + } + + private void createBuffer() + { + GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); + GLProxy.ensureAllGLJobCompleted(); + sameContextBuffer = createTextingBuffer(); + } + + public void render() + { + spamLogger.debug("rendering"); + + GLState state = new GLState(); + init(); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); + GL32.glViewport(0, 0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight()); + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); + GL32.glDisable(GL32.GL_CULL_FACE); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_STENCIL_TEST); + GL32.glDisable(GL32.GL_BLEND); + //GL32.glDisable(GL32.GL_SCISSOR_TEST); + + basicShader.bind(); + va.bind(); + + // Switch between the two buffers per second + if (System.currentTimeMillis() % 2000 < 1000) + { + sameContextBuffer.bind(); + va.bindBufferToAllBindingPoint(sameContextBuffer.getId()); + spamLogger.debug("same context buffer"); + } + else + { + sameContextBuffer.bind(); + va.bindBufferToAllBindingPoint(sharedContextBuffer.getId()); + spamLogger.debug("shared context buffer"); + } + // Render the square + GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4); + GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); + + state.restore(); + spamLogger.incLogTries(); + } + + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java index a26b1977a..0cbf31ca4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/AbstractShaderRenderer.java @@ -14,150 +14,158 @@ import org.lwjgl.opengl.GL32; import java.nio.ByteBuffer; import java.nio.ByteOrder; -public abstract class AbstractShaderRenderer { - protected static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - private static final float[] box_vertices = { - -1, -1, - 1, -1, - 1, 1, - -1, -1, - 1, 1, - -1, 1, - }; - - protected final ShaderProgram shader; - protected final ShaderProgram applyShader; - public GLVertexBuffer boxBuffer; - protected VertexAttribute va; +public abstract class AbstractShaderRenderer +{ + protected static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + private static final float[] box_vertices = { + -1, -1, + 1, -1, + 1, 1, + -1, -1, + 1, 1, + -1, 1, + }; + + protected final ShaderProgram shader; + protected final ShaderProgram applyShader; + public GLVertexBuffer boxBuffer; + protected VertexAttribute va; boolean init = false; - - private int width = -1; - private int height = -1; - private int framebuffer = -1; - private int shaderTexture = -1; - - - protected AbstractShaderRenderer(ShaderProgram shader) { - this(shader, null); - } - - protected AbstractShaderRenderer(ShaderProgram shader, ShaderProgram applyShader) { - this.shader = shader; - this.applyShader = applyShader; - } - - private void init() - { + + private int width = -1; + private int height = -1; + private int framebuffer = -1; + private int shaderTexture = -1; + + + protected AbstractShaderRenderer(ShaderProgram shader) + { + this(shader, null); + } + + protected AbstractShaderRenderer(ShaderProgram shader, ShaderProgram applyShader) + { + this.shader = shader; + this.applyShader = applyShader; + } + + private void init() + { if (init) return; init = true; - - va = VertexAttribute.create(); - va.bind(); - // Pos - setVertexAttributes(); - va.completeAndCheck(Float.BYTES * 2); - - // Some shader stuff needs to be set a bit later than - this.postInit(); - // Framebuffer - this.createBuffer(); - } - - /** Sets all the vertex attributes */ - void setVertexAttributes() { - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - }; - /** Overwrite this to apply uniforms to the shader */ - void setShaderUniforms(float partialTicks) {}; - /** Overwrite this to apply uniforms to the apply shader */ - void setApplyShaderUniforms(float partialTicks) {}; - /** Overwrite if you need to run something on runtime */ - void postInit() {}; - + + va = VertexAttribute.create(); + va.bind(); + // Pos + setVertexAttributes(); + va.completeAndCheck(Float.BYTES * 2); + + // Some shader stuff needs to be set a bit later than + this.postInit(); + // Framebuffer + this.createBuffer(); + } + + /** Sets all the vertex attributes */ + void setVertexAttributes() + { + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + } + ; + /** Overwrite this to apply uniforms to the shader */ + void setShaderUniforms(float partialTicks) { } + ; + /** Overwrite this to apply uniforms to the apply shader */ + void setApplyShaderUniforms(float partialTicks) { } + ; + /** Overwrite if you need to run something on runtime */ + void postInit() { } + ; + // TODO pass in the Model View and Projection Matrices along with the ticks - public void render(float partialTicks) - { - GLState state = new GLState(); + public void render(float partialTicks) + { + GLState state = new GLState(); this.init(); - int width = MC_RENDER.getTargetFrameBufferViewportWidth(); - int height = MC_RENDER.getTargetFrameBufferViewportHeight(); - - if (this.width != width || this.height != height) + int width = MC_RENDER.getTargetFrameBufferViewportWidth(); + int height = MC_RENDER.getTargetFrameBufferViewportHeight(); + + if (this.width != width || this.height != height) { - this.width = width; - this.height = height; - this.createFramebuffer(width, height); - } - - - - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer); - GL32.glViewport(0, 0, width, height); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_BLEND); - GL32.glDisable(GL32.GL_SCISSOR_TEST); - - - shader.bind(); - this.setShaderUniforms(partialTicks); - va.bind(); - va.bindBufferToAllBindingPoint(boxBuffer.getId()); - - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - - if (applyShader != null) - { - applyShader.bind(); - this.setApplyShaderUniforms(partialTicks); - } - - GL32.glEnable(GL11.GL_BLEND); - GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - + this.width = width; + this.height = height; + this.createFramebuffer(width, height); + } + + + + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer); + GL32.glViewport(0, 0, width, height); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_BLEND); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + + + shader.bind(); + this.setShaderUniforms(partialTicks); + va.bind(); + va.bindBufferToAllBindingPoint(boxBuffer.getId()); + + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); + + if (applyShader != null) + { + applyShader.bind(); + this.setApplyShaderUniforms(partialTicks); + } + + GL32.glEnable(GL11.GL_BLEND); + GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture); + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); + // explicitly unbinding the frame buffer is necessary to prevent GL_CLEAR calls from hitting the wrong buffer - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0); - state.restore(); - } - - - private void createFramebuffer(int width, int height) - { - if (this.framebuffer != -1) + state.restore(); + } + + + private void createFramebuffer(int width, int height) + { + if (this.framebuffer != -1) { - GL32.glDeleteFramebuffers(this.framebuffer); - this.framebuffer = -1; - } - - if (this.shaderTexture != -1) + GL32.glDeleteFramebuffers(this.framebuffer); + this.framebuffer = -1; + } + + if (this.shaderTexture != -1) { - GL32.glDeleteTextures(this.shaderTexture); - this.shaderTexture = -1; - } - - this.framebuffer = GL32.glGenFramebuffers(); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.framebuffer); - - this.shaderTexture = GL32.glGenTextures(); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.shaderTexture); - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.shaderTexture, 0); - } - - private void createBuffer() - { + GL32.glDeleteTextures(this.shaderTexture); + this.shaderTexture = -1; + } + + this.framebuffer = GL32.glGenFramebuffers(); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.framebuffer); + + this.shaderTexture = GL32.glGenTextures(); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.shaderTexture); + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.shaderTexture, 0); + } + + private void createBuffer() + { ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); buffer.order(ByteOrder.nativeOrder()); buffer.asFloatBuffer().put(box_vertices); @@ -165,15 +173,15 @@ public abstract class AbstractShaderRenderer { this.boxBuffer = new GLVertexBuffer(false); this.boxBuffer.bind(); this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - } + } - public void free() - { - this.shader.free(); - if (this.applyShader != null) - { - this.applyShader.free(); - } - } + public void free() + { + this.shader.free(); + if (this.applyShader != null) + { + this.applyShader.free(); + } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java index f9d825b8e..618cf2b00 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/DarkShader.java @@ -2,10 +2,13 @@ package com.seibel.distanthorizons.core.render.renderer.shaders; import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; -public class DarkShader extends AbstractShaderRenderer { - public static DarkShader INSTANCE = new DarkShader(); - - protected DarkShader() { - super(new ShaderProgram("shaders/normal.vert", "shaders/test/dark.frag", "fragColor", new String[] { "vPosition", "color" })); - } +public class DarkShader extends AbstractShaderRenderer +{ + public static DarkShader INSTANCE = new DarkShader(); + + protected DarkShader() + { + super(new ShaderProgram("shaders/normal.vert", "shaders/test/dark.frag", "fragColor", new String[]{"vPosition", "color"})); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java index 4a7edb107..5abae934e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java @@ -17,110 +17,111 @@ import java.awt.*; public class FogShader extends AbstractShaderRenderer { - public static FogShader INSTANCE = new FogShader(LodFogConfig.generateFogConfig()); - private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class); + public static FogShader INSTANCE = new FogShader(LodFogConfig.generateFogConfig()); + private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class); - public final int gModelViewProjectionUniform; - public final int gDepthMapUniform; + public final int gModelViewProjectionUniform; + public final int gDepthMapUniform; - // Fog Uniforms - public final int fogColorUniform; - public final int fogScaleUniform; - public final int fogVerticalScaleUniform; - public final int nearFogStartUniform; - public final int nearFogLengthUniform;; - public final int fullFogModeUniform; + // Fog Uniforms + public final int fogColorUniform; + public final int fogScaleUniform; + public final int fogVerticalScaleUniform; + public final int nearFogStartUniform; + public final int nearFogLengthUniform; + ; + public final int fullFogModeUniform; - public FogShader(LodFogConfig fogConfig) - { - super(new ShaderProgram( + public FogShader(LodFogConfig fogConfig) + { + super(new ShaderProgram( // TODO rename normal.vert to something like "postProcess.vert" - () -> Shader.loadFile("shaders/normal.vert", false, new StringBuilder()).toString(), - () -> fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(), - "fragColor", new String[] { "vPosition" } - )); + () -> Shader.loadFile("shaders/normal.vert", false, new StringBuilder()).toString(), + () -> fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(), + "fragColor", new String[]{"vPosition"} + )); // all uniforms should be tryGet... - // because disabling fog can cause the GLSL to optimize out most (if not all) uniforms + // because disabling fog can cause the GLSL to optimize out most (if not all) uniforms - - this.gModelViewProjectionUniform = this.shader.tryGetUniformLocation("gMvmProj"); - this.gDepthMapUniform = this.shader.tryGetUniformLocation("gDepthMap"); - // Fog uniforms - this.fogColorUniform = this.shader.tryGetUniformLocation("fogColor"); - this.fullFogModeUniform = this.shader.tryGetUniformLocation("fullFogMode"); - this.fogScaleUniform = this.shader.tryGetUniformLocation("fogScale"); - this.fogVerticalScaleUniform = this.shader.tryGetUniformLocation("fogVerticalScale"); - // near fog - this.nearFogStartUniform = this.shader.tryGetUniformLocation("nearFogStart"); - this.nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength"); - } + this.gModelViewProjectionUniform = this.shader.tryGetUniformLocation("gMvmProj"); + this.gDepthMapUniform = this.shader.tryGetUniformLocation("gDepthMap"); + + // Fog uniforms + this.fogColorUniform = this.shader.tryGetUniformLocation("fogColor"); + this.fullFogModeUniform = this.shader.tryGetUniformLocation("fullFogMode"); + this.fogScaleUniform = this.shader.tryGetUniformLocation("fogScale"); + this.fogVerticalScaleUniform = this.shader.tryGetUniformLocation("fogVerticalScale"); + // near fog + this.nearFogStartUniform = this.shader.tryGetUniformLocation("nearFogStart"); + this.nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength"); + } - @Override - void setVertexAttributes() - { - this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - } + @Override + void setVertexAttributes() + { + this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + } - @Override - void setShaderUniforms(float partialTicks) - { - this.shader.bind(); + @Override + void setShaderUniforms(float partialTicks) + { + this.shader.bind(); - int lodDrawDistance = RenderUtil.getFarClipPlaneDistanceInBlocks(); - int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; - vanillaDrawDistance += LodUtil.CHUNK_WIDTH * 2; // Give it a 2 chunk boundary for near fog. + int lodDrawDistance = RenderUtil.getFarClipPlaneDistanceInBlocks(); + int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; + vanillaDrawDistance += LodUtil.CHUNK_WIDTH * 2; // Give it a 2 chunk boundary for near fog. - // bind the depth buffer - if (this.gDepthMapUniform != -1) - { - GL32.glActiveTexture(GL32.GL_TEXTURE3); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - GL32.glUniform1i(this.gDepthMapUniform, 3); - } + // bind the depth buffer + if (this.gDepthMapUniform != -1) + { + GL32.glActiveTexture(GL32.GL_TEXTURE3); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + GL32.glUniform1i(this.gDepthMapUniform, 3); + } - // Fog - if (this.fullFogModeUniform != -1) this.shader.setUniform(this.fullFogModeUniform, MC_RENDER.isFogStateSpecial() ? 1 : 0); - if (this.fogColorUniform != -1) this.shader.setUniform(this.fogColorUniform, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks)); + // Fog + if (this.fullFogModeUniform != -1) this.shader.setUniform(this.fullFogModeUniform, MC_RENDER.isFogStateSpecial() ? 1 : 0); + if (this.fogColorUniform != -1) this.shader.setUniform(this.fogColorUniform, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks)); - float nearFogLen = vanillaDrawDistance * 0.2f / lodDrawDistance; - float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float)Math.sqrt(2.0) : 1.0f) / lodDrawDistance; - if (this.nearFogStartUniform != -1) this.shader.setUniform(this.nearFogStartUniform, nearFogStart); - if (this.nearFogLengthUniform != -1) this.shader.setUniform(this.nearFogLengthUniform, nearFogLen); - if (this.fogScaleUniform != -1) this.shader.setUniform(this.fogScaleUniform, 1.f/lodDrawDistance); - if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f/MC.getWrappedClientWorld().getHeight()); - } - - - - private Color getFogColor(float partialTicks) - { - Color fogColor; - - if (Config.Client.Advanced.Graphics.Fog.colorMode.get() == EFogColorMode.USE_SKY_COLOR) - { - fogColor = MC_RENDER.getSkyColor(); - } - else - { - fogColor = MC_RENDER.getFogColor(partialTicks); - } - - return fogColor; - } - private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); } - + float nearFogLen = vanillaDrawDistance * 0.2f / lodDrawDistance; + float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float) Math.sqrt(2.0) : 1.0f) / lodDrawDistance; + if (this.nearFogStartUniform != -1) this.shader.setUniform(this.nearFogStartUniform, nearFogStart); + if (this.nearFogLengthUniform != -1) this.shader.setUniform(this.nearFogLengthUniform, nearFogLen); + if (this.fogScaleUniform != -1) this.shader.setUniform(this.fogScaleUniform, 1.f / lodDrawDistance); + if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f / MC.getWrappedClientWorld().getHeight()); + } + + + + private Color getFogColor(float partialTicks) + { + Color fogColor; + + if (Config.Client.Advanced.Graphics.Fog.colorMode.get() == EFogColorMode.USE_SKY_COLOR) + { + fogColor = MC_RENDER.getSkyColor(); + } + else + { + fogColor = MC_RENDER.getFogColor(partialTicks); + } + + return fogColor; + } + private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); } + public void setModelViewProjectionMatrix(Mat4f combinedModelViewProjectionMatrix) { - this.shader.bind(); + this.shader.bind(); this.shader.setUniform(this.gModelViewProjectionUniform, combinedModelViewProjectionMatrix); - this.shader.unbind(); + this.shader.unbind(); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java index 5b5915385..102cf4c5f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java @@ -18,183 +18,196 @@ import java.nio.ByteOrder; // TODO: Move over to SSAOShader // For some reason this version looks slightly different to that, even tough there isnt much visible change in the code -public class SSAORenderer { - public static SSAORenderer INSTANCE = new SSAORenderer(); - - public SSAORenderer() { - } - - private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - private static final float[] box_vertices = { - -1, -1, - 1, -1, - 1, 1, - -1, -1, - 1, 1, - -1, 1, - }; - - ShaderProgram ssaoShader; - ShaderProgram applyShader; - GLVertexBuffer boxBuffer; - VertexAttribute va; - boolean init = false; - - private static final int MAX_KERNEL_SIZE = 32; - private float[] kernel = new float[MAX_KERNEL_SIZE * 3]; - - public void init() { - if (init) return; - - init = true; - va = VertexAttribute.create(); - va.bind(); - // Pos - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - va.completeAndCheck(Float.BYTES * 2); - ssaoShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", - "fragColor", new String[]{"vPosition"}); - - applyShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag", - "fragColor", new String[]{"vPosition"}); - - - // Generate kernel - kernel = genKernel(); - // Framebuffer - createBuffer(); - } - - private int width = -1; - private int height = -1; - private int ssaoFramebuffer = -1; - - private int ssaoTexture = -1; - - private void createFramebuffer(int width, int height) { - if (ssaoFramebuffer != -1) { - GL32.glDeleteFramebuffers(ssaoFramebuffer); - ssaoFramebuffer = -1; - } - - if (ssaoTexture != -1) { - GL32.glDeleteTextures(ssaoTexture); - ssaoTexture = -1; - } - - ssaoFramebuffer = GL32.glGenFramebuffers(); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer); - - ssaoTexture = GL32.glGenTextures(); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture); - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); - GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, ssaoTexture, 0); - } - - private void createBuffer() { - ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(box_vertices); - buffer.rewind(); - boxBuffer = new GLVertexBuffer(false); - boxBuffer.bind(); - boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - } - - private static float[] genKernel() { - float[] kernel = new float[MAX_KERNEL_SIZE * 3]; - for (int i = 0; i < MAX_KERNEL_SIZE; i++) { - float sampleX = (float) (Math.random() * 2.0 - 1.0); - float sampleY = (float) (Math.random() * 2.0 - 1.0); - float sampleZ = (float) Math.random(); - - - // Normalize - float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2)); - sampleX /= magnitude; - sampleY /= magnitude; - sampleZ /= magnitude; - - float scale = i / (float) MAX_KERNEL_SIZE; - float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9)); - - sampleX *= interpolatedScale; - sampleY *= interpolatedScale; - sampleZ *= interpolatedScale; - kernel[i * 3] = sampleX; - kernel[i * 3 + 1] = sampleY; - kernel[i * 3 + 2] = sampleZ; - } - return kernel; - } - - public void render(float partialTicks) { - GLState state = new GLState(); - init(); - //GL32.glDepthMask(false); - int width = MC_RENDER.getTargetFrameBufferViewportWidth(); - int height = MC_RENDER.getTargetFrameBufferViewportHeight(); - - if (this.width != width || this.height != height) { - this.width = width; - this.height = height; - createFramebuffer(width, height); - } - - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer); - GL32.glViewport(0, 0, width, height); - GL32.glDisable(GL32.GL_DEPTH_TEST); - GL32.glDisable(GL32.GL_BLEND); - GL32.glDisable(GL32.GL_SCISSOR_TEST); - - - Mat4f perspective = Mat4f.perspective( - (float) MC_RENDER.getFov(partialTicks), - MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(), - RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), - (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2))); - - ssaoShader.bind(); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gProj"), perspective); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gSampleRad"), 3.0f); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gFactor"), 0.8f); - ssaoShader.setUniform(ssaoShader.getUniformLocation("gPower"), 1.0f); - va.bind(); - va.bindBufferToAllBindingPoint(boxBuffer.getId()); - - GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - - GL32.glUniform3fv(ssaoShader.getUniformLocation("gKernel"), kernel); - GL32.glUniform1i(ssaoShader.getUniformLocation("gDepthMap"), 0); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - +public class SSAORenderer +{ + public static SSAORenderer INSTANCE = new SSAORenderer(); + + public SSAORenderer() + { + } + + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + private static final float[] box_vertices = { + -1, -1, + 1, -1, + 1, 1, + -1, -1, + 1, 1, + -1, 1, + }; + + ShaderProgram ssaoShader; + ShaderProgram applyShader; + GLVertexBuffer boxBuffer; + VertexAttribute va; + boolean init = false; + + private static final int MAX_KERNEL_SIZE = 32; + private float[] kernel = new float[MAX_KERNEL_SIZE * 3]; + + public void init() + { + if (init) return; + + init = true; + va = VertexAttribute.create(); + va.bind(); + // Pos + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + va.completeAndCheck(Float.BYTES * 2); + ssaoShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", + "fragColor", new String[]{"vPosition"}); + + applyShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag", + "fragColor", new String[]{"vPosition"}); - applyShader.bind(); - - GL32.glEnable(GL11.GL_BLEND); - GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); - GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); - + // Generate kernel + kernel = genKernel(); + // Framebuffer + createBuffer(); + } + + private int width = -1; + private int height = -1; + private int ssaoFramebuffer = -1; + + private int ssaoTexture = -1; + + private void createFramebuffer(int width, int height) + { + if (ssaoFramebuffer != -1) + { + GL32.glDeleteFramebuffers(ssaoFramebuffer); + ssaoFramebuffer = -1; + } + + if (ssaoTexture != -1) + { + GL32.glDeleteTextures(ssaoTexture); + ssaoTexture = -1; + } + + ssaoFramebuffer = GL32.glGenFramebuffers(); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer); + + ssaoTexture = GL32.glGenTextures(); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture); + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, ssaoTexture, 0); + } + + private void createBuffer() + { + ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(box_vertices); + buffer.rewind(); + boxBuffer = new GLVertexBuffer(false); + boxBuffer.bind(); + boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); + } + + private static float[] genKernel() + { + float[] kernel = new float[MAX_KERNEL_SIZE * 3]; + for (int i = 0; i < MAX_KERNEL_SIZE; i++) + { + float sampleX = (float) (Math.random() * 2.0 - 1.0); + float sampleY = (float) (Math.random() * 2.0 - 1.0); + float sampleZ = (float) Math.random(); + + + // Normalize + float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2)); + sampleX /= magnitude; + sampleY /= magnitude; + sampleZ /= magnitude; + + float scale = i / (float) MAX_KERNEL_SIZE; + float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9)); + + sampleX *= interpolatedScale; + sampleY *= interpolatedScale; + sampleZ *= interpolatedScale; + kernel[i * 3] = sampleX; + kernel[i * 3 + 1] = sampleY; + kernel[i * 3 + 2] = sampleZ; + } + return kernel; + } + + public void render(float partialTicks) + { + GLState state = new GLState(); + init(); + //GL32.glDepthMask(false); + int width = MC_RENDER.getTargetFrameBufferViewportWidth(); + int height = MC_RENDER.getTargetFrameBufferViewportHeight(); + + if (this.width != width || this.height != height) + { + this.width = width; + this.height = height; + createFramebuffer(width, height); + } + + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer); + GL32.glViewport(0, 0, width, height); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_BLEND); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + + + Mat4f perspective = Mat4f.perspective( + (float) MC_RENDER.getFov(partialTicks), + MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(), + RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), + (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2))); + + ssaoShader.bind(); + ssaoShader.setUniform(ssaoShader.getUniformLocation("gProj"), perspective); + ssaoShader.setUniform(ssaoShader.getUniformLocation("gSampleRad"), 3.0f); + ssaoShader.setUniform(ssaoShader.getUniformLocation("gFactor"), 0.8f); + ssaoShader.setUniform(ssaoShader.getUniformLocation("gPower"), 1.0f); + va.bind(); + va.bindBufferToAllBindingPoint(boxBuffer.getId()); + GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture); - GL32.glUniform1i(applyShader.getUniformLocation("gSSAOMap"), 0); - GL32.glActiveTexture(GL32.GL_TEXTURE1); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - GL32.glUniform1i(applyShader.getUniformLocation("gDepthMap"), 1); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); - GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - + GL32.glUniform3fv(ssaoShader.getUniformLocation("gKernel"), kernel); + GL32.glUniform1i(ssaoShader.getUniformLocation("gDepthMap"), 0); + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); - state.restore(); - } - - public void free() { - ssaoShader.free(); - applyShader.free(); - } + + + applyShader.bind(); + + GL32.glEnable(GL11.GL_BLEND); + GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer()); + + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture); + GL32.glUniform1i(applyShader.getUniformLocation("gSSAOMap"), 0); + GL32.glActiveTexture(GL32.GL_TEXTURE1); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId()); + GL32.glUniform1i(applyShader.getUniformLocation("gDepthMap"), 1); + + GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6); + + + state.restore(); + } + + public void free() + { + ssaoShader.free(); + applyShader.free(); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java index d7fb1e8d8..305c7fe34 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java @@ -7,75 +7,83 @@ import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.lwjgl.opengl.GL32; -public class SSAOShader extends AbstractShaderRenderer { - public static SSAOShader INSTANCE = new SSAOShader(); - - private static final int MAX_KERNEL_SIZE = 32; - private float[] kernel = new float[MAX_KERNEL_SIZE * 3]; - - - public SSAOShader() { - super( - new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", - "fragColor", new String[]{"vPosition"}), - new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag", - "fragColor", new String[]{"vPosition"}) - ); - - } - @Override - void postInit() { - // Generate kernel - kernel = genKernel(); - } - - @Override - void setVertexAttributes() { - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); - } - - @Override - void setShaderUniforms(float partialTicks) { - Mat4f perspective = Mat4f.perspective( - (float) MC_RENDER.getFov(partialTicks), - MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(), - RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), - (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2))); - - - this.shader.setUniform(this.shader.getUniformLocation("gProj"), perspective); - this.shader.setUniform(this.shader.getUniformLocation("gSampleRad"), 3.0f); - this.shader.setUniform(this.shader.getUniformLocation("gFactor"), 0.8f); - this.shader.setUniform(this.shader.getUniformLocation("gPower"), 1.0f); - - GL32.glUniform3fv(this.shader.getUniformLocation("gKernel"), kernel); - GL32.glUniform1i(this.shader.getUniformLocation("gDepthMap"), 0); - } - - private static float[] genKernel() { - float[] kernel = new float[MAX_KERNEL_SIZE * 3]; - for (int i = 0; i < MAX_KERNEL_SIZE; i++) { - float sampleX = (float) (Math.random() * 2.0 - 1.0); - float sampleY = (float) (Math.random() * 2.0 - 1.0); - float sampleZ = (float) Math.random(); - - - // Normalize - float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2)); - sampleX /= magnitude; - sampleY /= magnitude; - sampleZ /= magnitude; - - float scale = i / (float) MAX_KERNEL_SIZE; - float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9)); - - sampleX *= interpolatedScale; - sampleY *= interpolatedScale; - sampleZ *= interpolatedScale; - kernel[i * 3] = sampleX; - kernel[i * 3 + 1] = sampleY; - kernel[i * 3 + 2] = sampleZ; - } - return kernel; - } +public class SSAOShader extends AbstractShaderRenderer +{ + public static SSAOShader INSTANCE = new SSAOShader(); + + private static final int MAX_KERNEL_SIZE = 32; + private float[] kernel = new float[MAX_KERNEL_SIZE * 3]; + + + public SSAOShader() + { + super( + new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", + "fragColor", new String[]{"vPosition"}), + new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag", + "fragColor", new String[]{"vPosition"}) + ); + + } + @Override + void postInit() + { + // Generate kernel + kernel = genKernel(); + } + + @Override + void setVertexAttributes() + { + va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false)); + } + + @Override + void setShaderUniforms(float partialTicks) + { + Mat4f perspective = Mat4f.perspective( + (float) MC_RENDER.getFov(partialTicks), + MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(), + RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks), + (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2))); + + + this.shader.setUniform(this.shader.getUniformLocation("gProj"), perspective); + this.shader.setUniform(this.shader.getUniformLocation("gSampleRad"), 3.0f); + this.shader.setUniform(this.shader.getUniformLocation("gFactor"), 0.8f); + this.shader.setUniform(this.shader.getUniformLocation("gPower"), 1.0f); + + GL32.glUniform3fv(this.shader.getUniformLocation("gKernel"), kernel); + GL32.glUniform1i(this.shader.getUniformLocation("gDepthMap"), 0); + } + + private static float[] genKernel() + { + float[] kernel = new float[MAX_KERNEL_SIZE * 3]; + for (int i = 0; i < MAX_KERNEL_SIZE; i++) + { + float sampleX = (float) (Math.random() * 2.0 - 1.0); + float sampleY = (float) (Math.random() * 2.0 - 1.0); + float sampleZ = (float) Math.random(); + + + // Normalize + float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2)); + sampleX /= magnitude; + sampleY /= magnitude; + sampleZ /= magnitude; + + float scale = i / (float) MAX_KERNEL_SIZE; + float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9)); + + sampleX *= interpolatedScale; + sampleY *= interpolatedScale; + sampleZ *= interpolatedScale; + kernel[i * 3] = sampleX; + kernel[i * 3 + 1] = sampleY; + kernel[i * 3 + 2] = sampleZ; + } + return kernel; + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java index 429a64190..af8592955 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/DefaultLodVertexFormats.java @@ -24,7 +24,7 @@ import com.google.common.collect.ImmutableList; /** * A (almost) exact copy of MC's * DefaultVertexFormats class. - * + * * @author James Seibel * @version 12-8-2021 */ @@ -40,14 +40,15 @@ public class DefaultLodVertexFormats public static final LodVertexFormatElement ELEMENT_LIGHT = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.UBYTE, 1, false); - public static final LodVertexFormat POSITION = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).build()); - public static final LodVertexFormat POSITION_COLOR = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).build()); - public static final LodVertexFormat POSITION_COLOR_LIGHTMAP = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_LIGHT_MAP_UV).build()); - public static final LodVertexFormat POSITION_TEX = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_UV).build()); - public static final LodVertexFormat POSITION_COLOR_TEX = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).build()); - public static final LodVertexFormat POSITION_COLOR_TEX_LIGHTMAP = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).add(ELEMENT_LIGHT_MAP_UV).build()); + public static final LodVertexFormat POSITION = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).build()); + public static final LodVertexFormat POSITION_COLOR = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).build()); + public static final LodVertexFormat POSITION_COLOR_LIGHTMAP = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_LIGHT_MAP_UV).build()); + public static final LodVertexFormat POSITION_TEX = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_UV).build()); + public static final LodVertexFormat POSITION_COLOR_TEX = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).build()); + public static final LodVertexFormat POSITION_COLOR_TEX_LIGHTMAP = new LodVertexFormat(ImmutableList.builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).add(ELEMENT_LIGHT_MAP_UV).build()); - public static final LodVertexFormat POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT = new LodVertexFormat(ImmutableList.builder() + public static final LodVertexFormat POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT = new LodVertexFormat(ImmutableList.builder() .add(ELEMENT_POSITION).add(ELEMENT_PADDING).add(ELEMENT_LIGHT) - .add(ELEMENT_COLOR).build()); + .add(ELEMENT_COLOR).build()); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormat.java b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormat.java index 44710cdd4..952ead328 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormat.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormat.java @@ -33,7 +33,7 @@ import it.unimi.dsi.fastutil.ints.IntList; * A (almost) exact copy of Minecraft's * VertexFormat class, several methods * were commented out since we didn't need them. - * + * * @author James Seibel * @version 12-9-2021 */ @@ -67,15 +67,15 @@ public class LodVertexFormat return this.elements; } - + // Forge added method public int getOffset(int index) { return offsets.getInt(index); } - - - + + + @Override public String toString() { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java index 3d8e26e74..69aa584e6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/vertexFormat/LodVertexFormatElement.java @@ -28,7 +28,7 @@ import org.lwjgl.opengl.GL11; * VertexFormatElement class.
* A number of things were removed from the original * object since we didn't need them, specifically "usage". - * + * * @author James Seibel * @version 11-13-2021 */ @@ -50,7 +50,8 @@ public class LodVertexFormatElement this.isPadding = isPadding; } - public final boolean getIsPadding() { + public final boolean getIsPadding() + { return isPadding; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/AnnotationUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/AnnotationUtil.java index 29f2f31f2..f0e4e4025 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/AnnotationUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/AnnotationUtil.java @@ -32,12 +32,12 @@ public class AnnotationUtil // should never happen // if we got here Java screwed up getting us the enums - throw new IllegalStateException("Enum missing expected value. Enum: ["+enumValue.getClass()+"] doesn't contain the value: ["+enumValue.name()+"]."); + throw new IllegalStateException("Enum missing expected value. Enum: [" + enumValue.getClass() + "] doesn't contain the value: [" + enumValue.name() + "]."); } catch (IllegalAccessException | IllegalArgumentException | ClassCastException e) { // shouldn't happen, but just in case - LOGGER.error("Unable to get annotation for enum: ["+enumValue.getClass()+"]. Unexpected exception: ["+e+"], message: ["+e.getMessage()+"].", e); + LOGGER.error("Unable to get annotation for enum: [" + enumValue.getClass() + "]. Unexpected exception: [" + e + "], message: [" + e.getMessage() + "].", e); return false; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/AtomicsUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/AtomicsUtil.java index e1ec861fd..3ce0bc955 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/AtomicsUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/AtomicsUtil.java @@ -13,79 +13,100 @@ import java.util.function.Predicate; public class AtomicsUtil { - public static T conditionalAndExchange(AtomicReference atomic, Predicate requirement, T newValue) { - while (true) { - T oldValue = atomic.get(); - if (!requirement.test(oldValue)) return oldValue; - if (atomic.weakCompareAndSet(oldValue, newValue)) return oldValue; - } - } + public static T conditionalAndExchange(AtomicReference atomic, Predicate requirement, T newValue) + { + while (true) + { + T oldValue = atomic.get(); + if (!requirement.test(oldValue)) return oldValue; + if (atomic.weakCompareAndSet(oldValue, newValue)) return oldValue; + } + } - public static BooleanObjectImmutablePair conditionalAndExchangeWeak(AtomicReference atomic, Predicate requirement, T newValue) { - T oldValue = atomic.get(); - if (requirement.test(oldValue) && atomic.weakCompareAndSet(oldValue, newValue)) { - return new BooleanObjectImmutablePair<>(true, oldValue); - } else { - return new BooleanObjectImmutablePair<>(false, oldValue); - } - } - - public static T compareAndExchange(AtomicReference atomic, T expected, T newValue) - { - while (true) { - T oldValue = atomic.get(); - if (oldValue != expected) return oldValue; - if (atomic.weakCompareAndSet(expected, newValue)) return expected; - } - } - - public static BooleanObjectImmutablePair compareAndExchangeWeak(AtomicReference atomic, T expected, T newValue) { - T oldValue = atomic.get(); - if (oldValue == expected && atomic.weakCompareAndSet(expected, newValue)) { - return new BooleanObjectImmutablePair<>(true, expected); - } else { - return new BooleanObjectImmutablePair<>(false, oldValue); - } - } - - // Additionally, we implement some helper methods for frequently used atomic operations. // + public static BooleanObjectImmutablePair conditionalAndExchangeWeak(AtomicReference atomic, Predicate requirement, T newValue) + { + T oldValue = atomic.get(); + if (requirement.test(oldValue) && atomic.weakCompareAndSet(oldValue, newValue)) + { + return new BooleanObjectImmutablePair<>(true, oldValue); + } + else + { + return new BooleanObjectImmutablePair<>(false, oldValue); + } + } - // Compare with expected value and set new value if equal. Then return whatever value the atomic now contains. - public static T compareAndSetThenGet(AtomicReference atomic, T expected, T newValue) { - while (true) { - T oldValue = atomic.get(); - if (oldValue != expected) return oldValue; - if (atomic.weakCompareAndSet(expected, newValue)) return newValue; - } - } + public static T compareAndExchange(AtomicReference atomic, T expected, T newValue) + { + while (true) + { + T oldValue = atomic.get(); + if (oldValue != expected) return oldValue; + if (atomic.weakCompareAndSet(expected, newValue)) return expected; + } + } + + public static BooleanObjectImmutablePair compareAndExchangeWeak(AtomicReference atomic, T expected, T newValue) + { + T oldValue = atomic.get(); + if (oldValue == expected && atomic.weakCompareAndSet(expected, newValue)) + { + return new BooleanObjectImmutablePair<>(true, expected); + } + else + { + return new BooleanObjectImmutablePair<>(false, oldValue); + } + } + + // Additionally, we implement some helper methods for frequently used atomic operations. // + + // Compare with expected value and set new value if equal. Then return whatever value the atomic now contains. + public static T compareAndSetThenGet(AtomicReference atomic, T expected, T newValue) + { + while (true) + { + T oldValue = atomic.get(); + if (oldValue != expected) return oldValue; + if (atomic.weakCompareAndSet(expected, newValue)) return newValue; + } + } - // Below is the array version of the above. // + // Below is the array version of the above. // - public static T compareAndExchange(AtomicReferenceArray array, int index, T expected, T newValue) { - while (true) { - T oldValue = array.get(index); - if (oldValue != expected) return oldValue; - if (array.weakCompareAndSet(index, expected, newValue)) return expected; - } - } + public static T compareAndExchange(AtomicReferenceArray array, int index, T expected, T newValue) + { + while (true) + { + T oldValue = array.get(index); + if (oldValue != expected) return oldValue; + if (array.weakCompareAndSet(index, expected, newValue)) return expected; + } + } - public static BooleanObjectImmutablePair compareAndExchangeWeak(AtomicReferenceArray array, int index, T expected, T newValue) { - T oldValue = array.get(index); - if (oldValue == expected && array.weakCompareAndSet(index, expected, newValue)) { - return new BooleanObjectImmutablePair<>(true, expected); - } else { - return new BooleanObjectImmutablePair<>(false, oldValue); - } - } + public static BooleanObjectImmutablePair compareAndExchangeWeak(AtomicReferenceArray array, int index, T expected, T newValue) + { + T oldValue = array.get(index); + if (oldValue == expected && array.weakCompareAndSet(index, expected, newValue)) + { + return new BooleanObjectImmutablePair<>(true, expected); + } + else + { + return new BooleanObjectImmutablePair<>(false, oldValue); + } + } - public static T compareAndSetThenGet(AtomicReferenceArray array, int index, T expected, T newValue) { - while (true) { - T oldValue = array.get(index); - if (oldValue != expected) return oldValue; - if (array.weakCompareAndSet(index, expected, newValue)) return newValue; - } - } + public static T compareAndSetThenGet(AtomicReferenceArray array, int index, T expected, T newValue) + { + while (true) + { + T oldValue = array.get(index); + if (oldValue != expected) return oldValue; + if (array.weakCompareAndSet(index, expected, newValue)) return newValue; + } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java index 228988b73..d75fc9bd6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.util; /** * Handles the bit-wise math used when * dealing with colors stored as integers. - * + * * @author Cola * @author Leonardo Amato * @version 2023-5-15 @@ -36,27 +36,27 @@ public class ColorUtil public static final int INVISIBLE = rgbToInt(0, 0, 0, 0); - public static final int BLACK = rgbToInt(0,0,0); - public static final int WHITE = rgbToInt(255,255,255); - public static final int RED = rgbToInt(255,0,0); - public static final int GREEN = rgbToInt(0,255,0); - public static final int BLUE = rgbToInt(0,0,255); - public static final int YELLOW = rgbToInt(255,255,0); - public static final int CYAN = rgbToInt(0,255,255); - public static final int MAGENTA = rgbToInt(255,0,255); - public static final int ORANGE = rgbToInt(255,128,0); - public static final int PINK = rgbToInt(255,128,128); - public static final int GRAY = rgbToInt(128,128,128); - public static final int LIGHT_GRAY = rgbToInt(192,192,192); - public static final int DARK_GRAY = rgbToInt(64,64,64); - public static final int BROWN = rgbToInt(128,64,0); - public static final int PURPLE = rgbToInt(128,0,128); + public static final int BLACK = rgbToInt(0, 0, 0); + public static final int WHITE = rgbToInt(255, 255, 255); + public static final int RED = rgbToInt(255, 0, 0); + public static final int GREEN = rgbToInt(0, 255, 0); + public static final int BLUE = rgbToInt(0, 0, 255); + public static final int YELLOW = rgbToInt(255, 255, 0); + public static final int CYAN = rgbToInt(0, 255, 255); + public static final int MAGENTA = rgbToInt(255, 0, 255); + public static final int ORANGE = rgbToInt(255, 128, 0); + public static final int PINK = rgbToInt(255, 128, 128); + public static final int GRAY = rgbToInt(128, 128, 128); + public static final int LIGHT_GRAY = rgbToInt(192, 192, 192); + public static final int DARK_GRAY = rgbToInt(64, 64, 64); + public static final int BROWN = rgbToInt(128, 64, 0); + public static final int PURPLE = rgbToInt(128, 0, 128); public static int rgbToInt(int red, int green, int blue) { return (0xFF << 24) | (red << 16) | (green << 8) | blue; } public static int rgbToInt(int alpha, int red, int green, int blue) { return (alpha << 24) | (red << 16) | (green << 8) | blue; } - public static int rgbToInt(float alpha, float red, float green, float blue) { return rgbToInt((int)(alpha*255f), (int)(red*255f), (int)(green*255f), (int)(blue*255f)); } + public static int rgbToInt(float alpha, float red, float green, float blue) { return rgbToInt((int) (alpha * 255f), (int) (red * 255f), (int) (green * 255f), (int) (blue * 255f)); } @@ -117,26 +117,31 @@ public class ColorUtil * Below 2 functions are from: https://stackoverflow.com/questions/13806483/increase-or-decrease-color-saturation * Alpha in [0.0,1.0], hue in [0.0,360.0], Sat in [0.0,1.0], Value in [0.0,1.0] */ - public static float[] argbToAhsv(int color) { + public static float[] argbToAhsv(int color) + { float a = getAlpha(color) / 255f; float r = getRed(color) / 255f; float g = getGreen(color) / 255f; float b = getBlue(color) / 255f; float h, s, v; - float min = Math.min(Math.min( r, g), b ); - float max = Math.max(Math.max( r, g), b ); - + float min = Math.min(Math.min(r, g), b); + float max = Math.max(Math.max(r, g), b); + v = max; float delta = max - min; - if( max != 0f ) + if (max != 0f) s = delta / max; // s - else { + else + { // r = g = b = 0 // s = 0, v is undefined return new float[]{a, 0f, 0f, 0f}; } - if (delta == 0f) { + if (delta == 0f) + { h = 0f; - } else { + } + else + { if (r == max) h = (g - b) / delta; // between yellow & magenta else if (g == max) h = 2f + (b - r) / delta; // between cyan & yellow else h = 4f + (r - g) / delta; // between magenta & cyan @@ -144,52 +149,61 @@ public class ColorUtil if (h < 0f) h += 360f; } - return new float[]{a,h,s,v}; + return new float[]{a, h, s, v}; } /** Alpha in [0.0,1.0], hue in [0.0,360.0], Sat in [0.0,1.0], Value in [0.0,1.0] */ - public static int ahsvToArgb(float a, float h, float s, float v) { + public static int ahsvToArgb(float a, float h, float s, float v) + { if (a > 1.f) a = 1.f; if (h > 360.f) h -= 350.f; if (s > 1.f) s = 1.f; if (v > 1.f) v = 1.f; - - if(s == 0f) { + + if (s == 0f) + { // achromatic (grey) return ColorUtil.rgbToInt(a, v, v, v); } h /= 60f; - int i = (int)(Math.floor(h)); - float f = h-i; // factorial part of h - float p = v * ( 1f - s ); - float q = v * ( 1f - s * f ); - float t = v * ( 1f - s * ( 1f - f ) ); - - switch (i) { - case 0: return ColorUtil.rgbToInt(a, v, t, p); - case 1: return ColorUtil.rgbToInt(a, q, v, p); - case 2: return ColorUtil.rgbToInt(a, p, v, t); - case 3: return ColorUtil.rgbToInt(a, p, q, v); - case 4: return ColorUtil.rgbToInt(a, t, p, v); - default: return ColorUtil.rgbToInt(a, v, p, q); // case 5 + int i = (int) (Math.floor(h)); + float f = h - i; // factorial part of h + float p = v * (1f - s); + float q = v * (1f - s * f); + float t = v * (1f - s * (1f - f)); + + switch (i) + { + case 0: + return ColorUtil.rgbToInt(a, v, t, p); + case 1: + return ColorUtil.rgbToInt(a, q, v, p); + case 2: + return ColorUtil.rgbToInt(a, p, v, t); + case 3: + return ColorUtil.rgbToInt(a, p, q, v); + case 4: + return ColorUtil.rgbToInt(a, t, p, v); + default: + return ColorUtil.rgbToInt(a, v, p, q); // case 5 } -} + } /** Returns the hex value for the Alpha, Red, Green, and Blue channels. */ public static String toHexString(int color) { - return "A:"+Integer.toHexString(getAlpha(color)) + - ",R:" +Integer.toHexString(getRed(color)) + - ",G:" +Integer.toHexString(getGreen(color)) + - ",B:" +Integer.toHexString(getBlue(color)); + return "A:" + Integer.toHexString(getAlpha(color)) + + ",R:" + Integer.toHexString(getRed(color)) + + ",G:" + Integer.toHexString(getGreen(color)) + + ",B:" + Integer.toHexString(getBlue(color)); } /** Returns the int value (0-255) for the Alpha, Red, Green, and Blue channels. */ public static String toString(int color) { - return "A:"+getAlpha(color) + - ",R:" +getRed(color) + - ",G:" +getGreen(color) + - ",B:" +getBlue(color); + return "A:" + getAlpha(color) + + ",R:" + getRed(color) + + ",G:" + getGreen(color) + + ",B:" + getBlue(color); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/EnumUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/EnumUtil.java index 56a181c76..65f954789 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/EnumUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/EnumUtil.java @@ -50,7 +50,7 @@ public class EnumUtil } // no enum found - throw new InvalidObjectException("No Enum of type [" + enumType.getSimpleName() + "] exists with the name [" + enumName + "]. Possible enum values are: [" + createEnumCsv(enumType) + "]" ); + throw new InvalidObjectException("No Enum of type [" + enumType.getSimpleName() + "] exists with the name [" + enumName + "]. Possible enum values are: [" + createEnumCsv(enumType) + "]"); } @@ -98,10 +98,10 @@ public class EnumUtil } // check that each value exists in both enums - for(Enum alphaVal : alphaValues) + for (Enum alphaVal : alphaValues) { boolean valueFoundInBothEnums = false; - for(Enum betaVal : betaValues) + for (Enum betaVal : betaValues) { if (alphaVal.name().equals(betaVal.name())) { @@ -136,6 +136,7 @@ public class EnumUtil this.success = newSuccess; this.failMessage = newFailMessage; } + } } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/FileScanUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/FileScanUtil.java index a948cca22..fced83bda 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/FileScanUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/FileScanUtil.java @@ -19,12 +19,13 @@ import java.util.stream.Stream; // Static util class?? public class FileScanUtil { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final int MAX_SCAN_DEPTH = 5; - public static final String LOD_FILE_POSTFIX = ".lod"; + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + public static final int MAX_SCAN_DEPTH = 5; + public static final String LOD_FILE_POSTFIX = ".lod"; public static final String RENDER_FILE_POSTFIX = ".rlod"; - public static void scanFiles(AbstractSaveStructure saveStructure, ILevelWrapper levelWrapper, + public static void scanFiles( + AbstractSaveStructure saveStructure, ILevelWrapper levelWrapper, @Nullable IFullDataSourceProvider dataSourceProvider, @Nullable ILodRenderSourceProvider renderSourceProvider) { @@ -35,12 +36,12 @@ public class FileScanUtil List files = pathStream.filter( path -> path.toFile().getName().endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile() ).map(Path::toFile).collect(Collectors.toList()); - LOGGER.info("Found "+files.size()+" full data files for "+levelWrapper+" in "+saveStructure); + LOGGER.info("Found " + files.size() + " full data files for " + levelWrapper + " in " + saveStructure); dataSourceProvider.addScannedFile(files); } catch (Exception e) { - LOGGER.error("Failed to scan and collect full data files for "+levelWrapper+" in "+saveStructure, e); + LOGGER.error("Failed to scan and collect full data files for " + levelWrapper + " in " + saveStructure, e); } } @@ -50,13 +51,13 @@ public class FileScanUtil { List files = pathStream.filter( path -> path.toFile().getName().endsWith(RENDER_FILE_POSTFIX) && path.toFile().isFile() - ).map(Path::toFile).collect(Collectors.toList()); - LOGGER.info("Found "+files.size()+" render cache files for "+levelWrapper+" in "+saveStructure); + ).map(Path::toFile).collect(Collectors.toList()); + LOGGER.info("Found " + files.size() + " render cache files for " + levelWrapper + " in " + saveStructure); renderSourceProvider.addScannedFile(files); } catch (Exception e) { - LOGGER.error("Failed to scan and collect cache files for "+levelWrapper+" in "+saveStructure, e); + LOGGER.error("Failed to scan and collect cache files for " + levelWrapper + " in " + saveStructure, e); } } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/FileUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/FileUtil.java index 3ededde0c..a1d620f2d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/FileUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/FileUtil.java @@ -9,10 +9,10 @@ public class FileUtil { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - /** + /** * Renames the given file to FILE_NAME.ORIGINAL_PREFIX.corrupted. * If an existing corrupted file already exists, this will attempt to remove it first. - * + * * @return the file after it has been renamed */ public static File renameCorruptedFile(File file) @@ -25,21 +25,21 @@ public class FileUtil // could happen if there was a corrupted file before that was removed if (!corruptedFile.delete()) { - LOGGER.error("Unable to delete pre-existing corrupted file ["+corruptedFileName+"]."); + LOGGER.error("Unable to delete pre-existing corrupted file [" + corruptedFileName + "]."); } } if (file.renameTo(corruptedFile)) { - LOGGER.error("Renamed corrupted file to ["+corruptedFileName+"]."); + LOGGER.error("Renamed corrupted file to [" + corruptedFileName + "]."); } else { - LOGGER.error("Failed to rename corrupted file to ["+corruptedFileName+"]. Attempting to delete file..."); + LOGGER.error("Failed to rename corrupted file to [" + corruptedFileName + "]. Attempting to delete file..."); if (!file.delete()) { - LOGGER.error("Unable to delete corrupted file ["+corruptedFileName+"]."); + LOGGER.error("Unable to delete corrupted file [" + corruptedFileName + "]."); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/FullDataPointUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/FullDataPointUtil.java index 11dc94c1a..9a82ad3cd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/FullDataPointUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/FullDataPointUtil.java @@ -7,9 +7,9 @@ import org.jetbrains.annotations.Contract; /** * A helper class that is used to access the data from a long * formatted as a full data point.
- * A full data point contains the most information and is the + * A full data point contains the most information and is the * base truth used when creating render data.

- * + * * To access data from a long formatted as a render data point see: {@link RenderDataPointUtil}

* * DataPoint Format:
@@ -38,55 +38,55 @@ public class FullDataPointUtil /** Represents the data held by an empty data point */ public static final int EMPTY_DATA_POINT = 0; - public static final int ID_WIDTH = 32; - public static final int DP_WIDTH = 12; - public static final int Y_WIDTH = 12; - public static final int LIGHT_WIDTH = 8; - public static final int ID_OFFSET = 0; - public static final int DP_OFFSET = ID_OFFSET + ID_WIDTH; + public static final int ID_WIDTH = 32; + public static final int DP_WIDTH = 12; + public static final int Y_WIDTH = 12; + public static final int LIGHT_WIDTH = 8; + public static final int ID_OFFSET = 0; + public static final int DP_OFFSET = ID_OFFSET + ID_WIDTH; /** indicates the Y position where the LOD starts relative to the level's minimum height */ - public static final int Y_OFFSET = DP_OFFSET + DP_WIDTH; - public static final int LIGHT_OFFSET = Y_OFFSET + Y_WIDTH; + public static final int Y_OFFSET = DP_OFFSET + DP_WIDTH; + public static final int LIGHT_OFFSET = Y_OFFSET + Y_WIDTH; - public static final long ID_MASK = Integer.MAX_VALUE; - public static final long INVERSE_ID_MASK = ~ID_MASK; - public static final int DP_MASK = (int)Math.pow(2, DP_WIDTH) - 1; - public static final int Y_MASK = (int)Math.pow(2, Y_WIDTH) - 1; - public static final int LIGHT_MASK = (int)Math.pow(2, LIGHT_WIDTH) - 1; + public static final long ID_MASK = Integer.MAX_VALUE; + public static final long INVERSE_ID_MASK = ~ID_MASK; + public static final int DP_MASK = (int) Math.pow(2, DP_WIDTH) - 1; + public static final int Y_MASK = (int) Math.pow(2, Y_WIDTH) - 1; + public static final int LIGHT_MASK = (int) Math.pow(2, LIGHT_WIDTH) - 1; /** creates a new datapoint with the given values */ - public static long encode(int id, int depth, int y, byte lightPair) + public static long encode(int id, int depth, int y, byte lightPair) { - LodUtil.assertTrue(y >= 0 && y < RenderDataPointUtil.MAX_WORLD_Y_SIZE, "Trying to create datapoint with y[{}] out of range!", y); - LodUtil.assertTrue(depth > 0 && depth < RenderDataPointUtil.MAX_WORLD_Y_SIZE, "Trying to create datapoint with depth[{}] out of range!", depth); - LodUtil.assertTrue(y+depth <= RenderDataPointUtil.MAX_WORLD_Y_SIZE, "Trying to create datapoint with y+depth[{}] out of range!", y+depth); + LodUtil.assertTrue(y >= 0 && y < RenderDataPointUtil.MAX_WORLD_Y_SIZE, "Trying to create datapoint with y[{}] out of range!", y); + LodUtil.assertTrue(depth > 0 && depth < RenderDataPointUtil.MAX_WORLD_Y_SIZE, "Trying to create datapoint with depth[{}] out of range!", depth); + LodUtil.assertTrue(y + depth <= RenderDataPointUtil.MAX_WORLD_Y_SIZE, "Trying to create datapoint with y+depth[{}] out of range!", y + depth); - long data = 0; - data |= id & ID_MASK; - data |= (long) (depth & DP_MASK) << DP_OFFSET; - data |= (long) (y & Y_MASK) << Y_OFFSET; - data |= (long) lightPair << LIGHT_OFFSET; - LodUtil.assertTrue(getId(data) == id && getHeight(data) == depth && getBottomY(data) == y && getLight(data) == Byte.toUnsignedInt(lightPair), - "Trying to create datapoint with id[{}], depth[{}], y[{}], lightPair[{}] but got id[{}], depth[{}], y[{}], lightPair[{}]!", - id, depth, y, Byte.toUnsignedInt(lightPair), getId(data), getHeight(data), getBottomY(data), getLight(data)); + long data = 0; + data |= id & ID_MASK; + data |= (long) (depth & DP_MASK) << DP_OFFSET; + data |= (long) (y & Y_MASK) << Y_OFFSET; + data |= (long) lightPair << LIGHT_OFFSET; + LodUtil.assertTrue(getId(data) == id && getHeight(data) == depth && getBottomY(data) == y && getLight(data) == Byte.toUnsignedInt(lightPair), + "Trying to create datapoint with id[{}], depth[{}], y[{}], lightPair[{}] but got id[{}], depth[{}], y[{}], lightPair[{}]!", + id, depth, y, Byte.toUnsignedInt(lightPair), getId(data), getHeight(data), getBottomY(data), getLight(data)); - return data; - } + return data; + } - /** Returns the BlockState/Biome pair ID used to identify this LOD's color */ - public static int getId(long data) { return (int) (data & ID_MASK); } + /** Returns the BlockState/Biome pair ID used to identify this LOD's color */ + public static int getId(long data) { return (int) (data & ID_MASK); } /** Returns how many blocks tall this LOD is. */ - public static int getHeight(long data) { return (int) ((data >> DP_OFFSET) & DP_MASK); } + public static int getHeight(long data) { return (int) ((data >> DP_OFFSET) & DP_MASK); } /** Returns the block position of the bottom vertices for this LOD relative to the level's minimum height. */ - public static int getBottomY(long data) { return (int) ((data >> Y_OFFSET) & Y_MASK); } - public static int getLight(long data) { return (int) ((data >> LIGHT_OFFSET) & LIGHT_MASK); } + public static int getBottomY(long data) { return (int) ((data >> Y_OFFSET) & Y_MASK); } + public static int getLight(long data) { return (int) ((data >> LIGHT_OFFSET) & LIGHT_MASK); } - public static String toString(long data) { return "[ID:" + getId(data) + ",Y:" + getBottomY(data) + ",Height:" + getHeight(data) + ",Light:" + getLight(data) + "]"; } + public static String toString(long data) { return "[ID:" + getId(data) + ",Y:" + getBottomY(data) + ",Height:" + getHeight(data) + ",Light:" + getLight(data) + "]"; } /** Remaps the biome/blockState ID of the given datapoint */ - @Contract(pure = true) - public static long remap(int[] newIdMapping, long data) { return (data & INVERSE_ID_MASK) | newIdMapping[(int)data]; } + @Contract(pure = true) + public static long remap(int[] newIdMapping, long data) { return (data & INVERSE_ID_MASK) | newIdMapping[(int) data]; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java index 1a96cef6a..487a0dcf7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java @@ -41,7 +41,7 @@ import org.apache.logging.log4j.Logger; /** * This class holds methods and constants that may be used in multiple places. - * + * * @author James Seibel * @version 2022-12-5 */ @@ -73,7 +73,7 @@ public class LodUtil * alpha used when drawing chunks in debug mode */ public static final int DEBUG_ALPHA = 255; // 0 - 25; - + public static final int COLOR_DEBUG_BLACK = ColorUtil.rgbToInt(DEBUG_ALPHA, 0, 0, 0); public static final int COLOR_DEBUG_WHITE = ColorUtil.rgbToInt(DEBUG_ALPHA, 255, 255, 255); public static final int COLOR_INVISIBLE = ColorUtil.rgbToInt(0, 0, 0, 0); @@ -83,8 +83,8 @@ public class LodUtil * In order of nearest to farthest:
* Red, Orange, Yellow, Green, Cyan, Blue, Magenta, white, gray, black */ - public static final int[] DEBUG_DETAIL_LEVEL_COLORS = new int[] { - ColorUtil.rgbToInt(255,0,0), ColorUtil.rgbToInt(255,127,0), + public static final int[] DEBUG_DETAIL_LEVEL_COLORS = new int[]{ + ColorUtil.rgbToInt(255, 0, 0), ColorUtil.rgbToInt(255, 127, 0), ColorUtil.rgbToInt(255, 255, 0), ColorUtil.rgbToInt(127, 255, 0), ColorUtil.rgbToInt(0, 255, 0), ColorUtil.rgbToInt(0, 255, 127), ColorUtil.rgbToInt(0, 255, 255), ColorUtil.rgbToInt(0, 127, 255), @@ -146,11 +146,12 @@ public class LodUtil /** * Gets the ServerWorld for the relevant dimension. + * * @return null if there is no ServerWorld for the given dimension */ public static ILevelWrapper getServerWorldFromDimension(IDimensionTypeWrapper newDimension) { - if(!MC_CLIENT.hasSinglePlayerServer()) + if (!MC_CLIENT.hasSinglePlayerServer()) return null; Iterable worlds = MC_CLIENT.getAllServerWorlds(); @@ -167,24 +168,32 @@ public class LodUtil return returnWorld; } - - - public static int computeOverdrawOffset() { + + + public static int computeOverdrawOffset() + { int chunkRenderDist = MC_RENDER.getRenderDistance() + 1; EVanillaOverdraw overdraw = EVanillaOverdraw.ALWAYS; //Config.Client.Advanced.Graphics.AdvancedGraphics.vanillaOverdraw.get(); if (overdraw == EVanillaOverdraw.ALWAYS) return Integer.MAX_VALUE; int offset; - if (overdraw == EVanillaOverdraw.NEVER) { + if (overdraw == EVanillaOverdraw.NEVER) + { offset = 0; //Config.Client.Advanced.Graphics.AdvancedGraphics.overdrawOffset.get(); - } else { - if (chunkRenderDist < MINIMUM_RENDER_DISTANCE_FOR_FAR_OVERDRAW) { + } + else + { + if (chunkRenderDist < MINIMUM_RENDER_DISTANCE_FOR_FAR_OVERDRAW) + { offset = 1; - } else { + } + else + { offset = chunkRenderDist / 5; } } - - if (chunkRenderDist - offset <= 1) { + + if (chunkRenderDist - offset <= 1) + { return Integer.MAX_VALUE; } return offset; @@ -197,21 +206,24 @@ public class LodUtil int offset = computeOverdrawOffset(); if (offset == Integer.MAX_VALUE) return null; int renderDist = MC_RENDER.getRenderDistance() + 1; - + Iterator posIter = MC_RENDER.getVanillaRenderedChunks().iterator(); - - return new EdgeDistanceBooleanGrid(new Iterator() { - @Override - public boolean hasNext() { - return posIter.hasNext(); - } - - @Override - public Pos2D next() { - DhChunkPos pos = posIter.next(); - return new Pos2D(pos.getX(), pos.getZ()); - } - }, + + return new EdgeDistanceBooleanGrid(new Iterator() + { + @Override + public boolean hasNext() + { + return posIter.hasNext(); + } + + @Override + public Pos2D next() + { + DhChunkPos pos = posIter.next(); + return new Pos2D(pos.getX(), pos.getZ()); + } + }, MC_CLIENT.getPlayerChunkPos().getX() - renderDist, MC_CLIENT.getPlayerChunkPos().getZ() - renderDist, renderDist * 2 + 1); @@ -221,29 +233,32 @@ public class LodUtil // True if the requested threshold pass, or false otherwise // For details, see: // https://stackoverflow.com/questions/3571203/what-are-runtime-getruntime-totalmemory-and-freememory - public static boolean checkRamUsage(double minFreeMemoryPercent, int minFreeMemoryMB) { + public static boolean checkRamUsage(double minFreeMemoryPercent, int minFreeMemoryMB) + { long freeMem = Runtime.getRuntime().freeMemory() + Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory(); if (freeMem < minFreeMemoryMB * 1024L * 1024L) return false; long maxMem = Runtime.getRuntime().maxMemory(); - if (freeMem/(double)maxMem < minFreeMemoryPercent) return false; + if (freeMem / (double) maxMem < minFreeMemoryPercent) return false; return true; } - public static void checkInterrupts() throws InterruptedException { + public static void checkInterrupts() throws InterruptedException + { if (Thread.interrupted()) throw new InterruptedException(); } - + /** * Format a given string with params using log4j's MessageFormat * - * @apiNote This 'format' SHOULD ONLY be used for logging and debugging purposes! - * Do not use it for deserialization or naming of objects. * @param str The string to format * @param param The parameters to use in the string * @return A message object. Call .toString() to get the string. + * @apiNote This 'format' SHOULD ONLY be used for logging and debugging purposes! + * Do not use it for deserialization or naming of objects. * @author leetom */ - public static String formatLog(String str, Object... param) { + public static String formatLog(String str, Object... param) + { return LOGGER.getMessageFactory().newMessage(str, param).getFormattedMessage(); } @@ -262,51 +277,67 @@ public class LodUtil return str.substring(0, Math.min(str.length(), maxLength)); } } - - public static class AssertFailureException extends RuntimeException { - public AssertFailureException(String message) { + + public static class AssertFailureException extends RuntimeException + { + public AssertFailureException(String message) + { super(message); debugBreak(); } + } - - public static void debugBreak() { + + public static void debugBreak() + { int a = 0; // Set breakpoint here for auto pause on assert failure } - - public static void assertTrue(boolean condition) { - if (!condition) { + + public static void assertTrue(boolean condition) + { + if (!condition) + { throw new AssertFailureException("Assertion failed"); } } - public static void assertTrue(boolean condition, String message) { - if (!condition) { + public static void assertTrue(boolean condition, String message) + { + if (!condition) + { throw new AssertFailureException("Assertion failed:\n " + message); } } - public static void assertTrue(boolean condition, String message, Object... args) { - if (!condition) { + public static void assertTrue(boolean condition, String message, Object... args) + { + if (!condition) + { throw new AssertFailureException("Assertion failed:\n " + formatLog(message, args)); } } - public static void assertNotReach() { + public static void assertNotReach() + { throw new AssertFailureException("Assert Not Reach failed"); } - public static void assertNotReach(String message) { + public static void assertNotReach(String message) + { throw new AssertFailureException("Assert Not Reach failed:\n " + message); } - public static void assertNotReach(String message, Object... args) { + public static void assertNotReach(String message, Object... args) + { throw new AssertFailureException("Assert Not Reach failed:\n " + formatLog(message, args)); } - public static void assertToDo() { + public static void assertToDo() + { throw new AssertFailureException("TODO!"); } - - public static Throwable ensureUnwrap(Throwable t) { + + public static Throwable ensureUnwrap(Throwable t) + { return t instanceof CompletionException ? ensureUnwrap(t.getCause()) : t; } - - public static boolean isInterruptOrReject(Throwable t) { + + public static boolean isInterruptOrReject(Throwable t) + { Throwable unwrapped = LodUtil.ensureUnwrap(t); return UncheckedInterruptedException.isInterrupt(unwrapped) || unwrapped instanceof RejectedExecutionException || diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RayCastUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RayCastUtil.java index 36b593f6c..eb3602962 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RayCastUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RayCastUtil.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util; /** @@ -86,7 +86,7 @@ public class RayCastUtil // is the ray pointing towards the square? if ((rayXDirection > 0 && rayX > squareMaxX) || // right - (rayXDirection < 0 && rayX < squareMinX)) // left + (rayXDirection < 0 && rayX < squareMinX)) // left { // the ray is pointing away from the square return false; @@ -122,7 +122,7 @@ public class RayCastUtil // does the intersection happen before the ray's origin? if ((rayYDirection > 0 && (yIntersectMin <= rayY && yIntersectMax <= rayY)) || // moving in pos Y direction - (rayYDirection < 0 && (yIntersectMin >= rayY && yIntersectMax >= rayY))) // moving in neg Y direction + (rayYDirection < 0 && (yIntersectMin >= rayY && yIntersectMax >= rayY))) // moving in neg Y direction { return false; } @@ -144,7 +144,7 @@ public class RayCastUtil // does the intersection happen before the ray's origin? if ((rayXDirection > 0 && (xIntersectMin <= rayX && xIntersectMax <= rayX)) || // moving in pos X direction - (rayXDirection < 0 && (xIntersectMin >= rayX && xIntersectMax >= rayX))) // moving in neg X direction + (rayXDirection < 0 && (xIntersectMin >= rayX && xIntersectMax >= rayX))) // moving in neg X direction { return false; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java index d599f35e1..e2e58a077 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java @@ -30,7 +30,7 @@ import java.util.Arrays; /** * A helper class that is used to access the data from a long * formatted as a render data point.

- * + * * To access data from a long formatted as a full data point see: {@link FullDataPointUtil} * * DataPoint Format:
@@ -46,65 +46,65 @@ import java.util.Arrays; * SL: sky light
* * =======Bit layout=======
- * _ GM GM GM A A A A |
- * R R R R R R R R |
- * G G G G G G G G |
- * B B B B B B B B |

+ * _ GM GM GM A A A A |
+ * R R R R R R R R |
+ * G G G G G G G G |
+ * B B B B B B B B |

* - * H H H H H H H H |
- * H H H H D D D D |
- * D D D D D D D D |
- * BL BL BL BL SL SL SL SL |
+ * H H H H H H H H |
+ * H H H H D D D D |
+ * D D D D D D D D |
+ * BL BL BL BL SL SL SL SL |
* - * + * * @see FullDataPointUtil */ public class RenderDataPointUtil { - // Reminder: bytes have range of [-128, 127]. - // When converting to or from an int a 128 should be added or removed. - // If there is a bug with color then it's probably caused by this. + // Reminder: bytes have range of [-128, 127]. + // When converting to or from an int a 128 should be added or removed. + // If there is a bug with color then it's probably caused by this. private static final SpamReducedLogger warnLogger = new SpamReducedLogger(1); public final static int EMPTY_DATA = 0; - public final static int MAX_WORLD_Y_SIZE = 4096; + public final static int MAX_WORLD_Y_SIZE = 4096; - public final static int ALPHA_DOWNSIZE_SHIFT = 4; + public final static int ALPHA_DOWNSIZE_SHIFT = 4; - public final static int GEN_TYPE_SHIFT = 60; + public final static int GEN_TYPE_SHIFT = 60; - public final static int COLOR_SHIFT = 32; - public final static int BLUE_SHIFT = COLOR_SHIFT; - public final static int GREEN_SHIFT = BLUE_SHIFT + 8; - public final static int RED_SHIFT = GREEN_SHIFT + 8; - public final static int ALPHA_SHIFT = RED_SHIFT + 8; + public final static int COLOR_SHIFT = 32; + public final static int BLUE_SHIFT = COLOR_SHIFT; + public final static int GREEN_SHIFT = BLUE_SHIFT + 8; + public final static int RED_SHIFT = GREEN_SHIFT + 8; + public final static int ALPHA_SHIFT = RED_SHIFT + 8; - public final static int HEIGHT_SHIFT = 20; - public final static int DEPTH_SHIFT = 8; - public final static int BLOCK_LIGHT_SHIFT = 4; - public final static int SKY_LIGHT_SHIFT = 0; + public final static int HEIGHT_SHIFT = 20; + public final static int DEPTH_SHIFT = 8; + public final static int BLOCK_LIGHT_SHIFT = 4; + public final static int SKY_LIGHT_SHIFT = 0; - public final static long ALPHA_MASK = 0xF; - public final static long RED_MASK = 0xFF; - public final static long GREEN_MASK = 0xFF; - public final static long BLUE_MASK = 0xFF; - public final static long COLOR_MASK = 0xFFFFFF; - public final static long HEIGHT_MASK = 0xFFF; - public final static long DEPTH_MASK = 0xFFF; - public final static long HEIGHT_DEPTH_MASK = 0xFFFFFF; - public final static long BLOCK_LIGHT_MASK = 0xF; - public final static long SKY_LIGHT_MASK = 0xF; - public final static long GEN_TYPE_MASK = 0b111; - public final static long COMPARE_SHIFT = GEN_TYPE_SHIFT; + public final static long ALPHA_MASK = 0xF; + public final static long RED_MASK = 0xFF; + public final static long GREEN_MASK = 0xFF; + public final static long BLUE_MASK = 0xFF; + public final static long COLOR_MASK = 0xFFFFFF; + public final static long HEIGHT_MASK = 0xFFF; + public final static long DEPTH_MASK = 0xFFF; + public final static long HEIGHT_DEPTH_MASK = 0xFFFFFF; + public final static long BLOCK_LIGHT_MASK = 0xF; + public final static long SKY_LIGHT_MASK = 0xF; + public final static long GEN_TYPE_MASK = 0b111; + public final static long COMPARE_SHIFT = GEN_TYPE_SHIFT; - public final static long HEIGHT_SHIFTED_MASK = HEIGHT_MASK << HEIGHT_SHIFT; - public final static long DEPTH_SHIFTED_MASK = DEPTH_MASK << DEPTH_SHIFT; - public final static long GEN_TYPE_SHIFTED_MASK = GEN_TYPE_MASK << GEN_TYPE_SHIFT; + public final static long HEIGHT_SHIFTED_MASK = HEIGHT_MASK << HEIGHT_SHIFT; + public final static long DEPTH_SHIFTED_MASK = DEPTH_MASK << DEPTH_SHIFT; + public final static long GEN_TYPE_SHIFTED_MASK = GEN_TYPE_MASK << GEN_TYPE_SHIFT; - public final static long VOID_SETTER = HEIGHT_SHIFTED_MASK | DEPTH_SHIFTED_MASK; + public final static long VOID_SETTER = HEIGHT_SHIFTED_MASK | DEPTH_SHIFTED_MASK; @@ -122,7 +122,7 @@ public class RenderDataPointUtil return (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; } - public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode) + public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode) { return createDataPoint( ColorUtil.getAlpha(color), @@ -148,19 +148,19 @@ public class RenderDataPointUtil { LodUtil.assertTrue(generationMode != 0, "Trying to create datapoint with genMode 0, which is NOT allowed in DataPoint version 10!"); - LodUtil.assertTrue(height >= 0 && height < MAX_WORLD_Y_SIZE, "Trying to create datapoint with height["+height+"] out of range!"); - LodUtil.assertTrue(depth >= 0 && depth < MAX_WORLD_Y_SIZE, "Trying to create datapoint with depth["+depth+"] out of range!"); + LodUtil.assertTrue(height >= 0 && height < MAX_WORLD_Y_SIZE, "Trying to create datapoint with height[" + height + "] out of range!"); + LodUtil.assertTrue(depth >= 0 && depth < MAX_WORLD_Y_SIZE, "Trying to create datapoint with depth[" + depth + "] out of range!"); - LodUtil.assertTrue(lightSky >= 0 && lightSky < 16, "Trying to create datapoint with lightSky["+lightSky+"] out of range!"); - LodUtil.assertTrue(lightBlock >= 0 && lightBlock < 16, "Trying to create datapoint with lightBlock["+lightBlock+"] out of range!"); + LodUtil.assertTrue(lightSky >= 0 && lightSky < 16, "Trying to create datapoint with lightSky[" + lightSky + "] out of range!"); + LodUtil.assertTrue(lightBlock >= 0 && lightBlock < 16, "Trying to create datapoint with lightBlock[" + lightBlock + "] out of range!"); - LodUtil.assertTrue(alpha >= 0 && alpha < 256, "Trying to create datapoint with alpha["+alpha+"] out of range!"); - LodUtil.assertTrue(red >= 0 && red < 256, "Trying to create datapoint with red["+red+"] out of range!"); - LodUtil.assertTrue(green >= 0 && green < 256, "Trying to create datapoint with green["+green+"] out of range!"); - LodUtil.assertTrue(blue >= 0 && blue < 256, "Trying to create datapoint with blue["+blue+"] out of range!"); + LodUtil.assertTrue(alpha >= 0 && alpha < 256, "Trying to create datapoint with alpha[" + alpha + "] out of range!"); + LodUtil.assertTrue(red >= 0 && red < 256, "Trying to create datapoint with red[" + red + "] out of range!"); + LodUtil.assertTrue(green >= 0 && green < 256, "Trying to create datapoint with green[" + green + "] out of range!"); + LodUtil.assertTrue(blue >= 0 && blue < 256, "Trying to create datapoint with blue[" + blue + "] out of range!"); - LodUtil.assertTrue(generationMode >= 0 && generationMode < 8, "Trying to create datapoint with genMode["+generationMode+"] out of range!"); - LodUtil.assertTrue(depth <= height, "Trying to create datapoint with depth["+depth+"] greater than height["+height+"]!"); + LodUtil.assertTrue(generationMode >= 0 && generationMode < 8, "Trying to create datapoint with genMode[" + generationMode + "] out of range!"); + LodUtil.assertTrue(depth <= height, "Trying to create datapoint with depth[" + depth + "] greater than height[" + height + "]!"); return (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT | (red & RED_MASK) << RED_SHIFT @@ -174,7 +174,7 @@ public class RenderDataPointUtil ; } - public static long shiftHeightAndDepth(long dataPoint, short offset) + public static long shiftHeightAndDepth(long dataPoint, short offset) { long height = (dataPoint + ((long) offset << HEIGHT_SHIFT)) & HEIGHT_SHIFTED_MASK; long depth = (dataPoint + (offset << DEPTH_SHIFT)) & DEPTH_SHIFTED_MASK; @@ -183,17 +183,17 @@ public class RenderDataPointUtil } /** AKA the ending/top/highest Y value above {@link DhLevel#getMinY()} */ - public static short getYMax(long dataPoint) { return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK); } + public static short getYMax(long dataPoint) { return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK); } /** AKA the starting/bottom/lowest Y value above {@link DhLevel#getMinY()} */ - public static short getYMin(long dataPoint) { return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK); } + public static short getYMin(long dataPoint) { return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK); } - public static short getAlpha(long dataPoint) { return (short) ((((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT) | 0b1111); } - public static short getRed(long dataPoint) { return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK); } - public static short getGreen(long dataPoint) { return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK); } - public static short getBlue(long dataPoint) { return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK); } + public static short getAlpha(long dataPoint) { return (short) ((((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT) | 0b1111); } + public static short getRed(long dataPoint) { return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK); } + public static short getGreen(long dataPoint) { return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK); } + public static short getBlue(long dataPoint) { return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK); } - public static byte getLightSky(long dataPoint) { return (byte) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); } - public static byte getLightBlock(long dataPoint) { return (byte) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK); } + public static byte getLightSky(long dataPoint) { return (byte) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); } + public static byte getLightBlock(long dataPoint) { return (byte) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK); } public static byte getGenerationMode(long dataPoint) { @@ -207,20 +207,20 @@ public class RenderDataPointUtil return (genMode == 0) ? 1 : genMode; } - public static long overrideGenerationMode(long current, byte b) { return (current & ~GEN_TYPE_SHIFTED_MASK) | ((b & GEN_TYPE_MASK) << GEN_TYPE_SHIFT); } + public static long overrideGenerationMode(long current, byte b) { return (current & ~GEN_TYPE_SHIFTED_MASK) | ((b & GEN_TYPE_MASK) << GEN_TYPE_SHIFT); } - public static boolean isVoid(long dataPoint) { return (((dataPoint >>> DEPTH_SHIFT) & HEIGHT_DEPTH_MASK) == 0); } + public static boolean isVoid(long dataPoint) { return (((dataPoint >>> DEPTH_SHIFT) & HEIGHT_DEPTH_MASK) == 0); } - public static boolean doesDataPointExist(long dataPoint) { return dataPoint != EMPTY_DATA; } + public static boolean doesDataPointExist(long dataPoint) { return dataPoint != EMPTY_DATA; } - public static int getColor(long dataPoint) + public static int getColor(long dataPoint) { - long alpha = getAlpha(dataPoint); - return (int) (((dataPoint >>> COLOR_SHIFT) & COLOR_MASK) | (alpha << (ALPHA_SHIFT - COLOR_SHIFT))); - } + long alpha = getAlpha(dataPoint); + return (int) (((dataPoint >>> COLOR_SHIFT) & COLOR_MASK) | (alpha << (ALPHA_SHIFT - COLOR_SHIFT))); + } - /** Return (>0) if dataA should replace dataB, (0) if equal, (<0) if dataB should replace dataA */ - public static int compareDatapointPriority(long dataA, long dataB) { return (int) ((dataA >> COMPARE_SHIFT) - (dataB >> COMPARE_SHIFT)); } + /** Return (>0) if dataA should replace dataB, (0) if equal, (<0) if dataB should replace dataA */ + public static int compareDatapointPriority(long dataA, long dataB) { return (int) ((dataA >> COMPARE_SHIFT) - (dataB >> COMPARE_SHIFT)); } /** This is used to convert a dataPoint to string (useful for the print function) */ @SuppressWarnings("unused") @@ -243,7 +243,7 @@ public class RenderDataPointUtil getBlue(dataPoint) + " " + getGreen(dataPoint) + " BL:" + getLightBlock(dataPoint) + - " SL:" +getLightSky(dataPoint) + + " SL:" + getLightSky(dataPoint) + " G:" + getGenerationMode(dataPoint); } } @@ -264,11 +264,11 @@ public class RenderDataPointUtil /** - * This method merge column of multiple data together - * - * @param sourceData one or more columns of data - * @param output one column of space for the result to be written to - */ + * This method merge column of multiple data together + * + * @param sourceData one or more columns of data + * @param output one column of space for the result to be written to + */ public static void mergeMultiData(IColumnDataView sourceData, ColumnArrayView output) { if (output.dataCount() != 1) @@ -404,7 +404,7 @@ public class RenderDataPointUtil { //the column we are checking touches the current column from the bottom //for this reason we extend what's below - + //We want to avoid to expend this column if it has already been expanded by //this index if (!indexHandled[index]) @@ -413,7 +413,7 @@ public class RenderDataPointUtil increaseIndex[index] = true; indexHandled[index] = true; } - + } else if (tempYMin < newHeight && tempYMin > newDepth) { @@ -444,7 +444,7 @@ public class RenderDataPointUtil } } } - + //Now we add the height and depth data we extracted to the heightAndDepth array if (newDepth != newHeight) { @@ -460,7 +460,7 @@ public class RenderDataPointUtil heightAndDepth[count * 2 + 1] = (short) newDepth; count++; } - + //Here we check the condition that makes the loop continue //We stop the loop only if there is no more data to check stillHasDataToCheck = false; @@ -473,7 +473,7 @@ public class RenderDataPointUtil } } } - + //we limit the vertical portion to maxVerticalData int j = 0; while (count > outputVerticalSize) @@ -500,14 +500,14 @@ public class RenderDataPointUtil count--; } //As standard the vertical lods are ordered from top to bottom - + if (!limited && dataCount == 1) // This mean source vertSize < output vertSize AND both dataCount == 1 { sourceData.copyTo(output.data, output.offset, output.vertSize); } else { - + //We want to efficiently memorize indexes int[] dataIndexesCache = tDataIndexCache.get(); if (dataIndexesCache == null || dataIndexesCache.length != dataCount) @@ -526,18 +526,18 @@ public class RenderDataPointUtil //this will be added to each realtive long DataPoint yMax = heightAndDepth[j * 2]; yMin = heightAndDepth[j * 2 + 1]; - + //if both height and depth are at 0 then we finished if ((yMin == 0 && yMax == 0) || j >= heightAndDepth.length / 2) { break; } - + //We initialize data useful for the merge int numberOfChildren = 0; allEmpty = true; allVoid = true; - + //We initialize all the new values that we are going to put in the dataPoint int tempAlpha = 0; int tempRed = 0; @@ -546,7 +546,7 @@ public class RenderDataPointUtil int tempLightBlock = 0; int tempLightSky = 0; long data = 0; - + //For each position that we want to merge for (int index = 0; index < dataCount; index++) { @@ -574,7 +574,7 @@ public class RenderDataPointUtil { data = createVoidDataPoint(genMode); } - + if (doesDataPointExist(data)) { allEmpty = false; @@ -609,7 +609,7 @@ public class RenderDataPointUtil //} output.set(j, createDataPoint(tempAlpha, (int) Math.sqrt(tempRed), (int) Math.sqrt(tempGreen), (int) Math.sqrt(tempBlue), yMax, yMin, tempLightSky, tempLightBlock, genMode)); - + } } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java index 800ef9113..e89a66960 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java @@ -37,7 +37,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; /** * This holds miscellaneous helper code * to be used in the rendering process. - * + * * @author James Seibel * @version 2022-8-21 */ @@ -53,6 +53,7 @@ public class RenderUtil /** * Returns if the given ChunkPos is in the loaded area of the world. + * * @param center the center of the loaded world (probably the player's ChunkPos) */ public static boolean isChunkPosInLoadedArea(DhChunkPos pos, DhChunkPos center) @@ -61,11 +62,12 @@ public class RenderUtil && pos.getX() <= center.getX() + MC_RENDER.getRenderDistance()) && (pos.getZ() >= center.getZ() - MC_RENDER.getRenderDistance() - && pos.getZ() <= center.getZ() + MC_RENDER.getRenderDistance()); + && pos.getZ() <= center.getZ() + MC_RENDER.getRenderDistance()); } /** * Returns if the given coordinate is in the loaded area of the world. + * * @param centerCoordinate the center of the loaded world */ public static boolean isCoordinateInLoadedArea(int x, int z, int centerCoordinate) @@ -107,8 +109,8 @@ public class RenderUtil // calculate the 4 corners Vec3f vboSeVec = new Vec3f(vboVec.x + LodUtil.REGION_WIDTH, vboVec.y, vboVec.z + LodUtil.REGION_WIDTH); - Vec3f vboSwVec = new Vec3f(vboVec.x , vboVec.y, vboVec.z + LodUtil.REGION_WIDTH); - Vec3f vboNwVec = new Vec3f(vboVec.x , vboVec.y, vboVec.z); + Vec3f vboSwVec = new Vec3f(vboVec.x, vboVec.y, vboVec.z + LodUtil.REGION_WIDTH); + Vec3f vboNwVec = new Vec3f(vboVec.x, vboVec.y, vboVec.z); Vec3f vboNeVec = new Vec3f(vboVec.x + LodUtil.REGION_WIDTH, vboVec.y, vboVec.z); // if any corner is visible, this region should be rendered @@ -138,6 +140,7 @@ public class RenderUtil /** * create and return a new projection matrix based on MC's modelView and projection matrices + * * @param mcProjMat Minecraft's current projection matrix */ public static Mat4f createLodProjectionMatrix(Mat4f mcProjMat, float partialTicks) @@ -150,7 +153,7 @@ public class RenderUtil // Set new far and near clip plane values. lodProj.setClipPlanes( getNearClipPlaneDistanceInBlocks(partialTicks), - (float)((farPlaneDistanceInBlocks+LodUtil.REGION_WIDTH) * Math.sqrt(2))); + (float) ((farPlaneDistanceInBlocks + LodUtil.REGION_WIDTH) * Math.sqrt(2))); return lodProj; } @@ -165,6 +168,7 @@ public class RenderUtil /** * create and return a new combined modelView/projection matrix based on MC's modelView and projection matrices + * * @param mcProjMat Minecraft's current projection matrix * @param mcModelViewMat Minecraft's current model view matrix */ @@ -191,7 +195,7 @@ public class RenderUtil { nearClipPlane = 0.1f; } - else + else { // TODO make this option dependent on player speed. // if the player is flying quickly, lower the near clip plane to account for slow chunk loading. @@ -204,16 +208,16 @@ public class RenderUtil case NONE: nearClipPlane = 0.1f; break; - + case LIGHT: nearClipPlane = vanillaBlockRenderedDistance * 0.25f; break; - + case MEDIUM: nearClipPlane = vanillaBlockRenderedDistance * 0.4f; break; - - + + case HEAVY: // recommend render distance ot 6 or higher, otherwise holes may appear nearClipPlane = vanillaBlockRenderedDistance * 0.6f; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/ThreadUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/ThreadUtil.java index 19fb369d2..af9494cd9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/ThreadUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/ThreadUtil.java @@ -31,7 +31,7 @@ public class ThreadUtil THREAD_CHANGE_LISTENERS_BY_THREAD_NAME.remove(name); } - RateLimitedThreadPoolExecutor executor = new RateLimitedThreadPoolExecutor(poolSize, runTimeRatioConfigEntry.get(), new DhThreadFactory("DH-" + name, Thread.NORM_PRIORITY+relativePriority)); + RateLimitedThreadPoolExecutor executor = new RateLimitedThreadPoolExecutor(poolSize, runTimeRatioConfigEntry.get(), new DhThreadFactory("DH-" + name, Thread.NORM_PRIORITY + relativePriority)); ConfigChangeListener changeListener = new ConfigChangeListener<>(runTimeRatioConfigEntry, (newRunTimeRatio) -> { executor.runTimeRatio = newRunTimeRatio; }); THREAD_CHANGE_LISTENERS_BY_THREAD_NAME.put(name, changeListener); @@ -47,10 +47,10 @@ public class ThreadUtil // this is what was being internally used by Executors.newFixedThreadPool // I'm just calling it explicitly here so we can reference the more feature-rich // ThreadPoolExecutor vs the more generic ExecutorService - return new ThreadPoolExecutor(/*corePoolSize*/poolSize, /*maxPoolSize*/poolSize, + return new ThreadPoolExecutor(/*corePoolSize*/ poolSize, /*maxPoolSize*/ poolSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), - new DhThreadFactory("DH-" + name, Thread.NORM_PRIORITY+relativePriority)); + new DhThreadFactory("DH-" + name, Thread.NORM_PRIORITY + relativePriority)); } public static ThreadPoolExecutor makeThreadPool(int poolSize, Class clazz, int relativePriority) { return makeThreadPool(poolSize, clazz.getSimpleName(), relativePriority); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/ArrayGridList.java b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/ArrayGridList.java index 21265e8d6..bfb54ae65 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/ArrayGridList.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/ArrayGridList.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.gridList; import com.seibel.distanthorizons.core.pos.Pos2D; @@ -26,127 +26,157 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; -public class ArrayGridList extends ArrayList { +public class ArrayGridList extends ArrayList +{ public final int gridSize; - - public ArrayGridList(int gridSize, BiFunction filler) { + + public ArrayGridList(int gridSize, BiFunction filler) + { super((gridSize) * (gridSize)); this.gridSize = gridSize; - this.forEachPos((x, y) -> super.add(filler.apply(x,y))); + this.forEachPos((x, y) -> super.add(filler.apply(x, y))); } - - public ArrayGridList(int gridSize) { - this(gridSize, (x,y) -> null); + + public ArrayGridList(int gridSize) + { + this(gridSize, (x, y) -> null); } - - public ArrayGridList(ArrayGridList copy) { + + public ArrayGridList(ArrayGridList copy) + { super(copy); gridSize = copy.gridSize; } - - public ArrayGridList(ArrayGridList from, int minR, int maxR) { - super(maxR-minR); + + public ArrayGridList(ArrayGridList from, int minR, int maxR) + { + super(maxR - minR); if (minR > maxR) throw new IndexOutOfBoundsException("minR greater than maxR"); if (minR < 0) throw new IndexOutOfBoundsException("minR less than 0"); if (maxR > from.gridSize) throw new IndexOutOfBoundsException("maxR greater than gridSize"); - gridSize = maxR-minR; - for (int oy = minR; oy < maxR; oy++) { + gridSize = maxR - minR; + for (int oy = minR; oy < maxR; oy++) + { int begin = minR + oy * from.gridSize; int end = maxR + oy * from.gridSize; super.addAll(from.subList(begin, end)); } - if (super.size() != gridSize*gridSize) throw new IllegalStateException("subgrid clone failure"); + if (super.size() != gridSize * gridSize) throw new IllegalStateException("subgrid clone failure"); // System.out.println("========================================\n"+ // this.toDetailString() + "\nTOOOOOOOOOOOOO\n"+subGrid.toDetailString()+ // "==========================================\n"); } - - protected int _indexOf(int x, int y) { + + protected int _indexOf(int x, int y) + { return x + y * gridSize; } - - public final T get(Pos2D pos) { + + public final T get(Pos2D pos) + { return get(pos.x, pos.y); } - public final T set(Pos2D pos, T e) { + public final T set(Pos2D pos, T e) + { return set(pos.x, pos.y, e); } - public T get(int x, int y) { - if (!inRange(x,y)) return null; - return get(_indexOf(x,y)); + public T get(int x, int y) + { + if (!inRange(x, y)) return null; + return get(_indexOf(x, y)); } - public T getFirst() { - return get(0,0); + public T getFirst() + { + return get(0, 0); } - public T getLast() { - return get(gridSize-1, gridSize-1); + public T getLast() + { + return get(gridSize - 1, gridSize - 1); } - - public T set(int x, int y, T e) { - if (!inRange(x,y)) return null; + + public T set(int x, int y, T e) + { + if (!inRange(x, y)) return null; return set(_indexOf(x, y), e); } - public T setFirst(T e) { - return set(0,0,e); + public T setFirst(T e) + { + return set(0, 0, e); } - public T setLast(T e) { - return set(gridSize-1, gridSize-1, e); + public T setLast(T e) + { + return set(gridSize - 1, gridSize - 1, e); } - - public boolean inRange(int x, int y) { - return (x>=0 && x=0 && y= 0 && x < gridSize && + y >= 0 && y < gridSize); } - - public final void clear() { + + public final void clear() + { this.clear(null); } - public final void fill(BiFunction filler) { + public final void fill(BiFunction filler) + { this.fill(null, filler); } - public final void clear(Consumer dealloc) { - this.fill(dealloc, (x,y) -> null); + public final void clear(Consumer dealloc) + { + this.fill(dealloc, (x, y) -> null); } - public final void fill(Consumer dealloc, - BiFunction filler) { + public final void fill( + Consumer dealloc, + BiFunction filler) + { this.forEachPos((x, y) -> { T t = this.set(x, y, filler.apply(x, y)); - if (t!=null) dealloc.accept(t); + if (t != null) dealloc.accept(t); }); } - - public void forEachPos(BiConsumer consumer) { - for (int y=0; y consumer) + { + for (int y = 0; y < gridSize; y++) + { + for (int x = 0; x < gridSize; x++) + { + consumer.accept(x, y); } } } - + @Override - public final void forEach(Consumer consumer) { + public final void forEach(Consumer consumer) + { super.forEach(consumer); } - + @Override - public String toString() { + public String toString() + { return getClass().toString() + " " + gridSize + "*" + gridSize + "[" + size() + "]"; } - - public String toDetailString() { + + public String toDetailString() + { StringBuilder str = new StringBuilder("\n"); int i = 0; str.append(this); str.append("\n"); - for (T t : this) { - - str.append(t!=null ? t.toString() : "NULL"); + for (T t : this) + { + + str.append(t != null ? t.toString() : "NULL"); str.append(", "); i++; - if (i % gridSize == 0) { + if (i % gridSize == 0) + { str.append("\n"); } } return str.toString(); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/EdgeDistanceBooleanGrid.java b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/EdgeDistanceBooleanGrid.java index 7a4b0a0a8..1a496bf74 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/EdgeDistanceBooleanGrid.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/EdgeDistanceBooleanGrid.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.gridList; import com.seibel.distanthorizons.core.pos.Pos2D; @@ -25,65 +25,76 @@ import com.seibel.distanthorizons.core.util.objects.BoolType; import java.util.Iterator; import java.util.function.IntPredicate; -public class EdgeDistanceBooleanGrid extends PosArrayGridList { - ArrayGridList edgeCache = null; - - public EdgeDistanceBooleanGrid(Iterator posIter, int offsetX, int offsetY, int gridSize) { - super(gridSize, offsetX, offsetY); - while (posIter.hasNext()) { - Pos2D p = posIter.next(); - this.set(p, BoolType.TRUE); - } - } - - // Return false if it is indeed updated - private static boolean updatePos(ArrayGridList grid, int ox, int oy) { - if (grid.get(ox,oy) < 0) return true; - if (ox==0 || oy==0 || ox==grid.gridSize-1 || oy==grid.gridSize-1) { - return true; - } - - int v = grid.get(ox,oy); - if ( - grid.get(ox,oy+1)(gridSize, (ox, oy) -> { - BoolType b = get(ox+getOffsetX(), oy+getOffsetY()); - return b==null ? -1 : 0; - }); - - final boolean[] isDone = {false}; - while (!isDone[0]) { - isDone[0] = true; - edgeCache.forEachPos( (ox, oy) -> { - isDone[0] &= updatePos(edgeCache, ox, oy); - }); - } - } - - // 0 means right on the edge, while 1 means 1 ceil away. Uses Manhattan Distance - public > void flagAllWithDistance(T list, IntPredicate predicate) { - computeEdgeCache(); - edgeCache.forEachPos((ox, oy) -> { - int v = edgeCache.get(ox, oy); - if (v<0 || !predicate.test(v)) return; - list.set(ox + getOffsetX(), oy + getOffsetY(), BoolType.TRUE); - }); - } - - +public class EdgeDistanceBooleanGrid extends PosArrayGridList +{ + ArrayGridList edgeCache = null; + + public EdgeDistanceBooleanGrid(Iterator posIter, int offsetX, int offsetY, int gridSize) + { + super(gridSize, offsetX, offsetY); + while (posIter.hasNext()) + { + Pos2D p = posIter.next(); + this.set(p, BoolType.TRUE); + } + } + + // Return false if it is indeed updated + private static boolean updatePos(ArrayGridList grid, int ox, int oy) + { + if (grid.get(ox, oy) < 0) return true; + if (ox == 0 || oy == 0 || ox == grid.gridSize - 1 || oy == grid.gridSize - 1) + { + return true; + } + + int v = grid.get(ox, oy); + if ( + grid.get(ox, oy + 1) < v || + grid.get(ox, oy - 1) < v || + grid.get(ox + 1, oy) < v || + grid.get(ox - 1, oy) < v + ) + { + return true; + } + else + { + grid.set(ox, oy, v + 1); + return false; + } + } + + //FIXME: This is slow and expensive. Use queue to make this skip recheck done pos + private void computeEdgeCache() + { + if (edgeCache != null) return; + + edgeCache = new ArrayGridList(gridSize, (ox, oy) -> { + BoolType b = get(ox + getOffsetX(), oy + getOffsetY()); + return b == null ? -1 : 0; + }); + + final boolean[] isDone = {false}; + while (!isDone[0]) + { + isDone[0] = true; + edgeCache.forEachPos((ox, oy) -> { + isDone[0] &= updatePos(edgeCache, ox, oy); + }); + } + } + + // 0 means right on the edge, while 1 means 1 ceil away. Uses Manhattan Distance + public > void flagAllWithDistance(T list, IntPredicate predicate) + { + computeEdgeCache(); + edgeCache.forEachPos((ox, oy) -> { + int v = edgeCache.get(ox, oy); + if (v < 0 || !predicate.test(v)) return; + list.set(ox + getOffsetX(), oy + getOffsetY(), BoolType.TRUE); + }); + } + + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/MovableGridRingList.java b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/MovableGridRingList.java index b73a69ba1..ae61bb338 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/MovableGridRingList.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/MovableGridRingList.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.gridList; import com.seibel.distanthorizons.core.pos.Pos2D; @@ -56,7 +56,7 @@ public class MovableGridRingList extends ArrayList implements List this.width = halfWidth * 2 + 1; this.halfWidth = halfWidth; - this.minPosRef.set(new Pos2D(centerX- halfWidth, centerY- halfWidth)); + this.minPosRef.set(new Pos2D(centerX - halfWidth, centerY - halfWidth)); this.clear(); } @@ -83,7 +83,7 @@ public class MovableGridRingList extends ArrayList implements List { Pos2D newMin = this.minPosRef.get(); // Use EXACT compare here - if (min!=newMin) + if (min != newMin) { if (!this._inRangeAcquired(x, y, newMin)) { @@ -115,7 +115,7 @@ public class MovableGridRingList extends ArrayList implements List { Pos2D newMin = this.minPosRef.get(); // Use EXACT compare here - if (min!=newMin) + if (min != newMin) { if (!this._inRangeAcquired(x, y, newMin)) { @@ -137,7 +137,7 @@ public class MovableGridRingList extends ArrayList implements List * returns null if x,y is outside the grid * Otherwise, returns the new value */ - public T setChained(int x, int y, T item) { return this.set(x,y,item) ? item : null; } + public T setChained(int x, int y, T item) { return this.set(x, y, item) ? item : null; } @@ -161,7 +161,7 @@ public class MovableGridRingList extends ArrayList implements List { Pos2D newMin = this.minPosRef.get(); // Use EXACT compare here - if (min!=newMin) + if (min != newMin) { if (!this._inRangeAcquired(x, y, newMin)) { @@ -259,12 +259,12 @@ public class MovableGridRingList extends ArrayList implements List { for (int y = 0; y < this.width; y++) { - Pos2D itemPos = new Pos2D(x+cPos.x, y+cPos.y); + Pos2D itemPos = new Pos2D(x + cPos.x, y + cPos.y); - if (x - deltaX < 0 - || y - deltaY < 0 - || x - deltaX >= this.width - || y - deltaY >= this.width) + if (x - deltaX < 0 + || y - deltaY < 0 + || x - deltaX >= this.width + || y - deltaY >= this.width) { T item = this._swapUnsafe(itemPos.x, itemPos.y, null); if (item != null && removedItemConsumer != null) @@ -303,7 +303,7 @@ public class MovableGridRingList extends ArrayList implements List public Pos2D getCenter() { return new Pos2D(this.minPosRef.get().x + this.halfWidth, this.minPosRef.get().y + this.halfWidth); } public Pos2D getMinPosInRange() { return this.minPosRef.get(); } - public Pos2D getMaxPosInRange() { return new Pos2D(this.minPosRef.get().x + this.width -1, this.minPosRef.get().y + this.width -1); } + public Pos2D getMaxPosInRange() { return new Pos2D(this.minPosRef.get().x + this.width - 1, this.minPosRef.get().y + this.width - 1); } public int getWidth() { return this.width; } public int getHalfWidth() { return this.halfWidth; } @@ -321,24 +321,24 @@ public class MovableGridRingList extends ArrayList implements List public boolean inRange(int x, int y) { Pos2D minPos = this.minPosRef.get(); - return (x>=minPos.x - && x=minPos.y - && y= minPos.x + && x < minPos.x + this.width + && y >= minPos.y + && y < minPos.y + this.width); } private boolean _inRangeAcquired(int x, int y, Pos2D min) { - return (x>=min.x - && x=min.y - && y= min.x + && x < min.x + this.width + && y >= min.y + && y < min.y + this.width); } - private T _getUnsafe(int x, int y) { return super.get(Math.floorMod(x, this.width) + Math.floorMod(y, this.width)*this.width); } - private void _setUnsafe(int x, int y, T item) { super.set(Math.floorMod(x, this.width) + Math.floorMod(y, this.width)*this.width, item); } - private T _swapUnsafe(int x, int y, T item) { return super.set(Math.floorMod(x, this.width) + Math.floorMod(y, this.width)*this.width, item); } - + private T _getUnsafe(int x, int y) { return super.get(Math.floorMod(x, this.width) + Math.floorMod(y, this.width) * this.width); } + private void _setUnsafe(int x, int y, T item) { super.set(Math.floorMod(x, this.width) + Math.floorMod(y, this.width) * this.width, item); } + private T _swapUnsafe(int x, int y, T item) { return super.set(Math.floorMod(x, this.width) + Math.floorMod(y, this.width) * this.width, item); } + // TODO: implement this /* @@ -457,14 +457,14 @@ public class MovableGridRingList extends ArrayList implements List /** - * TODO: Check if this needs to be synchronized + * TODO: Check if this needs to be synchronized *
* FIXME: Make all usage of this class do stuff relative to the minPos instead of the center */ private void createRingIteratorList() { this.ringPositionIteratorArray = null; - Pos2D[] posArray = new Pos2D[this.width *this.width]; + Pos2D[] posArray = new Pos2D[this.width * this.width]; int i = 0; for (int xPos = -this.halfWidth; xPos <= this.halfWidth; xPos++) @@ -479,8 +479,8 @@ public class MovableGridRingList extends ArrayList implements List // sort the positions from nearest to farthest from the world origin Arrays.sort(posArray, (a, b) -> { - long disSqrA = (long) a.x*a.x + (long) a.y*a.y; - long disSqrB = (long) b.x*b.x + (long) b.y*b.y; + long disSqrA = (long) a.x * a.x + (long) a.y * a.y; + long disSqrB = (long) b.x * b.x + (long) b.y * b.y; return Double.compare(disSqrA, disSqrB); }); @@ -508,7 +508,7 @@ public class MovableGridRingList extends ArrayList implements List public String toString() { Pos2D p = this.minPosRef.get(); - return this.getClass().getSimpleName() + "[" + (p.x+this.halfWidth) + "," + (p.y+this.halfWidth) + "] " + this.width + "*" + this.width + "[" + this.size() + "]"; + return this.getClass().getSimpleName() + "[" + (p.x + this.halfWidth) + "," + (p.y + this.halfWidth) + "] " + this.width + "*" + this.width + "[" + this.size() + "]"; } public String toDetailString() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/PosArrayGridList.java b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/PosArrayGridList.java index ec3b4bbd2..11d4813d9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/PosArrayGridList.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/gridList/PosArrayGridList.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.gridList; import java.util.function.BiConsumer; @@ -29,69 +29,83 @@ import java.util.function.Consumer; * 6,7,8 */ -public class PosArrayGridList extends ArrayGridList { - +public class PosArrayGridList extends ArrayGridList +{ + private int offsetX; private int offsetY; - + /* * WARNING: Non Thread safe! */ - public PosArrayGridList(int gridSize, int offsetX, int offsetY, BiFunction filler) { + public PosArrayGridList(int gridSize, int offsetX, int offsetY, BiFunction filler) + { super(gridSize, filler); this.offsetX = offsetX; this.offsetY = offsetY; } - - public PosArrayGridList(int gridSize, int offsetX, int offsetY) { - this(gridSize, offsetX, offsetY, (x,y) -> null); + + public PosArrayGridList(int gridSize, int offsetX, int offsetY) + { + this(gridSize, offsetX, offsetY, (x, y) -> null); } - - public PosArrayGridList(PosArrayGridList copy) { + + public PosArrayGridList(PosArrayGridList copy) + { super(copy); offsetX = copy.offsetX; offsetY = copy.offsetY; } - - public PosArrayGridList(PosArrayGridList source, int minR, int maxR) { + + public PosArrayGridList(PosArrayGridList source, int minR, int maxR) + { super(source, minR, maxR); } - + @Override - protected int _indexOf(int x, int y) { - return (x-offsetX) + (y-offsetY) * gridSize; + protected int _indexOf(int x, int y) + { + return (x - offsetX) + (y - offsetY) * gridSize; } - + @Override - public void forEachPos(BiConsumer consumer) { - for (int y=offsetY; y consumer) + { + for (int y = offsetY; y < offsetY + gridSize; y++) + { + for (int x = offsetX; x < offsetX + gridSize; x++) + { + consumer.accept(x, y); } } } - - public int getOffsetX() { + + public int getOffsetX() + { return offsetX; } - public int getOffsetY() { + public int getOffsetY() + { return offsetY; } - + @Override - public boolean inRange(int x, int y) { - return (x>=offsetX && x=offsetY && y= offsetX && x < offsetX + gridSize && + y >= offsetY && y < offsetY + gridSize); } - - private T _directGet(int x, int y) { - if (!inRange(x,y)) return null; - return get(x,y); + + private T _directGet(int x, int y) + { + if (!inRange(x, y)) return null; + return get(x, y); } - + // Return false if haven't changed. Return true if it did - public boolean move(int deltaX, int deltaY, Consumer dealloc) { - if (deltaX==0 && deltaY==0) return false; + public boolean move(int deltaX, int deltaY, Consumer dealloc) + { + if (deltaX == 0 && deltaY == 0) return false; // if the x or z offset is equal to or greater than // the total width, just delete the current data @@ -108,30 +122,31 @@ public class PosArrayGridList extends ArrayGridList { int newMinY = offsetY + deltaY; int newMaxX = newMinX + gridSize; int newMaxY = newMinY + gridSize; - + // Dealloc stuff if (dealloc != null) - forEachPos((x,y) -> { - if (x=newMaxX || y>=newMaxY) { - T t = get(x,y); - if (t!=null) dealloc.accept(t); + forEachPos((x, y) -> { + if (x < newMinX || y < newMinY || + x >= newMaxX || y >= newMaxY) + { + T t = get(x, y); + if (t != null) dealloc.accept(t); } }); - + offsetX = newMinX; offsetY = newMinY; - + // X if (deltaX >= 0 && deltaY >= 0) { - + // move everything over to the left-up (as the center moves to the right-down) for (int x = newMinX; x < newMaxX; x++) { for (int y = newMinY; y < newMaxY; y++) { - set(x, y, _directGet(x+deltaX, y+deltaY)); + set(x, y, _directGet(x + deltaX, y + deltaY)); } } } @@ -142,7 +157,7 @@ public class PosArrayGridList extends ArrayGridList { { for (int y = newMinY; y < newMaxY; y++) { - set(x, y, _directGet(x+deltaX, y+deltaY)); + set(x, y, _directGet(x + deltaX, y + deltaY)); } } } @@ -153,7 +168,7 @@ public class PosArrayGridList extends ArrayGridList { { for (int y = newMaxY - 1; y >= newMinY; y--) { - set(x, y, _directGet(x+deltaX, y+deltaY)); + set(x, y, _directGet(x + deltaX, y + deltaY)); } } } @@ -164,15 +179,17 @@ public class PosArrayGridList extends ArrayGridList { { for (int y = newMaxY - 1; y >= newMinY; y--) { - set(x, y, _directGet(x+deltaX, y+deltaY)); + set(x, y, _directGet(x + deltaX, y + deltaY)); } } } return true; } - + @Override - public String toString() { + public String toString() + { return getClass().toString() + "[" + offsetX + "," + offsetY + "] " + gridSize + "*" + gridSize + "[" + size() + "]"; } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/math/UnitBytes.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/UnitBytes.java index 2d28cec32..3b8bcd089 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/math/UnitBytes.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/UnitBytes.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.math; import java.util.Objects; @@ -24,32 +24,40 @@ import java.util.Objects; public class UnitBytes { public final long value; - public UnitBytes(long value) { + public UnitBytes(long value) + { this.value = value; } - public long value() {return value;} + public long value() { return value; } - public static long byteToGB(long v) { - return v/1073741824; + public static long byteToGB(long v) + { + return v / 1073741824; } - public static long byteToMB(long v) { - return v/1048576; + public static long byteToMB(long v) + { + return v / 1048576; } - public static long byteToKB(long v) { - return v/1024; + public static long byteToKB(long v) + { + return v / 1024; } - public static long GBToByte(long v) { - return v*1073741824; + public static long GBToByte(long v) + { + return v * 1073741824; } - public static long MBToByte(long v) { - return v*1048576; + public static long MBToByte(long v) + { + return v * 1048576; } - public static long KBToByte(long v) { - return v*1024; + public static long KBToByte(long v) + { + return v * 1024; } @Override - public String toString() { + public String toString() + { long v = value; StringBuilder str = new StringBuilder(); long GB = byteToGB(v); @@ -64,17 +72,20 @@ public class UnitBytes str.append(v).append("B"); return str.toString(); } - + @Override - public boolean equals(Object o) { + public boolean equals(Object o) + { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UnitBytes unitBytes = (UnitBytes) o; return value == unitBytes.value; } - + @Override - public int hashCode() { + public int hashCode() + { return Objects.hash(value); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/BoolType.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/BoolType.java index 8461d2113..0efa0a8d0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/BoolType.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/BoolType.java @@ -16,11 +16,13 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.objects; -public final class BoolType { - public static final BoolType TRUE = new BoolType(); - public static final BoolType FALSE = null; - private BoolType() {} +public final class BoolType +{ + public static final BoolType TRUE = new BoolType(); + public static final BoolType FALSE = null; + private BoolType() { } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DhThreadFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DhThreadFactory.java index 7dcc897a4..d5ac954cc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DhThreadFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DhThreadFactory.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull; /** * Just a simple ThreadFactory to name ExecutorService * threads, which can be helpful when debugging. - * + * * @author James Seibel * @version 2023-6-5 */ @@ -49,7 +49,7 @@ public class DhThreadFactory implements ThreadFactory { if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { - throw new IllegalArgumentException("Thread priority should be ["+Thread.MIN_PRIORITY+"-"+ Thread.MAX_PRIORITY+"]!"); + throw new IllegalArgumentException("Thread priority should be [" + Thread.MIN_PRIORITY + "-" + Thread.MAX_PRIORITY + "]!"); } this.threadName = newThreadName + " Thread"; @@ -59,7 +59,7 @@ public class DhThreadFactory implements ThreadFactory @Override public Thread newThread(@NotNull Runnable runnable) { - Thread thread = new Thread(runnable, this.threadName + "["+(this.threadCount++)+"]"); + Thread thread = new Thread(runnable, this.threadName + "[" + (this.threadCount++) + "]"); thread.setPriority(this.priority); this.threads.add(new WeakReference<>(thread)); return thread; @@ -90,7 +90,7 @@ public class DhThreadFactory implements ThreadFactory if (stacks.length != 0) { LOGGER.info("===========================================\n" + - "Thread: "+thread.getName()+"\n" + + "Thread: " + thread.getName() + "\n" + StackTraceToString(stacks)); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DummyRunExecutorService.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DummyRunExecutorService.java index 342531e73..b8e2d95e7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DummyRunExecutorService.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/DummyRunExecutorService.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.objects; import java.util.ArrayList; @@ -30,7 +30,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -public class DummyRunExecutorService implements ExecutorService { +public class DummyRunExecutorService implements ExecutorService +{ private boolean shutdownCalled = false; @Override @@ -38,50 +39,52 @@ public class DummyRunExecutorService implements ExecutorService { { command.run(); } - + @Override public void shutdown() { shutdownCalled = true; } - + @Override public List shutdownNow() { shutdownCalled = true; return new ArrayList(); } - + @Override public boolean isShutdown() { return shutdownCalled; } - + @Override public boolean isTerminated() { return shutdownCalled; } - + @Override public boolean awaitTermination(long timeout, TimeUnit unit) { shutdownCalled = true; return true; } - + @Override public Future submit(Callable task) { try { return CompletableFuture.completedFuture(task.call()); - } catch (Throwable e) { - return CompletableFuture.supplyAsync( () -> {throw new CompletionException(e);}, Runnable::run); + } + catch (Throwable e) + { + return CompletableFuture.supplyAsync(() -> { throw new CompletionException(e); }, Runnable::run); } } - + @Override public Future submit(Runnable task, T result) { @@ -92,10 +95,10 @@ public class DummyRunExecutorService implements ExecutorService { } catch (Throwable e) { - return CompletableFuture.supplyAsync( () -> {throw new CompletionException(e);}, Runnable::run); + return CompletableFuture.supplyAsync(() -> { throw new CompletionException(e); }, Runnable::run); } } - + @Override public Future submit(Runnable task) { @@ -106,32 +109,35 @@ public class DummyRunExecutorService implements ExecutorService { } catch (Throwable e) { - return CompletableFuture.supplyAsync( () -> {throw new CompletionException(e);}, Runnable::run); + return CompletableFuture.supplyAsync(() -> { throw new CompletionException(e); }, Runnable::run); } } - + @Override public List> invokeAll(Collection> tasks) { List> futures = new ArrayList>(tasks.size()); - for (Callable t : tasks) { + for (Callable t : tasks) + { futures.add(submit(t)); } return futures; } - + @Override public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) { return invokeAll(tasks); } - + @Override public T invokeAny(Collection> tasks) throws ExecutionException { Throwable latestE = null; - for (Callable t : tasks) { - try { + for (Callable t : tasks) + { + try + { return t.call(); } catch (Throwable e) @@ -141,7 +147,7 @@ public class DummyRunExecutorService implements ExecutorService { } throw new ExecutionException(latestE); } - + @Override public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws ExecutionException { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/EventTimer.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/EventTimer.java index a458018bf..6b8fa75bb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/EventTimer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/EventTimer.java @@ -3,68 +3,90 @@ package com.seibel.distanthorizons.core.util.objects; import java.time.Duration; import java.util.ArrayList; -public class EventTimer { - public static class Event { - public long timeNs = -1; - public String name; - Event(String name) { - this.name = name; - } - } - long lastEventNs = -1; - - public ArrayList events = new ArrayList<>(); - - public EventTimer(String firstEventName) { - lastEventNs = System.nanoTime(); - events.add(new Event(firstEventName)); - } - - public void nextEvent(String name) { - long timeNs = System.nanoTime(); - if (lastEventNs != -1 && !events.isEmpty() && events.get(events.size()-1).timeNs == -1) { - events.get(events.size()-1).timeNs = timeNs - lastEventNs; - } - lastEventNs = timeNs; - events.add(new Event(name)); - } - - public void complete() { - long timeNs = System.nanoTime(); - if (lastEventNs != -1 && !events.isEmpty() && events.get(events.size()-1).timeNs == -1) { - events.get(events.size()-1).timeNs = timeNs - lastEventNs; - } - lastEventNs = -1; - } - - public long getEventTimeNs(String name) { - for (Event e : events) { - if (e.name.equals(name)) { - return e.timeNs; - } - } - return -1; - } - - public long getTotalTimeNs() { - long total = 0; - for (Event e : events) { - if (e.timeNs != -1) { - total += e.timeNs; - } - } - return total; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - for (Event e : events) { - if (e.timeNs != -1) { - sb.append(e.name).append(": ").append(Duration.ofNanos(e.timeNs)).append('\n'); - } else { - sb.append(e.name).append(": ").append("N/A").append('\n'); - } - } - return sb.toString(); - } +public class EventTimer +{ + public static class Event + { + public long timeNs = -1; + public String name; + Event(String name) + { + this.name = name; + } + + } + + long lastEventNs = -1; + + public ArrayList events = new ArrayList<>(); + + public EventTimer(String firstEventName) + { + lastEventNs = System.nanoTime(); + events.add(new Event(firstEventName)); + } + + public void nextEvent(String name) + { + long timeNs = System.nanoTime(); + if (lastEventNs != -1 && !events.isEmpty() && events.get(events.size() - 1).timeNs == -1) + { + events.get(events.size() - 1).timeNs = timeNs - lastEventNs; + } + lastEventNs = timeNs; + events.add(new Event(name)); + } + + public void complete() + { + long timeNs = System.nanoTime(); + if (lastEventNs != -1 && !events.isEmpty() && events.get(events.size() - 1).timeNs == -1) + { + events.get(events.size() - 1).timeNs = timeNs - lastEventNs; + } + lastEventNs = -1; + } + + public long getEventTimeNs(String name) + { + for (Event e : events) + { + if (e.name.equals(name)) + { + return e.timeNs; + } + } + return -1; + } + + public long getTotalTimeNs() + { + long total = 0; + for (Event e : events) + { + if (e.timeNs != -1) + { + total += e.timeNs; + } + } + return total; + } + + public String toString() + { + StringBuilder sb = new StringBuilder(); + for (Event e : events) + { + if (e.timeNs != -1) + { + sb.append(e.name).append(": ").append(Duration.ofNanos(e.timeNs)).append('\n'); + } + else + { + sb.append(e.name).append(": ").append("N/A").append('\n'); + } + } + return sb.toString(); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessage.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessage.java index 8fd7a8dc0..6f3ad7464 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessage.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessage.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.objects; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -28,14 +28,14 @@ import java.util.function.Function; /** * Handles parsing and creating string messages from OpenGL messages. - * + * * @author Leetom * @version 2022-10-1 */ public final class GLMessage { private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); - + static final String HEADER = "[LWJGL] OpenGL debug message"; public final EType type; public final ESeverity severity; @@ -82,7 +82,7 @@ public final class GLMessage } @Override - public String toString() { return "[level:"+severity+", type:"+type+", source:"+source+", id:"+id+", msg:{"+message+"}]"; } + public String toString() { return "[level:" + severity + ", type:" + type + ", source:" + source + ", id:" + id + ", msg:{" + message + "}]"; } @@ -161,9 +161,9 @@ public final class GLMessage public enum ESeverity { - HIGH, - MEDIUM, - LOW, + HIGH, + MEDIUM, + LOW, NOTIFICATION; @@ -201,24 +201,24 @@ public final class GLMessage /** how many stages are present in the message parser */ private static final int FINAL_PARSER_STAGE_INDEX = 15; - public static final Builder DEFAULT_MESSAGE_BUILDER = + public static final Builder DEFAULT_MESSAGE_BUILDER = new Builder( - (type) -> { // type filter - if (type == GLMessage.EType.POP_GROUP) - return false; - if (type == GLMessage.EType.PUSH_GROUP) - return false; - if (type == GLMessage.EType.MARKER) - return false; - // if (type == GLMessage.Type.PERFORMANCE) return false; - return true; - }, - (severity) -> { // severity filter - if (severity == GLMessage.ESeverity.NOTIFICATION) - return false; - return true; - }, - null + (type) -> { // type filter + if (type == GLMessage.EType.POP_GROUP) + return false; + if (type == GLMessage.EType.PUSH_GROUP) + return false; + if (type == GLMessage.EType.MARKER) + return false; + // if (type == GLMessage.Type.PERFORMANCE) return false; + return true; + }, + (severity) -> { // severity filter + if (severity == GLMessage.ESeverity.NOTIFICATION) + return false; + return true; + }, + null ); @@ -259,12 +259,12 @@ public final class GLMessage - /** - * Adds the given string to the message builder.

- * - * Will log a warning if the string given wasn't expected - * for the next stage of the OpenGL message format.

- * + /** + * Adds the given string to the message builder.

+ * + * Will log a warning if the string given wasn't expected + * for the next stage of the OpenGL message format.

+ * * @return null if the message isn't complete */ public GLMessage add(String str) @@ -309,55 +309,55 @@ public final class GLMessage { switch (this.parserStage) { - case 0: - return checkAndIncStage(str, GLMessage.HEADER); - case 1: - return checkAndIncStage(str, "ID"); - case 2: - return checkAndIncStage(str, ":"); - case 3: - this.id = str; - this.parserStage++; - return true; - case 4: - return checkAndIncStage(str, "Source"); - case 5: - return checkAndIncStage(str, ":"); - case 6: - this.source = ESource.get(str); - this.parserStage++; - return true; - case 7: - return checkAndIncStage(str, "Type"); - case 8: - return checkAndIncStage(str, ":"); - case 9: - this.type = EType.get(str); - this.parserStage++; - return true; - case 10: - return checkAndIncStage(str, "Severity"); - case 11: - return checkAndIncStage(str, ":"); - case 12: - this.severity = ESeverity.get(str); - this.parserStage++; - return true; - case 13: - return checkAndIncStage(str, "Message"); - case 14: - return checkAndIncStage(str, ":"); - case 15: - this.message = str; - this.parserStage++; - return true; - default: - return false; + case 0: + return checkAndIncStage(str, GLMessage.HEADER); + case 1: + return checkAndIncStage(str, "ID"); + case 2: + return checkAndIncStage(str, ":"); + case 3: + this.id = str; + this.parserStage++; + return true; + case 4: + return checkAndIncStage(str, "Source"); + case 5: + return checkAndIncStage(str, ":"); + case 6: + this.source = ESource.get(str); + this.parserStage++; + return true; + case 7: + return checkAndIncStage(str, "Type"); + case 8: + return checkAndIncStage(str, ":"); + case 9: + this.type = EType.get(str); + this.parserStage++; + return true; + case 10: + return checkAndIncStage(str, "Severity"); + case 11: + return checkAndIncStage(str, ":"); + case 12: + this.severity = ESeverity.get(str); + this.parserStage++; + return true; + case 13: + return checkAndIncStage(str, "Message"); + case 14: + return checkAndIncStage(str, ":"); + case 15: + this.message = str; + this.parserStage++; + return true; + default: + return false; } } - /** - * Returns true and increments the parserStage + /** + * Returns true and increments the parserStage * if the given and expected strings are the same. */ private boolean checkAndIncStage(String givenString, String expectedString) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessageOutputStream.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessageOutputStream.java index 6736ff39e..1368b4528 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessageOutputStream.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/GLMessageOutputStream.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.objects; import java.io.ByteArrayOutputStream; @@ -31,7 +31,7 @@ public final class GLMessageOutputStream extends OutputStream private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - + public GLMessageOutputStream(Consumer func, GLMessage.Builder builder) { this.func = func; @@ -42,7 +42,7 @@ public final class GLMessageOutputStream extends OutputStream public void write(int b) { buffer.write(b); - if (b=='\n') flush(); + if (b == '\n') flush(); } @Override @@ -60,4 +60,5 @@ public final class GLMessageOutputStream extends OutputStream flush(); buffer.close(); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/Pair.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/Pair.java index 81850b34f..fc83e5921 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/Pair.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/Pair.java @@ -15,7 +15,7 @@ public final class Pair } @Override - public String toString() { return "("+this.first+", "+this.second+")"; } + public String toString() { return "(" + this.first + ", " + this.second + ")"; } @Override public int hashCode() { return Objects.hash(this.first, this.second); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/ParsedIp.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/ParsedIp.java index b97e5268d..a8ce0ac95 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/ParsedIp.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/ParsedIp.java @@ -16,13 +16,13 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.objects; /** * Represents an IP and includes a couple helper methods. - * + * * @author James Seibel * @version 3-7-2022 */ @@ -42,7 +42,7 @@ public class ParsedIp /** Examples: "192.168.1.19", "mc.hypixel.net", or "localhost" */ public final String ip; - /** + /** * null if the ip isn't numeric (IE: "mc.hypixel.net" or "localhost")
* Example: "25586" */ @@ -100,10 +100,11 @@ public class ParsedIp @Override public String toString() { - return ip + + return ip + // only print the ":port" if a port is present (port != null ? (":" + port) : ""); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java index 7b23a6dc4..a732842f9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java @@ -3,8 +3,8 @@ package com.seibel.distanthorizons.core.util.objects; import java.util.concurrent.*; /** - * Can be used to more finely control CPU usage and - * reduce CPU usage if only 1 thread is already assigned. + * Can be used to more finely control CPU usage and + * reduce CPU usage if only 1 thread is already assigned. */ public class RateLimitedThreadPoolExecutor extends ThreadPoolExecutor { @@ -41,20 +41,23 @@ public class RateLimitedThreadPoolExecutor extends ThreadPoolExecutor { super.beforeExecute(thread, runnable); - if (this.runTimeRatio < 1.0 && this.lastRunDurationNanoTimeRef.get() != -1) + if (this.runTimeRatio < 1.0 && this.lastRunDurationNanoTimeRef.get() != -1) { - try + try { long deltaMs = TimeUnit.NANOSECONDS.toMillis(this.lastRunDurationNanoTimeRef.get()); - Thread.sleep((long) (deltaMs/this.runTimeRatio - deltaMs)); - } catch (InterruptedException ignored) { } + Thread.sleep((long) (deltaMs / this.runTimeRatio - deltaMs)); + } + catch (InterruptedException ignored) + { + } } this.runStartNanoTimeRef.set(System.nanoTime()); } @Override - protected void afterExecute(Runnable runnable, Throwable throwable) + protected void afterExecute(Runnable runnable, Throwable throwable) { super.afterExecute(runnable, throwable); this.lastRunDurationNanoTimeRef.set(System.nanoTime() - this.runStartNanoTimeRef.get()); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/SortedArraySet.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/SortedArraySet.java index b2217385d..781d25076 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/SortedArraySet.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/SortedArraySet.java @@ -2,158 +2,188 @@ package com.seibel.distanthorizons.core.util.objects; import java.util.*; -public class SortedArraySet implements SortedSet { - private final ArrayList list; - private final Comparator comparator; - - public SortedArraySet() { - list = new ArrayList<>(); - comparator = null; - } - - public SortedArraySet(Comparator comparator) { - list = new ArrayList<>(); - this.comparator = comparator; - } - - public SortedArraySet(Collection collection) { - list = new ArrayList<>(collection); - comparator = null; - list.sort(null); - } - - public SortedArraySet(Collection collection, Comparator comparator) { - list = new ArrayList<>(collection); - this.comparator = comparator; - list.sort(comparator); - } - - @Override - public Comparator comparator() { - return comparator; - } - - @Override - public E first() { - return list.get(0); - } - - @Override - public E last() { - return list.get(list.size() - 1); - } - - @Override - public int size() { - return list.size(); - } - - @Override - public boolean isEmpty() { - return list.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return list.contains(o); - } - - @Override - public Iterator iterator() { - return list.iterator(); - } - - public ListIterator listIterator() { - return list.listIterator(); - } - - public ListIterator listIterator(int index) { - return list.listIterator(index); - } - - - @Override - public Object[] toArray() { - return list.toArray(); - } - - @Override - public T[] toArray(T[] a) { - return list.toArray(a); - } - - @Override - public boolean add(E e) { - int index = Collections.binarySearch(list, e, comparator); - if (index < 0) { - index = ~index; - } - list.add(index, e); - return true; - } - - @Override - public boolean remove(Object o) { - return list.remove(o); - } - - @Override - public boolean containsAll(Collection c) { - return list.containsAll(c); - } - - @Override - public boolean addAll(Collection c) { - boolean changed = false; - for (E e : c) { - changed |= add(e); - } - return changed; - } - - @Override - public boolean retainAll(Collection c) { - return list.retainAll(c); - } - - @Override - public boolean removeAll(Collection c) { - return list.removeAll(c); - } - - @Override - public void clear() { - list.clear(); - } - - @Override - public String toString() { - return "SortedArraySet{" + - "list=" + list + - ", comparator=" + comparator + - '}'; - } - - @Override - public SortedSet subSet(E fromElement, E toElement) { - int fromIndex = Collections.binarySearch(list, fromElement, comparator); - if (fromIndex < 0) fromIndex = ~fromIndex; - int toIndex = Collections.binarySearch(list, toElement, comparator); - if (toIndex < 0) toIndex = ~toIndex; - return new SortedArraySet<>(list.subList(fromIndex, toIndex), comparator); - } - - @Override - public SortedSet headSet(E toElement) { - int toIndex = Collections.binarySearch(list, toElement, comparator); - if (toIndex < 0) toIndex = ~toIndex; - return new SortedArraySet<>(list.subList(0, toIndex), comparator); - } - - @Override - public SortedSet tailSet(E fromElement) { - int fromIndex = Collections.binarySearch(list, fromElement, comparator); - if (fromIndex < 0) fromIndex = ~fromIndex; - return new SortedArraySet<>(list.subList(fromIndex, list.size()), comparator); - } +public class SortedArraySet implements SortedSet +{ + private final ArrayList list; + private final Comparator comparator; + + public SortedArraySet() + { + list = new ArrayList<>(); + comparator = null; + } + + public SortedArraySet(Comparator comparator) + { + list = new ArrayList<>(); + this.comparator = comparator; + } + + public SortedArraySet(Collection collection) + { + list = new ArrayList<>(collection); + comparator = null; + list.sort(null); + } + + public SortedArraySet(Collection collection, Comparator comparator) + { + list = new ArrayList<>(collection); + this.comparator = comparator; + list.sort(comparator); + } + + @Override + public Comparator comparator() + { + return comparator; + } + + @Override + public E first() + { + return list.get(0); + } + + @Override + public E last() + { + return list.get(list.size() - 1); + } + + @Override + public int size() + { + return list.size(); + } + + @Override + public boolean isEmpty() + { + return list.isEmpty(); + } + + @Override + public boolean contains(Object o) + { + return list.contains(o); + } + + @Override + public Iterator iterator() + { + return list.iterator(); + } + + public ListIterator listIterator() + { + return list.listIterator(); + } + + public ListIterator listIterator(int index) + { + return list.listIterator(index); + } + + + @Override + public Object[] toArray() + { + return list.toArray(); + } + + @Override + public T[] toArray(T[] a) + { + return list.toArray(a); + } + + @Override + public boolean add(E e) + { + int index = Collections.binarySearch(list, e, comparator); + if (index < 0) + { + index = ~index; + } + list.add(index, e); + return true; + } + + @Override + public boolean remove(Object o) + { + return list.remove(o); + } + + @Override + public boolean containsAll(Collection c) + { + return list.containsAll(c); + } + + @Override + public boolean addAll(Collection c) + { + boolean changed = false; + for (E e : c) + { + changed |= add(e); + } + return changed; + } + + @Override + public boolean retainAll(Collection c) + { + return list.retainAll(c); + } + + @Override + public boolean removeAll(Collection c) + { + return list.removeAll(c); + } + + @Override + public void clear() + { + list.clear(); + } + + @Override + public String toString() + { + return "SortedArraySet{" + + "list=" + list + + ", comparator=" + comparator + + '}'; + } + + @Override + public SortedSet subSet(E fromElement, E toElement) + { + int fromIndex = Collections.binarySearch(list, fromElement, comparator); + if (fromIndex < 0) fromIndex = ~fromIndex; + int toIndex = Collections.binarySearch(list, toElement, comparator); + if (toIndex < 0) toIndex = ~toIndex; + return new SortedArraySet<>(list.subList(fromIndex, toIndex), comparator); + } + + @Override + public SortedSet headSet(E toElement) + { + int toIndex = Collections.binarySearch(list, toElement, comparator); + if (toIndex < 0) toIndex = ~toIndex; + return new SortedArraySet<>(list.subList(0, toIndex), comparator); + } + + @Override + public SortedSet tailSet(E fromElement) + { + int fromIndex = Collections.binarySearch(list, fromElement, comparator); + if (fromIndex < 0) fromIndex = ~fromIndex; + return new SortedArraySet<>(list.subList(fromIndex, list.size()), comparator); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/StatsMap.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/StatsMap.java index ad8c53c6e..510d1d98f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/StatsMap.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/StatsMap.java @@ -16,39 +16,43 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.util.objects; import com.seibel.distanthorizons.core.util.math.UnitBytes; import java.util.TreeMap; -public class StatsMap +public class StatsMap { final TreeMap longMap = new TreeMap(); final TreeMap bytesMap = new TreeMap(); - + /** - * + * */ @SuppressWarnings("unused") private static final long serialVersionUID = 1926219295516863173L; - public StatsMap() {super();} + public StatsMap() { super(); } - public void incStat(String key) { + public void incStat(String key) + { incStat(key, 1); } - public void incStat(String key, long value) { - longMap.put(key, longMap.getOrDefault(key, 0L)+value); + public void incStat(String key, long value) + { + longMap.put(key, longMap.getOrDefault(key, 0L) + value); } - public void incBytesStat(String key, long bytes) { + public void incBytesStat(String key, long bytes) + { long b = bytesMap.getOrDefault(key, new UnitBytes(0)).value; - bytesMap.put(key, new UnitBytes(b+bytes)); + bytesMap.put(key, new UnitBytes(b + bytes)); } @Override - public String toString() { + public String toString() + { return longMap.toString() + " " + bytesMap.toString(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/UncheckedInterruptedException.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/UncheckedInterruptedException.java index f88ad376a..5cfe0833f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/UncheckedInterruptedException.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/UncheckedInterruptedException.java @@ -4,44 +4,61 @@ import com.seibel.distanthorizons.core.util.LodUtil; import java.util.concurrent.CompletionException; -public class UncheckedInterruptedException extends RuntimeException { - public UncheckedInterruptedException(String message) { - super(message); - } - public UncheckedInterruptedException(Throwable cause) { - super(cause); - } - public UncheckedInterruptedException(String message, Throwable cause) { - super(message, cause); - } - public UncheckedInterruptedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - public UncheckedInterruptedException() { - super(); - } - - public static void throwIfInterrupted() { - if (Thread.currentThread().isInterrupted()) { - throw new UncheckedInterruptedException(); - } - } - - public static UncheckedInterruptedException convert(InterruptedException e) { - return new UncheckedInterruptedException(e); - } - - public static void rethrowIfIsInterruption(Throwable t) { - if (t instanceof InterruptedException) { - throw convert((InterruptedException) t); - } else if (t instanceof UncheckedInterruptedException) { - throw (UncheckedInterruptedException) t; - } else if (t instanceof CompletionException) { - rethrowIfIsInterruption(t.getCause()); - } - } - public static boolean isInterrupt(Throwable t) { - Throwable unwrapped = LodUtil.ensureUnwrap(t); - return unwrapped instanceof InterruptedException || unwrapped instanceof UncheckedInterruptedException; - } +public class UncheckedInterruptedException extends RuntimeException +{ + public UncheckedInterruptedException(String message) + { + super(message); + } + public UncheckedInterruptedException(Throwable cause) + { + super(cause); + } + public UncheckedInterruptedException(String message, Throwable cause) + { + super(message, cause); + } + public UncheckedInterruptedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + public UncheckedInterruptedException() + { + super(); + } + + public static void throwIfInterrupted() + { + if (Thread.currentThread().isInterrupted()) + { + throw new UncheckedInterruptedException(); + } + } + + public static UncheckedInterruptedException convert(InterruptedException e) + { + return new UncheckedInterruptedException(e); + } + + public static void rethrowIfIsInterruption(Throwable t) + { + if (t instanceof InterruptedException) + { + throw convert((InterruptedException) t); + } + else if (t instanceof UncheckedInterruptedException) + { + throw (UncheckedInterruptedException) t; + } + else if (t instanceof CompletionException) + { + rethrowIfIsInterruption(t.getCause()); + } + } + public static boolean isInterrupt(Throwable t) + { + Throwable unwrapped = LodUtil.ensureUnwrap(t); + return unwrapped instanceof InterruptedException || unwrapped instanceof UncheckedInterruptedException; + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataInputStream.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataInputStream.java index 9a1b7068f..76f14256b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataInputStream.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataInputStream.java @@ -13,7 +13,7 @@ import java.io.InputStream; * the wrong stream.

* * Note: - * This stream cannot be closed, + * This stream cannot be closed, * the passed in stream must be closed instead. * This is done to prevent closing file channels prematurely while accessing them. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java index 6fb607377..ae1df8f24 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java @@ -6,6 +6,7 @@ import java.io.*; /** * See {@link DhDataInputStream} for more information about these custom streams. + * * @see DhDataInputStream */ public class DhDataOutputStream extends DataOutputStream diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java index d7f023a7f..254b2b6a8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java @@ -21,28 +21,28 @@ public class QuadNode public T value; - /** + /** * North West
* index 0
- * relative pos (0,0) + * relative pos (0,0) */ public QuadNode nwChild; /** * North East
* index 1
- * relative (1,0) + * relative (1,0) */ public QuadNode neChild; /** * South West
* index 2
- * relative (0,1) + * relative (0,1) */ public QuadNode swChild; /** * South East
* index 3
- * relative (1,1) + * relative (1,1) */ public QuadNode seChild; @@ -56,11 +56,12 @@ public class QuadNode - /** + /** * Use {@link QuadNode#getNonNullChildCount()} if you want the number of non-null child values. - * @return the number of non-null child nodes + * + * @return the number of non-null child nodes */ - public int getTotalChildCount() + public int getTotalChildCount() { int count = 0; for (int i = 0; i < 4; i++) @@ -122,17 +123,17 @@ public class QuadNode /** * @param sectionPos must be 1 detail level lower than this node's detail level - * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node * @return the node at the given position + * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node */ public QuadNode getNode(DhSectionPos sectionPos) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, false, null); } /** * @param sectionPos must be 1 detail level lower than this node's detail level - * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node * @return the value at the given position before the new value was set + * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node */ - public T setValue(DhSectionPos sectionPos, T newValue) throws IllegalArgumentException + public T setValue(DhSectionPos sectionPos, T newValue) throws IllegalArgumentException { QuadNode previousNode = this.getNode(sectionPos); if (previousNode != null) @@ -150,8 +151,8 @@ public class QuadNode /** * @param inputSectionPos must be 1 detail level lower than this node's detail level - * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this * @return the node at the given position before the new node was set (if the new node should be set) + * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this */ private QuadNode getOrSetValue(DhSectionPos inputSectionPos, boolean replaceValue, T newValue) throws IllegalArgumentException { @@ -159,23 +160,23 @@ public class QuadNode if (!this.sectionPos.contains(inputSectionPos)) { - LOGGER.error((replaceValue ? "set " : "get ")+inputSectionPos+" center block: "+inputSectionPos.getCenter().getCornerBlockPos()+", this pos: "+this.sectionPos+" this center block: "+this.sectionPos.getCenter().getCornerBlockPos()); - throw new IllegalArgumentException("Input section pos "+inputSectionPos+" outside of this quadNode's pos: "+this.sectionPos+", this node's blockPos: "+this.sectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL)+" block width: "+this.sectionPos.getWidth().toBlockWidth()+" input detail level: "+inputSectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL)+" width: "+inputSectionPos.getWidth().toBlockWidth()); + LOGGER.error((replaceValue ? "set " : "get ") + inputSectionPos + " center block: " + inputSectionPos.getCenter().getCornerBlockPos() + ", this pos: " + this.sectionPos + " this center block: " + this.sectionPos.getCenter().getCornerBlockPos()); + throw new IllegalArgumentException("Input section pos " + inputSectionPos + " outside of this quadNode's pos: " + this.sectionPos + ", this node's blockPos: " + this.sectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL) + " block width: " + this.sectionPos.getWidth().toBlockWidth() + " input detail level: " + inputSectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL) + " width: " + inputSectionPos.getWidth().toBlockWidth()); } if (inputSectionPos.sectionDetailLevel > this.sectionPos.sectionDetailLevel) { - throw new IllegalArgumentException("detail level higher than this node. Node Detail level: "+this.sectionPos.sectionDetailLevel+" input detail level: "+inputSectionPos.sectionDetailLevel); + throw new IllegalArgumentException("detail level higher than this node. Node Detail level: " + this.sectionPos.sectionDetailLevel + " input detail level: " + inputSectionPos.sectionDetailLevel); } if (inputSectionPos.sectionDetailLevel == this.sectionPos.sectionDetailLevel && !inputSectionPos.equals(this.sectionPos)) { - throw new IllegalArgumentException("Node and input detail level are equal, however positions are not; this tree doesn't contain the requested position. Node pos: "+this.sectionPos+", input pos: "+inputSectionPos); + throw new IllegalArgumentException("Node and input detail level are equal, however positions are not; this tree doesn't contain the requested position. Node pos: " + this.sectionPos + ", input pos: " + inputSectionPos); } if (inputSectionPos.sectionDetailLevel < this.minimumDetailLevel) { - throw new IllegalArgumentException("Input position is requesting a detail level lower than what this node can provide. Node minimum detail level: "+this.minimumDetailLevel+", input pos: "+inputSectionPos); + throw new IllegalArgumentException("Input position is requesting a detail level lower than what this node can provide. Node minimum detail level: " + this.minimumDetailLevel + ", input pos: " + inputSectionPos); } @@ -194,7 +195,7 @@ public class QuadNode { // this node is a parent to the position requested, // recurse to the next node - + // LOGGER.info((replaceValue ? "set " : "get ")+inputSectionPos+" center block: "+inputSectionPos.getCenter().getCornerBlockPos()+", this pos: "+this.sectionPos+" this center block: "+this.sectionPos.getCenter().getCornerBlockPos()); DhSectionPos nwPos = this.sectionPos.getChildByIndex(0); @@ -329,6 +330,6 @@ public class QuadNode //==============// @Override - public String toString() { return "pos: "+this.sectionPos+", children #: "+this.getTotalChildCount()+", value: "+this.value; } + public String toString() { return "pos: " + this.sectionPos + ", children #: " + this.getTotalChildCount() + ", value: " + this.value; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java index 235a5abda..402aaa9da 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java @@ -27,24 +27,25 @@ public class QuadTree /** The largest number detail level in this tree. */ - public final byte treeMaxDetailLevel; + public final byte treeMaxDetailLevel; /** The smallest number detail level in this tree. */ - public final byte treeMinDetailLevel; + public final byte treeMinDetailLevel; /** contain the actual data in the quad tree structure */ - private final MovableGridRingList> topRingList; + private final MovableGridRingList> topRingList; private DhBlockPos2D centerBlockPos; - private int widthInBlocks; + private int widthInBlocks; /** - * Constructor of the quadTree - * @param widthInBlocks equivalent to the distance between two opposing sides - */ - public QuadTree(int widthInBlocks, DhBlockPos2D centerBlockPos, byte treeMinDetailLevel) + * Constructor of the quadTree + * + * @param widthInBlocks equivalent to the distance between two opposing sides + */ + public QuadTree(int widthInBlocks, DhBlockPos2D centerBlockPos, byte treeMinDetailLevel) { this.centerBlockPos = centerBlockPos; this.widthInBlocks = widthInBlocks; @@ -57,11 +58,11 @@ public class QuadTree halfSizeInRootNodes = halfSizeInRootNodes + 1; // always add 1 so nodes will always have a parent, even if the tree's center is offset from the root node grid Pos2D ringListCenterPos = new Pos2D( - BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMaxDetailLevel), + BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMaxDetailLevel), BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.z, this.treeMaxDetailLevel)); this.topRingList = new MovableGridRingList<>(halfSizeInRootNodes, ringListCenterPos.x, ringListCenterPos.y); - - } + + } @@ -69,17 +70,17 @@ public class QuadTree // getters and setters // //=====================// - /** @return the node at the given section position */ - public final QuadNode getNode(DhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); } + /** @return the node at the given section position */ + public final QuadNode getNode(DhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); } /** @return the value at the given section position */ - public final T getValue(DhSectionPos pos) throws IndexOutOfBoundsException + public final T getValue(DhSectionPos pos) throws IndexOutOfBoundsException { QuadNode node = this.getNode(pos); if (node != null) { return node.value; } - return null; + return null; } /** @return the value that was previously in the given position, null if nothing */ @@ -109,12 +110,12 @@ public class QuadTree topQuadNode = new QuadNode(rootPos, this.treeMinDetailLevel); boolean successfullyAdded = this.topRingList.set(ringListPosX, ringListPosZ, topQuadNode); - LodUtil.assertTrue(successfullyAdded, "Failed to add top quadTree node at position: "+rootPos); + LodUtil.assertTrue(successfullyAdded, "Failed to add top quadTree node at position: " + rootPos); } if (!topQuadNode.sectionPos.contains(pos)) { - LodUtil.assertNotReach("failed to get a root node that contains the input position: "+pos+" root node pos: "+topQuadNode.sectionPos); + LodUtil.assertNotReach("failed to get a root node that contains the input position: " + pos + " root node pos: " + topQuadNode.sectionPos); } @@ -127,10 +128,10 @@ public class QuadTree } else { - int radius = this.diameterInBlocks()/2; + int radius = this.diameterInBlocks() / 2; DhBlockPos2D minPos = this.getCenterBlockPos().add(new DhBlockPos2D(-radius, -radius)); - DhBlockPos2D maxPos =this.getCenterBlockPos().add(new DhBlockPos2D(radius, radius)); - throw new IndexOutOfBoundsException("QuadTree GetOrSet failed. Position out of bounds, min pos: "+minPos+", max pos: "+maxPos+", min detail level: "+this.treeMinDetailLevel+", max detail level: "+this.treeMaxDetailLevel+". Given Position: "+pos+" = block pos: "+pos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL)); + DhBlockPos2D maxPos = this.getCenterBlockPos().add(new DhBlockPos2D(radius, radius)); + throw new IndexOutOfBoundsException("QuadTree GetOrSet failed. Position out of bounds, min pos: " + minPos + ", max pos: " + maxPos + ", min detail level: " + this.treeMinDetailLevel + ", max detail level: " + this.treeMaxDetailLevel + ". Given Position: " + pos + " = block pos: " + pos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL)); } } @@ -145,11 +146,11 @@ public class QuadTree // check if the testPos is within the X,Z boundary of the tree - DhBlockPos2D treeBlockCorner = this.centerBlockPos.add(new DhBlockPos2D(-this.widthInBlocks/2,-this.widthInBlocks/2)); - DhLodPos treeCornerPos = new DhLodPos((byte)0, treeBlockCorner.x, treeBlockCorner.z); + DhBlockPos2D treeBlockCorner = this.centerBlockPos.add(new DhBlockPos2D(-this.widthInBlocks / 2, -this.widthInBlocks / 2)); + DhLodPos treeCornerPos = new DhLodPos((byte) 0, treeBlockCorner.x, treeBlockCorner.z); - DhSectionPos inputSectionCorner = testPos.convertToDetailLevel((byte)0); - DhLodPos inputCornerPos = new DhLodPos((byte)0, inputSectionCorner.sectionX, inputSectionCorner.sectionZ); + DhSectionPos inputSectionCorner = testPos.convertToDetailLevel((byte) 0); + DhLodPos inputCornerPos = new DhLodPos((byte) 0, inputSectionCorner.sectionX, inputSectionCorner.sectionZ); int inputBlockWidth = BitShiftUtil.powerOfTwo(testPos.sectionDetailLevel); return DoSquaresOverlap(treeCornerPos, this.widthInBlocks, inputCornerPos, inputBlockWidth); @@ -161,18 +162,18 @@ public class QuadTree float rect1MaxX = square1Min.x + square1Width; float rect1MinZ = square1Min.z; float rect1MaxZ = square1Min.z + square1Width; - + float rect2MinX = square2Min.x; float rect2MaxX = square2Min.x + square2Width; float rect2MinZ = square2Min.z; float rect2MaxZ = square2Min.z + square2Width; - + // Check if the squares overlap - return - rect1MinX < rect2MaxX && - rect1MaxX > rect2MinX && - rect1MinZ < rect2MaxZ && - rect1MaxZ > rect2MinZ; + return + rect1MinX < rect2MaxX && + rect1MaxX > rect2MinX && + rect1MinZ < rect2MaxZ && + rect1MaxZ > rect2MinZ; } @@ -220,7 +221,7 @@ public class QuadTree this.centerBlockPos = newCenterPos; Pos2D expectedCenterPos = new Pos2D( - BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMaxDetailLevel), + BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMaxDetailLevel), BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.z, this.treeMaxDetailLevel)); if (this.topRingList.getCenter().equals(expectedCenterPos)) @@ -231,15 +232,15 @@ public class QuadTree // remove out of bounds root nodes - this.topRingList.moveTo(expectedCenterPos.x, expectedCenterPos.y, (quadNode) -> + this.topRingList.moveTo(expectedCenterPos.x, expectedCenterPos.y, (quadNode) -> { if (quadNode != null && removedItemConsumer != null) { removedItemConsumer.accept(quadNode.value); } }); - - + + // // remove out of bound nodes and clean up empty nodes // // Note: this will iterate over a lot of unnecessary nodes, hopefully speed won't be an issue // Iterator rootNodePosIterator = this.rootNodePosIterator(); @@ -306,9 +307,9 @@ public class QuadTree Iterator> nodeIterator = node.getNodeIterator(); while (nodeIterator.hasNext()) { - if(nodeIterator.next().value != null) + if (nodeIterator.next().value != null) { - count++; + count++; } } } @@ -343,7 +344,7 @@ public class QuadTree public int ringListWidth() { return 3; } public int ringListHalfWidth() { return 1; } public int diameterInBlocks() { return this.widthInBlocks; } - + // public String getDebugString() // { // StringBuilder sb = new StringBuilder(); @@ -358,7 +359,7 @@ public class QuadTree // } @Override - public String toString() { return "center block: "+this.centerBlockPos+", block width: "+this.widthInBlocks+", detail level range: ["+this.treeMinDetailLevel+"-"+this.treeMaxDetailLevel+"], leaf #: "+this.leafNodeCount(); } + public String toString() { return "center block: " + this.centerBlockPos + ", block width: " + this.widthInBlocks + ", detail level range: [" + this.treeMinDetailLevel + "-" + this.treeMaxDetailLevel + "], leaf #: " + this.leafNodeCount(); } @@ -374,7 +375,7 @@ public class QuadTree public QuadTreeRootPosIterator(boolean includeNullNodes) { - QuadTree.this.topRingList.forEachPosOrdered((node, pos2D) -> + QuadTree.this.topRingList.forEachPosOrdered((node, pos2D) -> { if (node != null || includeNullNodes) { @@ -412,6 +413,7 @@ public class QuadTree @Override public void forEachRemaining(Consumer action) { Iterator.super.forEachRemaining(action); } + } private class QuadTreeNodeIterator implements Iterator> @@ -421,7 +423,7 @@ public class QuadTree private QuadNode lastNode = null; - private final boolean onlyReturnLeaves; + private final boolean onlyReturnLeaves; @@ -434,7 +436,7 @@ public class QuadTree @Override - public boolean hasNext() + public boolean hasNext() { if (!this.rootNodeIterator.hasNext() && this.currentNodeIterator != null && !this.currentNodeIterator.hasNext()) { @@ -446,7 +448,7 @@ public class QuadTree { this.currentNodeIterator = this.getNextChildNodeIterator(); } - return this.currentNodeIterator != null && this.currentNodeIterator.hasNext(); + return this.currentNodeIterator != null && this.currentNodeIterator.hasNext(); } @Override @@ -458,7 +460,7 @@ public class QuadTree } - this.lastNode = this.currentNodeIterator.next(); + this.lastNode = this.currentNodeIterator.next(); return this.lastNode; } @@ -466,7 +468,7 @@ public class QuadTree private Iterator> getNextChildNodeIterator() { Iterator> nodeIterator = null; - while((nodeIterator == null || !nodeIterator.hasNext()) && this.rootNodeIterator.hasNext()) + while ((nodeIterator == null || !nodeIterator.hasNext()) && this.rootNodeIterator.hasNext()) { DhSectionPos sectionPos = this.rootNodeIterator.next(); QuadNode rootNode = QuadTree.this.getNode(sectionPos); @@ -480,7 +482,7 @@ public class QuadTree @Override - public void remove() + public void remove() { if (this.lastNode == null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/AbstractDhWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/AbstractDhWorld.java index 880dbf51a..31351be5c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/AbstractDhWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/AbstractDhWorld.java @@ -6,18 +6,18 @@ import org.apache.logging.log4j.Logger; import java.io.Closeable; /** - * Represents an entire world (aka server) and + * Represents an entire world (aka server) and * contains every level in that world. */ public abstract class AbstractDhWorld implements IDhWorld, Closeable { - protected static final Logger LOGGER = DhLoggerBuilder.getLogger(); + protected static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public final EWorldEnvironment environment; + public final EWorldEnvironment environment; - protected AbstractDhWorld(EWorldEnvironment environment) { this.environment = environment; } + protected AbstractDhWorld(EWorldEnvironment environment) { this.environment = environment; } // remove the "throws IOException" diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java index 3572890dc..9e110ec43 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java @@ -17,7 +17,7 @@ import java.util.ArrayList; * This is separate from the world itself to prevent issues * with API implementors referencing said world when it needs * to be loaded/unloaded. - * + * * @author James Seibel * @version 2022-11-20 */ @@ -35,11 +35,11 @@ public class DhApiWorldProxy implements IDhApiWorldProxy - @Override + @Override public boolean worldLoaded() { return SharedApi.getAbstractDhWorld() != null; } @Override - public IDhApiLevelWrapper getSinglePlayerLevel() + public IDhApiLevelWrapper getSinglePlayerLevel() { if (SharedApi.getAbstractDhWorld() == null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java index 6c38ee926..db97abbbe 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java @@ -19,38 +19,38 @@ import java.util.concurrent.ExecutorService; public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWorld, IDhServerWorld { - private final HashMap levelObjMap; - private final HashSet dhLevels; - public final LocalSaveStructure saveStructure; + private final HashMap levelObjMap; + private final HashSet dhLevels; + public final LocalSaveStructure saveStructure; // TODO why does this executor have 2 threads? - public ExecutorService dhTickerThread = ThreadUtil.makeSingleThreadPool("DH Client Server World Ticker Thread", 2); - public EventLoop eventLoop = new EventLoop(this.dhTickerThread, this::_clientTick); //TODO: Rate-limit the loop + public ExecutorService dhTickerThread = ThreadUtil.makeSingleThreadPool("DH Client Server World Ticker Thread", 2); + public EventLoop eventLoop = new EventLoop(this.dhTickerThread, this::_clientTick); //TODO: Rate-limit the loop - public F3Screen.DynamicMessage f3Message; + public F3Screen.DynamicMessage f3Message; - public DhClientServerWorld() + public DhClientServerWorld() { - super(EWorldEnvironment.Client_Server); - this.saveStructure = new LocalSaveStructure(); + super(EWorldEnvironment.Client_Server); + this.saveStructure = new LocalSaveStructure(); this.levelObjMap = new HashMap<>(); this.dhLevels = new HashSet<>(); - LOGGER.info("Started DhWorld of type "+this.environment); + LOGGER.info("Started DhWorld of type " + this.environment); - this.f3Message = new F3Screen.DynamicMessage(() -> LodUtil.formatLog(this.environment+" World with "+this.dhLevels.size()+" levels")); - } + this.f3Message = new F3Screen.DynamicMessage(() -> LodUtil.formatLog(this.environment + " World with " + this.dhLevels.size() + " levels")); + } - @Override + @Override public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) { if (wrapper instanceof IServerLevelWrapper) { - return this.levelObjMap.computeIfAbsent(wrapper, (levelWrapper) -> + return this.levelObjMap.computeIfAbsent(wrapper, (levelWrapper) -> { File levelFile = this.saveStructure.getLevelFolder(levelWrapper); LodUtil.assertTrue(levelFile != null); @@ -80,21 +80,21 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor }); } } - - @Override - public DhClientServerLevel getLevel(ILevelWrapper wrapper) { return this.levelObjMap.get(wrapper); } - - @Override - public Iterable getAllLoadedLevels() { return this.dhLevels; } - - @Override - public void unloadLevel(ILevelWrapper wrapper) + + @Override + public DhClientServerLevel getLevel(ILevelWrapper wrapper) { return this.levelObjMap.get(wrapper); } + + @Override + public Iterable getAllLoadedLevels() { return this.dhLevels; } + + @Override + public void unloadLevel(ILevelWrapper wrapper) { if (this.levelObjMap.containsKey(wrapper)) { if (wrapper instanceof IServerLevelWrapper) { - LOGGER.info("Unloading level "+this.levelObjMap.get(wrapper)); + LOGGER.info("Unloading level " + this.levelObjMap.get(wrapper)); DhClientServerLevel clientServerLevel = this.levelObjMap.remove(wrapper); this.dhLevels.remove(clientServerLevel); clientServerLevel.close(); @@ -108,28 +108,28 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor } } } - - private void _clientTick() + + private void _clientTick() { - //LOGGER.info("Client world tick with {} levels", levels.size()); - this.dhLevels.forEach(DhClientServerLevel::clientTick); - } - - public void clientTick() + //LOGGER.info("Client world tick with {} levels", levels.size()); + this.dhLevels.forEach(DhClientServerLevel::clientTick); + } + + public void clientTick() { - //LOGGER.info("Client world tick"); + //LOGGER.info("Client world tick"); this.eventLoop.tick(); - } + } - public void serverTick() { this.dhLevels.forEach(DhClientServerLevel::serverTick); } + public void serverTick() { this.dhLevels.forEach(DhClientServerLevel::serverTick); } - public void doWorldGen() { this.dhLevels.forEach(DhClientServerLevel::doWorldGen); } + public void doWorldGen() { this.dhLevels.forEach(DhClientServerLevel::doWorldGen); } - @Override - public CompletableFuture saveAndFlush() { return CompletableFuture.allOf(this.dhLevels.stream().map(DhClientServerLevel::saveAsync).toArray(CompletableFuture[]::new)); } + @Override + public CompletableFuture saveAndFlush() { return CompletableFuture.allOf(this.dhLevels.stream().map(DhClientServerLevel::saveAsync).toArray(CompletableFuture[]::new)); } - @Override - public void close() + @Override + public void close() { // at this point the levels are probably unloaded, so this save call usually generally won't do anything this.saveAndFlush(); @@ -137,13 +137,13 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor for (DhClientServerLevel level : this.dhLevels) { - LOGGER.info("Unloading level "+level.getServerLevelWrapper().getDimensionType().getDimensionName()); + LOGGER.info("Unloading level " + level.getServerLevelWrapper().getDimensionType().getDimensionName()); level.close(); } this.levelObjMap.clear(); this.eventLoop.close(); - LOGGER.info("Closed DhWorld of type "+this.environment); + LOGGER.info("Closed DhWorld of type " + this.environment); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java index fc1341bbb..209f8905a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java @@ -23,16 +23,16 @@ import java.util.concurrent.ExecutorService; public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld { - private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - - private final ConcurrentHashMap levels; - public final ClientOnlySaveStructure saveStructure; + private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + + private final ConcurrentHashMap levels; + public final ClientOnlySaveStructure saveStructure; // private final NetworkClient networkClient; - + // TODO why does this executor have 2 threads? - public ExecutorService dhTickerThread = ThreadUtil.makeSingleThreadPool("DH Client World Ticker Thread", 2); - public EventLoop eventLoop = new EventLoop(this.dhTickerThread, this::_clientTick); + public ExecutorService dhTickerThread = ThreadUtil.makeSingleThreadPool("DH Client World Ticker Thread", 2); + public EventLoop eventLoop = new EventLoop(this.dhTickerThread, this::_clientTick); @@ -40,13 +40,13 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld // constructors // //==============// - public DhClientWorld() + public DhClientWorld() { super(EWorldEnvironment.Client_Only); - - this.saveStructure = new ClientOnlySaveStructure(); - this.levels = new ConcurrentHashMap<>(); - + + this.saveStructure = new ClientOnlySaveStructure(); + this.levels = new ConcurrentHashMap<>(); + if (Config.Client.Advanced.Multiplayer.enableServerNetworking.get()) { // TODO server specific configs @@ -57,12 +57,12 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld { // this.networkClient = null; } - - LOGGER.info("Started DhWorld of type "+this.environment); + + LOGGER.info("Started DhWorld of type " + this.environment); } - - private void registerNetworkHandlers() - { + + private void registerNetworkHandlers() + { // this.networkClient.registerHandler(HelloMessage.class, (msg, ctx) -> // { // ctx.writeAndFlush(new PlayerUUIDMessage(MC_CLIENT.getPlayerUUID())); @@ -83,7 +83,7 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld // // TODO Actually request chunks // ctx.writeAndFlush(new RequestChunksMessage()); // }); - } + } @@ -91,88 +91,88 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld // methods // //=========// - @Override - public DhClientLevel getOrLoadLevel(ILevelWrapper wrapper) + @Override + public DhClientLevel getOrLoadLevel(ILevelWrapper wrapper) { - if (!(wrapper instanceof IClientLevelWrapper)) + if (!(wrapper instanceof IClientLevelWrapper)) { return null; } - - return this.levels.computeIfAbsent((IClientLevelWrapper) wrapper, (clientLevelWrapper) -> + + return this.levels.computeIfAbsent((IClientLevelWrapper) wrapper, (clientLevelWrapper) -> { - File file = this.saveStructure.getLevelFolder(wrapper); - - if (file == null) + File file = this.saveStructure.getLevelFolder(wrapper); + + if (file == null) { return null; } - + return new DhClientLevel(this.saveStructure, clientLevelWrapper); - }); - } - - @Override - public DhClientLevel getLevel(ILevelWrapper wrapper) + }); + } + + @Override + public DhClientLevel getLevel(ILevelWrapper wrapper) { - if (!(wrapper instanceof IClientLevelWrapper)) + if (!(wrapper instanceof IClientLevelWrapper)) { return null; } - - return this.levels.get(wrapper); - } - - @Override - public Iterable getAllLoadedLevels() { return this.levels.values(); } - - @Override - public void unloadLevel(ILevelWrapper wrapper) + + return this.levels.get(wrapper); + } + + @Override + public Iterable getAllLoadedLevels() { return this.levels.values(); } + + @Override + public void unloadLevel(ILevelWrapper wrapper) { - if (!(wrapper instanceof IClientLevelWrapper)) + if (!(wrapper instanceof IClientLevelWrapper)) { return; } - - if (this.levels.containsKey(wrapper)) + + if (this.levels.containsKey(wrapper)) { - LOGGER.info("Unloading level "+this.levels.get(wrapper)); + LOGGER.info("Unloading level " + this.levels.get(wrapper)); this.levels.remove(wrapper).close(); - } - } - - private void _clientTick() + } + } + + private void _clientTick() { this.levels.values().forEach(DhClientLevel::clientTick); } - - public void clientTick() { this.eventLoop.tick(); } - - @Override - public CompletableFuture saveAndFlush() + + public void clientTick() { this.eventLoop.tick(); } + + @Override + public CompletableFuture saveAndFlush() { - return CompletableFuture.allOf(this.levels.values().stream().map(DhClientLevel::saveAsync).toArray(CompletableFuture[]::new)); - } - - @Override - public void close() + return CompletableFuture.allOf(this.levels.values().stream().map(DhClientLevel::saveAsync).toArray(CompletableFuture[]::new)); + } + + @Override + public void close() { // if (this.networkClient != null) // { //// this.networkClient.close(); // } - - + + this.saveAndFlush(); - for (DhClientLevel dhClientLevel : this.levels.values()) + for (DhClientLevel dhClientLevel : this.levels.values()) { - LOGGER.info("Unloading level " + dhClientLevel.getLevelWrapper().getDimensionType().getDimensionName()); - dhClientLevel.close(); - } - + LOGGER.info("Unloading level " + dhClientLevel.getLevelWrapper().getDimensionType().getDimensionName()); + dhClientLevel.close(); + } + this.levels.clear(); this.eventLoop.close(); - LOGGER.info("Closed DhWorld of type "+this.environment); - } - + LOGGER.info("Closed DhWorld of type " + this.environment); + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java index 1fdb28abb..fb2387413 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java @@ -24,7 +24,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld { private final HashMap levels; public final LocalSaveStructure saveStructure; - + // private final NetworkServer networkServer; // private final HashMap playersByUUID; // private final BiMap playersByConnection; @@ -37,16 +37,16 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld this.saveStructure = new LocalSaveStructure(); this.levels = new HashMap<>(); - + // TODO move to global payload once server specific configs are implemented // this.networkServer = new NetworkServer(25049); // this.playersByUUID = new HashMap<>(); // this.playersByConnection = HashBiMap.create(); // this.registerNetworkHandlers(); - LOGGER.info("Started "+DhServerWorld.class.getSimpleName()+" of type "+this.environment); + LOGGER.info("Started " + DhServerWorld.class.getSimpleName() + " of type " + this.environment); } - + private void registerNetworkHandlers() { // this.networkServer.registerHandler(CloseMessage.class, (closeMessage, channelContext) -> @@ -167,7 +167,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld public void close() { // this.networkServer.close(); - + for (DhServerLevel level : this.levels.values()) { LOGGER.info("Unloading level " + level.getLevelWrapper().getDimensionType().getDimensionName()); @@ -175,7 +175,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld } this.levels.clear(); - LOGGER.info("Closed DhWorld of type "+this.environment); + LOGGER.info("Closed DhWorld of type " + this.environment); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/EWorldEnvironment.java b/core/src/main/java/com/seibel/distanthorizons/core/world/EWorldEnvironment.java index a4fcf5976..aadac8e6d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/EWorldEnvironment.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/EWorldEnvironment.java @@ -7,7 +7,7 @@ package com.seibel.distanthorizons.core.world; */ public enum EWorldEnvironment { - Client_Only, - Client_Server, - Server_Only + Client_Only, + Client_Server, + Server_Only } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhClientWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhClientWorld.java index ccac84a10..ce5c72afd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhClientWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhClientWorld.java @@ -5,7 +5,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; public interface IDhClientWorld extends IDhWorld { - void clientTick(); + void clientTick(); default IDhClientLevel getOrLoadClientLevel(ILevelWrapper levelWrapper) { return (IDhClientLevel) this.getOrLoadLevel(levelWrapper); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java index 87a765a7b..c581f9540 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java @@ -3,11 +3,11 @@ package com.seibel.distanthorizons.core.world; import com.seibel.distanthorizons.core.level.IDhServerLevel; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -/** Used both for dedicated server and singleplayer worlds */ +/** Used both for dedicated server and singleplayer worlds */ public interface IDhServerWorld extends IDhWorld { - void serverTick(); - void doWorldGen(); + void serverTick(); + void doWorldGen(); default IDhServerLevel getOrLoadServerLevel(ILevelWrapper levelWrapper) { return (IDhServerLevel) this.getOrLoadLevel(levelWrapper); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IVersionConstants.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IVersionConstants.java index 5b77c44be..d84797b3a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IVersionConstants.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IVersionConstants.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; @@ -25,7 +25,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab * A singleton that contains variables specific to each version of Minecraft * which can be used to change how DH-Core runs. For example: After MC 1.17 * blocks can be negative, which changes how we generate LODs. - * + * * @author James Seibel * @version 3-5-2022 */ @@ -34,14 +34,16 @@ public interface IVersionConstants extends IBindable /** @return the minimum height blocks can be generated */ @Deprecated // This changes per world! int getMinimumWorldHeight(); - + /** @return the number of generations call per thread. */ @Deprecated // No longer used - default int getWorldGenerationCountPerThread() { + default int getWorldGenerationCountPerThread() + { return 8; } boolean isVanillaRenderedChunkSquare(); - + String getMinecraftVersion(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java index ef271da61..cf9b88c49 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java @@ -30,19 +30,20 @@ import java.io.IOException; /** * This handles creating abstract wrapper objects. - * + * * @author James Seibel * @version 2022-12-5 */ -public interface IWrapperFactory extends IBindable +public interface IWrapperFactory extends IBindable { AbstractBatchGenerationEnvironmentWrapper createBatchGenerator(IDhLevel targetLevel); IBiomeWrapper deserializeBiomeWrapper(String str) throws IOException; IBlockStateWrapper deserializeBlockStateWrapper(String str) throws IOException; IBlockStateWrapper getAirBlockStateWrapper(); - /** + /** * Specifically designed to be used with the API. + * * @throws ClassCastException with instructions on expected objects if the object couldn't be cast */ IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index 5df9357b4..e3ba0e4c8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -5,10 +5,10 @@ import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; /** A Minecraft version independent way of handling Blocks. */ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper { - String serialize(); + String serialize(); - /** - * Returning a value of 0 means the block is completely transparent. - * Note: this includes water. + /** + * @return The highest y position of a light-blocking or translucent block at the given relative chunk position.
+ * Note: this includes water. */ int getLightBlockingHeightMapValue(int xRel, int zRel); @@ -49,7 +49,7 @@ public interface IChunkWrapper extends IBindable int getMaxBlockZ(); int getMinBlockX(); int getMinBlockZ(); - + long getLongChunkPos(); void setIsDhLightCorrect(boolean isDhLightCorrect); @@ -66,17 +66,17 @@ public interface IChunkWrapper extends IBindable int getBlockLight(int relX, int relY, int relZ); int getSkyLight(int relX, int relY, int relZ); - /** - * Populates DH's saved lighting using MC's lighting engine. + /** + * Populates DH's saved lighting using MC's lighting engine. * This is generally done in cases where MC's lighting is correct now, but may not be later (like when a chunk is unloading). - * + * * @throws IllegalStateException if the chunk's lighting isn't valid. This is done to prevent accidentally baking broken lighting. */ default void bakeDhLightingUsingMcLightingEngine() throws IllegalStateException { if (!this.isLightCorrect()) { - throw new IllegalStateException("Unable to bake lighting for for chunk ["+this.getChunkPos()+"], Minecraft lighting not valid."); + throw new IllegalStateException("Unable to bake lighting for for chunk [" + this.getChunkPos() + "], Minecraft lighting not valid."); } // get the lighting for every relative block pos @@ -91,7 +91,7 @@ public interface IChunkWrapper extends IBindable } } } - } + } @@ -105,7 +105,7 @@ public interface IChunkWrapper extends IBindable && y >= this.getMinBuildHeight() && y < this.getMaxBuildHeight() && z >= this.getMinBlockZ() && z <= this.getMaxBlockZ()); } - default boolean blockPosInsideChunk(DhBlockPos2D blockPos) + default boolean blockPosInsideChunk(DhBlockPos2D blockPos) { return (blockPos.x >= this.getMinBlockX() && blockPos.x <= this.getMaxBlockX() && blockPos.z >= this.getMinBlockZ() && blockPos.z <= this.getMaxBlockZ()); @@ -120,9 +120,9 @@ public interface IChunkWrapper extends IBindable int hash = 31; int primeMultiplier = 227; - for(int x = 0; x < LodUtil.CHUNK_WIDTH; x++) + for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++) { - for(int z = 0; z < LodUtil.CHUNK_WIDTH; z++) + for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++) { hash = hash * primeMultiplier + Integer.hashCode(this.getLightBlockingHeightMapValue(x, z)); } @@ -136,6 +136,7 @@ public interface IChunkWrapper extends IBindable IBlockStateWrapper getBlockState(int relX, int relY, int relZ); IBiomeWrapper getBiome(int relX, int relY, int relZ); - - boolean isStillValid(); + + boolean isStillValid(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/config/ILangWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/config/ILangWrapper.java index f001715a7..0b3ae9358 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/config/ILangWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/config/ILangWrapper.java @@ -2,9 +2,11 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.config; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; -public interface ILangWrapper extends IBindable { - - boolean langExists(String str); - - String getLang(String str); +public interface ILangWrapper extends IBindable +{ + + boolean langExists(String str); + + String getLang(String str); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java index b9aec9bd1..c399f5624 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java @@ -33,7 +33,7 @@ import org.apache.logging.log4j.Level; /** * Contains everything related to the Minecraft object. - * + * * @author James Seibel * @version 2022-8-20 */ @@ -65,25 +65,25 @@ public interface IMinecraftClientWrapper extends IBindable String getCurrentServerName(); String getCurrentServerIp(); String getCurrentServerVersion(); - + //=============// // Simple gets // //=============// boolean playerExists(); - + UUID getPlayerUUID(); - + DhBlockPos getPlayerBlockPos(); DhChunkPos getPlayerChunkPos(); - - /** - * Returns the level the client is currently in.
+ + /** + * Returns the level the client is currently in.
* Returns null if the client isn't in a level. */ ILevelWrapper getWrappedClientWorld(); - + /** Please move over to getInstallationDirectory() within the IMinecraftSharedWrapper */ @Deprecated File getGameDirectory(); @@ -133,15 +133,15 @@ public interface IMinecraftClientWrapper extends IBindable /** * Crashes Minecraft, displaying the given errorMessage

* In the following format:
- * + * * The game crashed whilst errorMessage
* Error: ExceptionClass: exceptionErrorMessage
* Exit Code: -1
*/ void crashMinecraft(String errorMessage, Throwable exception); //FIXME: Move to IMinecraftSharedWrapper - - Object getOptionsObject(); - + + Object getOptionsObject(); + /** Executes the given task on Minecraft's render thread. */ void executeOnRenderThread(Runnable runnable); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java index 7eba1df86..edf67c7f6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java @@ -39,7 +39,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; /** * Contains everything related to * rendering in Minecraft. - * + * * @author James Seibel * @version 3-5-2022 */ @@ -59,8 +59,8 @@ public interface IMinecraftRenderWrapper extends IBindable Color getFogColor(float partialTicks); - default Color getSpecialFogColor(float partialTicks) {return getFogColor(partialTicks);} - + default Color getSpecialFogColor(float partialTicks) { return getFogColor(partialTicks); } + boolean isFogStateSpecial(); Color getSkyColor(); @@ -72,7 +72,7 @@ public interface IMinecraftRenderWrapper extends IBindable int getScreenWidth(); int getScreenHeight(); - + int getTargetFrameBuffer(); int getDepthTextureId(); int getTargetFrameBufferViewportWidth(); @@ -88,15 +88,16 @@ public interface IMinecraftRenderWrapper extends IBindable { // FIXME: Is this actually required? Does it make a differance if it exists or not? ISodiumAccessor sodium = ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class); - return sodium==null ? getMaximumRenderedChunks() : sodium.getNormalRenderedChunks(); + return sodium == null ? getMaximumRenderedChunks() : sodium.getNormalRenderedChunks(); } - - static boolean correctedCheckRadius(int dx, int dz, int radius2Mul4) { - dx = dx*2;// + (dx < 0 ? -1 : 1); - dz = dz*2;// + (dz < 0 ? -1 : 1); - return (dx*dx + dz*dz <= radius2Mul4); + + static boolean correctedCheckRadius(int dx, int dz, int radius2Mul4) + { + dx = dx * 2;// + (dx < 0 ? -1 : 1); + dz = dz * 2;// + (dz < 0 ? -1 : 1); + return (dx * dx + dz * dz <= radius2Mul4); } - + /** * Doesn't need to be implemented.
* Returns every chunk position within the vanilla render distance. @@ -108,31 +109,32 @@ public interface IMinecraftRenderWrapper extends IBindable IVersionConstants versionConstants = SingletonInjector.INSTANCE.get(IVersionConstants.class); IMinecraftClientWrapper minecraft = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); ILevelWrapper clientWorld = minecraft.getWrappedClientWorld(); - + int chunkDist = this.getRenderDistance() + 1; // For some reason having '+1' is actually closer to real value DhChunkPos centerChunkPos = mcWrapper.getPlayerChunkPos(); int centerChunkX = centerChunkPos.getX(); int centerChunkZ = centerChunkPos.getZ(); - int chunkDist2Mul4 = chunkDist*chunkDist*4; + int chunkDist2Mul4 = chunkDist * chunkDist * 4; // add every position within render distance HashSet renderedPos = new HashSet(); for (int deltaChunkX = -chunkDist; deltaChunkX <= chunkDist; deltaChunkX++) { - for(int deltaChunkZ = -chunkDist; deltaChunkZ <= chunkDist; deltaChunkZ++) + for (int deltaChunkZ = -chunkDist; deltaChunkZ <= chunkDist; deltaChunkZ++) { if (!versionConstants.isVanillaRenderedChunkSquare() && - !correctedCheckRadius(deltaChunkX,deltaChunkZ,chunkDist2Mul4)) { + !correctedCheckRadius(deltaChunkX, deltaChunkZ, chunkDist2Mul4)) + { continue; } if (!clientWorld.hasChunkLoaded(centerChunkX + deltaChunkX, centerChunkZ + deltaChunkZ)) continue; renderedPos.add(new DhChunkPos(centerChunkX + deltaChunkX, centerChunkZ + deltaChunkZ)); } } - return renderedPos; + return renderedPos; } - + ILightMapWrapper getLightmapWrapper(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftSharedWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftSharedWrapper.java index 9e4985ec9..07f29c73c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftSharedWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftSharedWrapper.java @@ -5,9 +5,10 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab import java.io.File; //TODO: Maybe have IMCClientWrapper & IMCDedicatedWrapper extend this interface??? -public interface IMinecraftSharedWrapper extends IBindable { - boolean isDedicatedServer(); - - File getInstallationDirectory(); - +public interface IMinecraftSharedWrapper extends IBindable +{ + boolean isDedicatedServer(); + + File getInstallationDirectory(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IProfilerWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IProfilerWrapper.java index 4159d041e..e635c257b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IProfilerWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IProfilerWrapper.java @@ -36,4 +36,5 @@ public interface IProfilerWrapper extends IBindable void popPush(String newSection); void pop(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/ILightMapWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/ILightMapWrapper.java index 0d53486a8..048916008 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/ILightMapWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/ILightMapWrapper.java @@ -27,8 +27,9 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab */ public interface ILightMapWrapper extends IBindable { - + // Returns the binded texture position void bind(); void unbind(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/IServerPlayerWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/IServerPlayerWrapper.java index 329ca7c54..c2e996533 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/IServerPlayerWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/misc/IServerPlayerWrapper.java @@ -4,7 +4,8 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; import java.util.UUID; -public interface IServerPlayerWrapper extends IDhApiUnsafeWrapper +public interface IServerPlayerWrapper extends IDhApiUnsafeWrapper { - UUID getUUID(); + UUID getUUID(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java index 7bec13ab1..3f2c6eadf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java @@ -10,9 +10,9 @@ import java.lang.reflect.Field; /** * Contains any shared code between Optifine for Forge (official Optifine) * and Optifine on Fabric (unofficial ports). - * - * @version 2022-11-24 + * * @author James Seibel + * @version 2022-11-24 */ public abstract class AbstractOptifineAccessor implements IOptifineAccessor { @@ -47,7 +47,7 @@ public abstract class AbstractOptifineAccessor implements IOptifineAccessor return null; } - /** + /** * Should not be called frequently since this uses reflection calls to determine if Optifine is present.
* Use {@link ReflectionHandler#optifinePresent()} instead. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IBCLibAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IBCLibAccessor.java index 5a9312311..80a14e6da 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IBCLibAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IBCLibAccessor.java @@ -1,6 +1,8 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; -public interface IBCLibAccessor extends IModAccessor { - /** Sets the BCLib custom fog renderer */ - void setRenderCustomFog(boolean newValue); +public interface IBCLibAccessor extends IModAccessor +{ + /** Sets the BCLib custom fog renderer */ + void setRenderCustomFog(boolean newValue); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java index 743d8d27b..cb98986f1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java @@ -1,4 +1,5 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; -public interface IImmersivePortalsAccessor extends IModAccessor { +public interface IImmersivePortalsAccessor extends IModAccessor +{ } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModAccessor.java index 1661aaf2c..6a19178ff 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModAccessor.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java index 05ee93585..e76c2af44 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IModChecker.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; @@ -27,7 +27,9 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab * @author coolGi * @version 3-5-2022 */ -public interface IModChecker extends IBindable { - /** Checks if a mod is loaded */ - boolean isModLoaded(String modid); +public interface IModChecker extends IBindable +{ + /** Checks if a mod is loaded */ + boolean isModLoaded(String modid); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java index b2d74b717..6a3eb8779 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; import com.seibel.distanthorizons.api.enums.rendering.EFogDrawMode; @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos; import java.util.HashSet; -public interface IOptifineAccessor extends IModAccessor +public interface IOptifineAccessor extends IModAccessor { /** Can be null */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ISodiumAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ISodiumAccessor.java index 56941ba1d..7dac1d941 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ISodiumAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ISodiumAccessor.java @@ -16,16 +16,18 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; import com.seibel.distanthorizons.core.pos.DhChunkPos; import java.util.HashSet; -public interface ISodiumAccessor extends IModAccessor { +public interface ISodiumAccessor extends IModAccessor +{ HashSet getNormalRenderedChunks(); - + /** A temporary overwrite for a config in sodium 0.5 to fix their terrain from showing, will be removed once a proper fix is added */ void setFogOcclusion(boolean b); // FIXME + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IStarlightAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IStarlightAccessor.java index 6618610be..017b8e712 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IStarlightAccessor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IStarlightAccessor.java @@ -16,9 +16,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; -public interface IStarlightAccessor extends IModAccessor { +public interface IStarlightAccessor extends IModAccessor +{ } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IBiomeWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IBiomeWrapper.java index 69fabc533..d2bf1072e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IBiomeWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IBiomeWrapper.java @@ -29,5 +29,6 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab public interface IBiomeWrapper extends IDhApiBiomeWrapper, IBindable { String getName(); - String serialize(); + String serialize(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java index 731893200..b5347de57 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java @@ -6,15 +6,14 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe import javax.annotation.Nullable; /** - * * @version 2022-9-16 */ public interface IClientLevelWrapper extends ILevelWrapper { - @Nullable - IServerLevelWrapper tryGetServerSideWrapper(); + @Nullable + IServerLevelWrapper tryGetServerSideWrapper(); - int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockState); + int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockState); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java index ecb627823..0bc41d07b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java @@ -29,7 +29,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab /** * Can be either a Server world or a Client world. - * + * * @author James Seibel * @version 2023-6-17 */ @@ -57,11 +57,11 @@ public interface ILevelWrapper extends IDhApiLevelWrapper, IBindable default IChunkWrapper tryGetChunk(DhChunkPos pos) { return null; } - boolean hasChunkLoaded(int chunkX, int chunkZ); - + boolean hasChunkLoaded(int chunkX, int chunkZ); + @Deprecated IBlockStateWrapper getBlockState(DhBlockPos pos); - + @Deprecated IBiomeWrapper getBiome(DhBlockPos pos); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java index 63bf3046f..925821e2a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java @@ -3,9 +3,11 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.world; import javax.annotation.Nullable; import java.io.File; -public interface IServerLevelWrapper extends ILevelWrapper { - @Nullable - IClientLevelWrapper tryGetClientLevelWrapper(); - - File getSaveFolder(); +public interface IServerLevelWrapper extends ILevelWrapper +{ + @Nullable + IClientLevelWrapper tryGetClientLevelWrapper(); + + File getSaveFolder(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvironmentWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvironmentWrapper.java index d7d282639..09a27bde8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvironmentWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvironmentWrapper.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - + package com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; @@ -38,7 +38,7 @@ public abstract class AbstractBatchGenerationEnvironmentWrapper public abstract void stop(); public abstract CompletableFuture generateChunks( - int minX, int minZ, int genSize, EDhApiWorldGenerationStep targetStep, + int minX, int minZ, int genSize, EDhApiWorldGenerationStep targetStep, ExecutorService worldGeneratorThreadPool, Consumer resultConsumer); } diff --git a/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestOne.java b/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestOne.java index d12d31b56..1402d3b0e 100644 --- a/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestOne.java +++ b/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestOne.java @@ -13,4 +13,5 @@ public interface ISingletonTestOne extends IBindable public int getValue(); public int getDependentValue(); + } diff --git a/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestTwo.java b/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestTwo.java index f7da32a76..0755c0327 100644 --- a/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestTwo.java +++ b/core/src/test/java/testItems/singletonInjection/interfaces/ISingletonTestTwo.java @@ -13,4 +13,5 @@ public interface ISingletonTestTwo extends IBindable public int getValue(); public int getDependentValue(); + } diff --git a/core/src/test/java/testItems/singletonInjection/objects/ConcreteSingletonTestBoth.java b/core/src/test/java/testItems/singletonInjection/objects/ConcreteSingletonTestBoth.java index 3bfe23a63..07e8878df 100644 --- a/core/src/test/java/testItems/singletonInjection/objects/ConcreteSingletonTestBoth.java +++ b/core/src/test/java/testItems/singletonInjection/objects/ConcreteSingletonTestBoth.java @@ -25,4 +25,5 @@ public class ConcreteSingletonTestBoth implements ISingletonTestOne, ISingletonT @Override public int getDependentValue() { return -1; } + } diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java index a4a38c278..646a97be9 100644 --- a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java +++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java @@ -15,10 +15,10 @@ public class LevelWrapperTest implements IDhApiLevelWrapper @Override public Object getWrappedMcObject() { return null; } - @Override + @Override public IDhApiDimensionTypeWrapper getDimensionType() { return null; } - @Override + @Override public EDhApiLevelType getLevelType() { return null; } @Override @@ -30,7 +30,7 @@ public class LevelWrapperTest implements IDhApiLevelWrapper @Override public int getHeight() { return 0; } - @Override + @Override public int getMinHeight() { return IDhApiLevelWrapper.super.getMinHeight(); } } diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/TestWorldGenerator.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/TestWorldGenerator.java index 879b4db03..b6e634981 100644 --- a/core/src/test/java/testItems/worldGeneratorInjection/objects/TestWorldGenerator.java +++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/TestWorldGenerator.java @@ -52,7 +52,7 @@ public class TestWorldGenerator implements IDhApiWorldGenerator //===================// @Override - public void close() { } + public void close() { } @Override public boolean isBusy() { return false; } @@ -61,7 +61,7 @@ public class TestWorldGenerator implements IDhApiWorldGenerator public CompletableFuture generateChunks(int chunkPosMinX, int chunkPosMinZ, byte granularity, byte targetDataDetail, EDhApiDistantGeneratorMode maxGenerationStep, ExecutorService executorService, Consumer resultConsumer) { return null; } @Override - public void preGeneratorTaskStart() { } + public void preGeneratorTaskStart() { } } diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestCore.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestCore.java index a44bb428b..c415a05d0 100644 --- a/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestCore.java +++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestCore.java @@ -1,6 +1,7 @@ package testItems.worldGeneratorInjection.objects; import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; + /** * Dummy test implementation object for world generator injection unit tests. * diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestPrimary.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestPrimary.java index abf34e20b..22c6cd6a7 100644 --- a/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestPrimary.java +++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/WorldGeneratorTestPrimary.java @@ -13,7 +13,7 @@ public class WorldGeneratorTestPrimary extends TestWorldGenerator public static int PRIORITY = OverrideInjector.DEFAULT_NON_CORE_OVERRIDE_PRIORITY + 5; public static final byte SMALLEST_DETAIL_LEVEL = 2; - + @Override public int getPriority() { return PRIORITY; } diff --git a/core/src/test/java/tests/CompressionTest.java b/core/src/test/java/tests/CompressionTest.java index e20019184..631f68655 100644 --- a/core/src/test/java/tests/CompressionTest.java +++ b/core/src/test/java/tests/CompressionTest.java @@ -37,18 +37,18 @@ import java.util.ArrayList; /** * Results (2023-5-20):
* 200 files

- * + * * uncompressed

- * + * * render data - ratio 1.0 (shocker :P)
* read time in - 784 ms, avg 3 ms/file
* write time in - 803 ms, avg 4 ms/file

- * + * * full data - ratio 1.0
* read time in - 2,213 ms, avg 11 ms/file
* write time in - 1,753 ms, avg 8 ms/file


* - * + * * XZ

* * render data - ratio 0.1044
@@ -58,8 +58,8 @@ import java.util.ArrayList; * full data - ratio 0.1123
* read time in - 5,888 ms, avg 29 ms/file
* write time in - 79,675 ms, avg 398 ms/file


- * - * + * + * * LZ4

* * render data - ratio 0.2933
@@ -69,8 +69,8 @@ import java.util.ArrayList; * full data - ratio 0.3275
* read time in - 1,964 ms, avg 9 ms/file
* write time in - 1,584 ms, avg 7 ms/file


- * - * + * + * * Z Standard

* * render data - ratio 0.1791
@@ -80,9 +80,9 @@ import java.util.ArrayList; * full data - ratio 0.2060
* read time in - 14,754 ms, avg 73 ms/file
* write time in - 14,057 ms, avg 70 ms/file


- * * - * + * + * * Note: * In order to test the compressors that aren't currently in use:
* 1. Generate DH data and point the {@link CompressionTest#TEST_DIR} variable to the "Distant_Horizons" folder. @@ -106,7 +106,7 @@ public class CompressionTest -// @Test + // @Test public void NoCompression() { String compressorName = "Uncompressed"; @@ -115,13 +115,13 @@ public class CompressionTest CreateOutputStreamFunc createOutputStreamFunc = (outputStream) -> outputStream; - System.out.println(compressorName+" testing render data"); + System.out.println(compressorName + " testing render data"); this.testCompressor(compressorName, RENDER_DATA_PATH, createInputStreamFunc, createOutputStreamFunc); - System.out.println(compressorName+" testing full data"); + System.out.println(compressorName + " testing full data"); this.testCompressor(compressorName, FULL_DATA_PATH, createInputStreamFunc, createOutputStreamFunc); } -// @Test + // @Test public void Lz4() { String compressorName = "LZ4"; @@ -130,12 +130,12 @@ public class CompressionTest CreateOutputStreamFunc createOutputStreamFunc = (outputStream) -> new LZ4FrameOutputStream(outputStream); - System.out.println(compressorName+" testing render data"); + System.out.println(compressorName + " testing render data"); this.testCompressor(compressorName, RENDER_DATA_PATH, createInputStreamFunc, createOutputStreamFunc); - System.out.println(compressorName+" testing full data"); + System.out.println(compressorName + " testing full data"); this.testCompressor(compressorName, FULL_DATA_PATH, createInputStreamFunc, createOutputStreamFunc); } - + // @Test // public void Zstandard() // { @@ -150,7 +150,7 @@ public class CompressionTest // System.out.println(compressorName+" testing full data"); // this.testCompressor(compressorName, FULL_DATA_PATH, createInputStreamFunc, createOutputStreamFunc); // } - + // @Test // public void Xz() // { @@ -173,9 +173,18 @@ public class CompressionTest //=================// @FunctionalInterface - public interface CreateInputStreamFunc { InputStream apply(InputStream inputStream) throws Exception; } + public interface CreateInputStreamFunc + { + InputStream apply(InputStream inputStream) throws Exception; + + } + @FunctionalInterface - public interface CreateOutputStreamFunc { OutputStream apply(OutputStream outputStream) throws Exception; } + public interface CreateOutputStreamFunc + { + OutputStream apply(OutputStream outputStream) throws Exception; + + } private void testCompressor( String compressorName, String inputFolderPath, @@ -194,7 +203,7 @@ public class CompressionTest File[] inputFileArray = inputFolder.listFiles(); Assert.assertNotNull(inputFileArray); - File compressedFolder = new File(inputFolderPath+"\\"+compressorName); + File compressedFolder = new File(inputFolderPath + "\\" + compressorName); compressedFolder.delete(); compressedFolder.mkdirs(); @@ -231,7 +240,8 @@ public class CompressionTest originalFileByteArray.add(nextByte); } } - catch (EOFException e) { /* end of file reached */ } + catch (EOFException e) + { /* end of file reached */ } } @@ -239,7 +249,7 @@ public class CompressionTest // compress file // long startWriteMsTime = System.currentTimeMillis(); - File compressedFile = new File(inputFolderPath+"\\"+compressorName+"\\"+inputFile.getName()); + File compressedFile = new File(inputFolderPath + "\\" + compressorName + "\\" + inputFile.getName()); compressedFile.delete(); compressedFile.createNewFile(); @@ -278,7 +288,8 @@ public class CompressionTest compressedFileByteArray.add(nextByte); } } - catch (EOFException e) { /* end of file reached */ } + catch (EOFException e) + { /* end of file reached */ } } long endReadMsTime = System.currentTimeMillis(); @@ -289,7 +300,7 @@ public class CompressionTest Assert.assertEquals("byte array size mismatch", compressedFileByteArray.size(), originalFileByteArray.size()); for (int i = 0; i < compressedFileByteArray.size(); i++) { - Assert.assertEquals("array content mismatch at index ["+i+"]", compressedFileByteArray.get(i), originalFileByteArray.get(i)); + Assert.assertEquals("array content mismatch at index [" + i + "]", compressedFileByteArray.get(i), originalFileByteArray.get(i)); } @@ -298,12 +309,12 @@ public class CompressionTest double compressionRatio = (totalCompressedFileSizeInBytes / (double) totalUncompressedFileSizeInBytes); - String compressionRatioString = compressionRatio+""; - compressionRatioString = compressionRatioString.substring(0, Math.min(6,compressionRatioString.length())); + String compressionRatioString = compressionRatio + ""; + compressionRatioString = compressionRatioString.substring(0, Math.min(6, compressionRatioString.length())); - System.out.println("Uncompressed file size: ["+humanReadableByteCountSI(totalUncompressedFileSizeInBytes)+"] Compressed file size: ["+humanReadableByteCountSI(totalCompressedFileSizeInBytes)+"]. Compression ratio: ["+compressionRatioString+"]."); - System.out.println("Total read time in MS: ["+totalReadTimeInMs+"] Average read time per file: ["+(totalReadTimeInMs/processedFileCount)+"]"); - System.out.println("Total write time in MS: ["+totalWriteTimeInMs+"] Average write time per file: ["+(totalWriteTimeInMs/processedFileCount)+"]"); + System.out.println("Uncompressed file size: [" + humanReadableByteCountSI(totalUncompressedFileSizeInBytes) + "] Compressed file size: [" + humanReadableByteCountSI(totalCompressedFileSizeInBytes) + "]. Compression ratio: [" + compressionRatioString + "]."); + System.out.println("Total read time in MS: [" + totalReadTimeInMs + "] Average read time per file: [" + (totalReadTimeInMs / processedFileCount) + "]"); + System.out.println("Total write time in MS: [" + totalWriteTimeInMs + "] Average write time per file: [" + (totalWriteTimeInMs / processedFileCount) + "]"); } catch (Exception e) { diff --git a/core/src/test/java/tests/DependencyInjectorTest.java b/core/src/test/java/tests/DependencyInjectorTest.java index e84201de7..9fc22e2c5 100644 --- a/core/src/test/java/tests/DependencyInjectorTest.java +++ b/core/src/test/java/tests/DependencyInjectorTest.java @@ -98,30 +98,38 @@ public class DependencyInjectorTest { OverrideInjector TEST_INJECTOR = new OverrideInjector(OverrideTestAssembly.getPackagePath(2)); OverrideInjector CORE_INJECTOR = new OverrideInjector(); - - + + // pre-dependency setup Assert.assertNull("Nothing should have been bound.", TEST_INJECTOR.get(IOverrideTest.class)); Assert.assertNull("Nothing should have been bound.", CORE_INJECTOR.get(IOverrideTest.class)); - - + + // variables to use later IOverrideTest override; OverrideTestCore coreOverride = new OverrideTestCore(); OverrideTestPrimary primaryOverride = new OverrideTestPrimary(); - - + + // core override binding - try { TEST_INJECTOR.bind(IOverrideTest.class, coreOverride); } catch (IllegalArgumentException e) { Assert.fail("Core override should be bindable for test package injector."); } - + try + { + TEST_INJECTOR.bind(IOverrideTest.class, coreOverride); + } + catch (IllegalArgumentException e) + { + Assert.fail("Core override should be bindable for test package injector."); + } + try { CORE_INJECTOR.bind(IOverrideTest.class, coreOverride); Assert.fail("Core override should not be bindable for core package injector."); } - catch (IllegalArgumentException e) { /* this exception should be thrown */ } - - + catch (IllegalArgumentException e) + { /* this exception should be thrown */ } + + // core override Assert.assertNotNull("Test injector should've bound core override.", TEST_INJECTOR.get(IOverrideTest.class)); Assert.assertNull("Core injector should not have bound core override.", CORE_INJECTOR.get(IOverrideTest.class)); @@ -132,8 +140,8 @@ public class DependencyInjectorTest override = TEST_INJECTOR.get(IOverrideTest.class); Assert.assertEquals("Override returned incorrect override type.", override.getPriority(), OverrideInjector.CORE_PRIORITY); Assert.assertEquals("Incorrect override object returned.", override.getValue(), OverrideTestCore.VALUE); - - + + // default override TEST_INJECTOR.bind(IOverrideTest.class, primaryOverride); // priority gets @@ -144,12 +152,12 @@ public class DependencyInjectorTest override = TEST_INJECTOR.get(IOverrideTest.class); Assert.assertEquals("Override returned incorrect override type.", override.getPriority(), OverrideTestPrimary.PRIORITY); Assert.assertEquals("Incorrect override object returned.", override.getValue(), OverrideTestPrimary.VALUE); - - + + // in-line get // (make sure the returned type is correct and compiles, the actual value doesn't matter) TEST_INJECTOR.get(IOverrideTest.class).getValue(); - + } @Test @@ -174,7 +182,14 @@ public class DependencyInjectorTest // bind the core generator // - try { TEST_INJECTOR.bind(boundLevel, coreLevelGenerator); } catch (IllegalArgumentException e) { Assert.fail("[" + coreLevelGenerator.getClass().getSimpleName() + "] should be bindable for test package injector."); } + try + { + TEST_INJECTOR.bind(boundLevel, coreLevelGenerator); + } + catch (IllegalArgumentException e) + { + Assert.fail("[" + coreLevelGenerator.getClass().getSimpleName() + "] should be bindable for test package injector."); + } // validate the core generator was bound generator = TEST_INJECTOR.get(boundLevel); @@ -188,7 +203,14 @@ public class DependencyInjectorTest // bind the secondary generator // - try { TEST_INJECTOR.bind(boundLevel, secondaryLevelGenerator); } catch (IllegalArgumentException e) { Assert.fail("[" + secondaryLevelGenerator.getClass().getSimpleName() + "] should be bindable for test package injector."); } + try + { + TEST_INJECTOR.bind(boundLevel, secondaryLevelGenerator); + } + catch (IllegalArgumentException e) + { + Assert.fail("[" + secondaryLevelGenerator.getClass().getSimpleName() + "] should be bindable for test package injector."); + } // validate the secondary generator overrides the core generator generator = TEST_INJECTOR.get(boundLevel); @@ -202,7 +224,14 @@ public class DependencyInjectorTest // bind the primary generator // - try { TEST_INJECTOR.bind(boundLevel, primaryLevelGenerator); } catch (IllegalArgumentException e) { Assert.fail("[" + primaryLevelGenerator.getClass().getSimpleName() + "] should be bindable for test package injector."); } + try + { + TEST_INJECTOR.bind(boundLevel, primaryLevelGenerator); + } + catch (IllegalArgumentException e) + { + Assert.fail("[" + primaryLevelGenerator.getClass().getSimpleName() + "] should be bindable for test package injector."); + } // validate the primary generator overrides both the core and secondary generator generator = TEST_INJECTOR.get(boundLevel); diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java index 97c9149ac..a837557f4 100644 --- a/core/src/test/java/tests/DhSectionPosTest.java +++ b/core/src/test/java/tests/DhSectionPosTest.java @@ -29,36 +29,36 @@ public class DhSectionPosTest @Test public void ContainsPosTest() { - DhSectionPos root = new DhSectionPos((byte)10, 0, 0); - DhSectionPos child = new DhSectionPos((byte)9, 1, 1); + DhSectionPos root = new DhSectionPos((byte) 10, 0, 0); + DhSectionPos child = new DhSectionPos((byte) 9, 1, 1); Assert.assertTrue("section pos contains fail", root.contains(child)); Assert.assertFalse("section pos contains fail", child.contains(root)); - root = new DhSectionPos((byte)10, 1, 0); + root = new DhSectionPos((byte) 10, 1, 0); // out of bounds - child = new DhSectionPos((byte)9, 0, 0); + child = new DhSectionPos((byte) 9, 0, 0); Assert.assertFalse("position should be out of bounds", root.contains(child)); - child = new DhSectionPos((byte)9, 1, 1); + child = new DhSectionPos((byte) 9, 1, 1); Assert.assertFalse("position should be out of bounds", root.contains(child)); // in bounds - child = new DhSectionPos((byte)9, 2, 0); + child = new DhSectionPos((byte) 9, 2, 0); Assert.assertTrue("position should be in bounds", root.contains(child)); - child = new DhSectionPos((byte)9, 3, 1); + child = new DhSectionPos((byte) 9, 3, 1); Assert.assertTrue("position should be in bounds", root.contains(child)); // out of bounds - child = new DhSectionPos((byte)9, 2, 2); + child = new DhSectionPos((byte) 9, 2, 2); Assert.assertFalse("position should be out of bounds", root.contains(child)); - child = new DhSectionPos((byte)9, 3, 3); + child = new DhSectionPos((byte) 9, 3, 3); Assert.assertFalse("position should be out of bounds", root.contains(child)); - child = new DhSectionPos((byte)9, 4, 4); + child = new DhSectionPos((byte) 9, 4, 4); Assert.assertFalse("position should be out of bounds", root.contains(child)); - child = new DhSectionPos((byte)9, 5, 5); + child = new DhSectionPos((byte) 9, 5, 5); Assert.assertFalse("position should be out of bounds", root.contains(child)); } @@ -66,15 +66,15 @@ public class DhSectionPosTest public void ContainsAdjacentPosTest() { // neither should contain the other, they are single blocks that are next to each other - DhSectionPos left = new DhSectionPos((byte)0, 4606, 0); - DhSectionPos right = new DhSectionPos((byte)0, 4607, 0); + DhSectionPos left = new DhSectionPos((byte) 0, 4606, 0); + DhSectionPos right = new DhSectionPos((byte) 0, 4607, 0); Assert.assertFalse(left.contains(right)); Assert.assertFalse(right.contains(left)); // 512 block wide sections that are adjacent, but not overlapping - left = new DhSectionPos((byte)9, 0, 0); - right = new DhSectionPos((byte)9, 1, 0); + left = new DhSectionPos((byte) 9, 0, 0); + right = new DhSectionPos((byte) 9, 1, 0); Assert.assertFalse(left.contains(right)); Assert.assertFalse(right.contains(left)); @@ -83,23 +83,23 @@ public class DhSectionPosTest @Test public void ParentPosTest() { - DhSectionPos leaf = new DhSectionPos((byte)0, 0, 0); - DhSectionPos convert = leaf.convertToDetailLevel((byte)1); + DhSectionPos leaf = new DhSectionPos((byte) 0, 0, 0); + DhSectionPos convert = leaf.convertToDetailLevel((byte) 1); DhSectionPos parent = leaf.getParentPos(); Assert.assertEquals("get parent at 0,0 fail", convert, parent); - leaf = new DhSectionPos((byte)0, 1, 1); - convert = leaf.convertToDetailLevel((byte)1); + leaf = new DhSectionPos((byte) 0, 1, 1); + convert = leaf.convertToDetailLevel((byte) 1); parent = leaf.getParentPos(); Assert.assertEquals("get parent at 1,1 fail", convert, parent); - leaf = new DhSectionPos((byte)1, 2, 2); - convert = leaf.convertToDetailLevel((byte)2); + leaf = new DhSectionPos((byte) 1, 2, 2); + convert = leaf.convertToDetailLevel((byte) 2); parent = leaf.getParentPos(); Assert.assertEquals("parent upscale fail", convert, parent); - convert = leaf.convertToDetailLevel((byte)0); + convert = leaf.convertToDetailLevel((byte) 0); DhSectionPos childIndex = leaf.getChildByIndex(0); Assert.assertEquals("child detail fail", convert, childIndex); @@ -108,7 +108,7 @@ public class DhSectionPosTest @Test public void ChildPosTest() { - DhSectionPos node = new DhSectionPos((byte)1, 2302, 0); + DhSectionPos node = new DhSectionPos((byte) 1, 2302, 0); DhSectionPos nw = node.getChildByIndex(0); DhSectionPos sw = node.getChildByIndex(1); DhSectionPos ne = node.getChildByIndex(2); @@ -120,26 +120,26 @@ public class DhSectionPosTest Assert.assertNotEquals(ne, se); // confirm each child has the correct value - Assert.assertEquals(nw, new DhSectionPos((byte)0, 4604, 0)); - Assert.assertEquals(sw, new DhSectionPos((byte)0, 4605, 0)); - Assert.assertEquals(ne, new DhSectionPos((byte)0, 4604, 1)); - Assert.assertEquals(se, new DhSectionPos((byte)0, 4605, 1)); + Assert.assertEquals(nw, new DhSectionPos((byte) 0, 4604, 0)); + Assert.assertEquals(sw, new DhSectionPos((byte) 0, 4605, 0)); + Assert.assertEquals(ne, new DhSectionPos((byte) 0, 4604, 1)); + Assert.assertEquals(se, new DhSectionPos((byte) 0, 4605, 1)); } @Test public void GetCenterTest() { - DhSectionPos node = new DhSectionPos((byte)1, 2303, 0); + DhSectionPos node = new DhSectionPos((byte) 1, 2303, 0); DhLodPos centerNode = node.getCenter(); - DhLodPos expectedCenterNode = new DhLodPos((byte)0, 4606,0); + DhLodPos expectedCenterNode = new DhLodPos((byte) 0, 4606, 0); Assert.assertEquals("", expectedCenterNode, centerNode); - node = new DhSectionPos((byte)10, 0, 0); // 1024 blocks wide + node = new DhSectionPos((byte) 10, 0, 0); // 1024 blocks wide centerNode = node.getCenter(); - expectedCenterNode = new DhLodPos((byte)0, 1024/2,1024/2); + expectedCenterNode = new DhLodPos((byte) 0, 1024 / 2, 1024 / 2); Assert.assertEquals("", expectedCenterNode, centerNode); } @@ -147,15 +147,15 @@ public class DhSectionPosTest @Test public void GetCenter2Test() { - DhSectionPos parentNode = new DhSectionPos((byte)2, 1151, 0); // width 4 blocks - DhSectionPos inputPos = new DhSectionPos((byte)0, 4606, 0); // width 1 block + DhSectionPos parentNode = new DhSectionPos((byte) 2, 1151, 0); // width 4 blocks + DhSectionPos inputPos = new DhSectionPos((byte) 0, 4606, 0); // width 1 block Assert.assertTrue(parentNode.contains(inputPos)); DhLodPos parentCenter = parentNode.getCenter(); DhLodPos inputCenter = inputPos.getCenter(); - Assert.assertEquals(new DhLodPos((byte)0, 4606, 2), parentCenter); - Assert.assertEquals(new DhLodPos((byte)0, 4606, 0), inputCenter); + Assert.assertEquals(new DhLodPos((byte) 0, 4606, 2), parentCenter); + Assert.assertEquals(new DhLodPos((byte) 0, 4606, 0), inputCenter); } diff --git a/core/src/test/java/tests/ExampleTest.java b/core/src/test/java/tests/ExampleTest.java index de45feab0..150f77422 100644 --- a/core/src/test/java/tests/ExampleTest.java +++ b/core/src/test/java/tests/ExampleTest.java @@ -24,7 +24,7 @@ import org.junit.Test; /** * This is just a quick demo to confirm the testing system is set up correctly. - * + * * @author James Seibel * @version 2022-9-5 */ diff --git a/core/src/test/java/tests/QuadTreeTest.java b/core/src/test/java/tests/QuadTreeTest.java index 80bbebc0e..35827b1e7 100644 --- a/core/src/test/java/tests/QuadTreeTest.java +++ b/core/src/test/java/tests/QuadTreeTest.java @@ -55,34 +55,34 @@ public class QuadTreeTest { AbstractTestTreeParams treeParams = new LargeTestTree(); QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), treeParams.getPositiveEdgeCenterPos(), LodUtil.BLOCK_DETAIL_LEVEL); - Assert.assertTrue("Tree min/max detail level out of expected bounds: "+tree, tree.treeMaxDetailLevel >= 10 && tree.treeMinDetailLevel <= 10 - 4); + Assert.assertTrue("Tree min/max detail level out of expected bounds: " + tree, tree.treeMaxDetailLevel >= 10 && tree.treeMinDetailLevel <= 10 - 4); // (pseudo) root node // - testSet(tree, new DhSectionPos((byte)10, 0, 0), 0); + testSet(tree, new DhSectionPos((byte) 10, 0, 0), 0); // first child (0,0) // - testSet(tree, new DhSectionPos((byte)9, 0, 0), 1); - testSet(tree, new DhSectionPos((byte)9, 1, 0), 2); - testSet(tree, new DhSectionPos((byte)9, 0, 1), 3); - testSet(tree, new DhSectionPos((byte)9, 1, 1), 4); + testSet(tree, new DhSectionPos((byte) 9, 0, 0), 1); + testSet(tree, new DhSectionPos((byte) 9, 1, 0), 2); + testSet(tree, new DhSectionPos((byte) 9, 0, 1), 3); + testSet(tree, new DhSectionPos((byte) 9, 1, 1), 4); // second child (0,0) (0,0) // - testSet(tree, new DhSectionPos((byte)8, 0, 0), 5); - testSet(tree, new DhSectionPos((byte)8, 1, 0), 6); - testSet(tree, new DhSectionPos((byte)8, 0, 1), 7); - testSet(tree, new DhSectionPos((byte)8, 1, 1), 8); + testSet(tree, new DhSectionPos((byte) 8, 0, 0), 5); + testSet(tree, new DhSectionPos((byte) 8, 1, 0), 6); + testSet(tree, new DhSectionPos((byte) 8, 0, 1), 7); + testSet(tree, new DhSectionPos((byte) 8, 1, 1), 8); // second child (0,0) (1,1) // - testSet(tree, new DhSectionPos((byte)8, 2, 2), 9); - testSet(tree, new DhSectionPos((byte)8, 3, 2), 10); - testSet(tree, new DhSectionPos((byte)8, 2, 3), 11); - testSet(tree, new DhSectionPos((byte)8, 3, 3), 12); + testSet(tree, new DhSectionPos((byte) 8, 2, 2), 9); + testSet(tree, new DhSectionPos((byte) 8, 3, 2), 10); + testSet(tree, new DhSectionPos((byte) 8, 2, 3), 11); + testSet(tree, new DhSectionPos((byte) 8, 3, 3), 12); // third child (0,0) (1,0) (0,0) // - testSet(tree, new DhSectionPos((byte)7, 5, 0), 9); - testSet(tree, new DhSectionPos((byte)7, 6, 0), 10); - testSet(tree, new DhSectionPos((byte)7, 5, 1), 11); - testSet(tree, new DhSectionPos((byte)7, 6, 1), 12); + testSet(tree, new DhSectionPos((byte) 7, 5, 0), 9); + testSet(tree, new DhSectionPos((byte) 7, 6, 0), 10); + testSet(tree, new DhSectionPos((byte) 7, 5, 1), 11); + testSet(tree, new DhSectionPos((byte) 7, 6, 1), 12); } @@ -94,13 +94,13 @@ public class QuadTreeTest // root node // - testSet(tree, new DhSectionPos((byte)10, -1, -1), 0); + testSet(tree, new DhSectionPos((byte) 10, -1, -1), 0); // first child (-1,-1) // - testSet(tree, new DhSectionPos((byte)9, -2, -1), 1); - testSet(tree, new DhSectionPos((byte)9, -1, -1), 2); - testSet(tree, new DhSectionPos((byte)9, -2, -2), 3); - testSet(tree, new DhSectionPos((byte)9, -1, -2), 4); + testSet(tree, new DhSectionPos((byte) 9, -2, -1), 1); + testSet(tree, new DhSectionPos((byte) 9, -1, -1), 2); + testSet(tree, new DhSectionPos((byte) 9, -2, -2), 3); + testSet(tree, new DhSectionPos((byte) 9, -1, -2), 4); // TODO // // second child (-1,-1) (0,0) // @@ -126,41 +126,41 @@ public class QuadTreeTest public void OutOfBoundsQuadTreeTest() { AbstractTestTreeParams treeParams = new LargeTestTree(); - QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0,0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), LodUtil.BLOCK_DETAIL_LEVEL); Assert.assertEquals("tree diameter incorrect", treeParams.getWidthInBlocks(), tree.diameterInBlocks()); // wrong detail level on purpose, if the detail level was 0 (block) this should work - DhSectionPos outOfBoundsPos = new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2), 0); + DhSectionPos outOfBoundsPos = new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // out of bounds // - outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2) + 1, 0); + outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); - outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2), 0); + outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // in bounds // - outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2)-1, 0); + outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); - outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2)-3, 0); + outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); // TODO this position probably has trouble with getting the center. - outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2)-2, 0); + outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 3, tree.leafNodeCount()); - outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks()/2)-4, 0); + outOfBoundsPos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 4, tree.leafNodeCount()); @@ -169,19 +169,19 @@ public class QuadTreeTest public void outOfBoundsInTreeTest() { // very specific tree parameters to match test results - QuadTree tree = new QuadTree<>(512, new DhBlockPos2D(125, -516), (byte)6); + QuadTree tree = new QuadTree<>(512, new DhBlockPos2D(125, -516), (byte) 6); Assert.assertEquals("Test may need to be re-calculated for different max detail level.", 9, tree.treeMaxDetailLevel); - DhSectionPos rootPos = new DhSectionPos((byte)9, 0, -1); + DhSectionPos rootPos = new DhSectionPos((byte) 9, 0, -1); testSet(tree, rootPos, 1); // pos is in tree, but out of range - DhSectionPos midPos = new DhSectionPos((byte)8, 0, -1); + DhSectionPos midPos = new DhSectionPos((byte) 8, 0, -1); testSet(tree, midPos, 2, IndexOutOfBoundsException.class); // pos is in tree, but out of range - DhSectionPos leafPos = new DhSectionPos((byte)7, 0, -2); + DhSectionPos leafPos = new DhSectionPos((byte) 7, 0, -2); testSet(tree, leafPos, 3, IndexOutOfBoundsException.class); } @@ -197,7 +197,7 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, new DhSectionPos((byte)10, 0, 0), 1); + testSet(tree, new DhSectionPos((byte) 10, 0, 0), 1); // first child (0,0) // DhSectionPos nw = new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); @@ -224,7 +224,7 @@ public class QuadTreeTest // small move // - DhBlockPos2D smallMoveBlockPos = new DhBlockPos2D(pseudoRootNodeWidthInBlocks*2, 0); // move enough that the original root nodes aren't touching the same grid squares they were before, but not far enough as to be garbage collected (TODO reword) + DhBlockPos2D smallMoveBlockPos = new DhBlockPos2D(pseudoRootNodeWidthInBlocks * 2, 0); // move enough that the original root nodes aren't touching the same grid squares they were before, but not far enough as to be garbage collected (TODO reword) tree.setCenterBlockPos(smallMoveBlockPos); Assert.assertEquals("Tree center incorrect", smallMoveBlockPos, tree.getCenterBlockPos()); @@ -259,17 +259,17 @@ public class QuadTreeTest Assert.assertEquals("Tree center incorrect", DhBlockPos2D.ZERO, tree.getCenterBlockPos()); // on the negative X edge - DhSectionPos edgePos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks()/2, 0); + DhSectionPos edgePos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); testSet(tree, edgePos, 1); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); // +1 root node from the negative X edge - DhSectionPos adjacentEdgePos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks()/2)+pseudoRootNodeWidthInBlocks, 0); + DhSectionPos adjacentEdgePos = new DhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); testSet(tree, adjacentEdgePos, 2); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); // move so only the root nodes exactly on the X edge remain - DhBlockPos2D edgeMoveBlockPos = new DhBlockPos2D(pseudoRootNodeWidthInBlocks - (treeParams.getWidthInRootNodes()*pseudoRootNodeWidthInBlocks), 0); + DhBlockPos2D edgeMoveBlockPos = new DhBlockPos2D(pseudoRootNodeWidthInBlocks - (treeParams.getWidthInRootNodes() * pseudoRootNodeWidthInBlocks), 0); tree.setCenterBlockPos(edgeMoveBlockPos); Assert.assertEquals("Tree center incorrect", edgeMoveBlockPos, tree.getCenterBlockPos()); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); @@ -284,14 +284,14 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, new DhSectionPos((byte)10, 0, 0), 1); - testSet(tree, new DhSectionPos((byte)10, 1, 0), 2); + testSet(tree, new DhSectionPos((byte) 10, 0, 0), 1); + testSet(tree, new DhSectionPos((byte) 10, 1, 0), 2); // first child (0,0) // - testSet(tree, new DhSectionPos((byte)9, 0, 0), 3); - testSet(tree, new DhSectionPos((byte)9, 1, 0), 4); - testSet(tree, new DhSectionPos((byte)9, 0, 1), 5); - testSet(tree, new DhSectionPos((byte)9, 1, 1), 6); + testSet(tree, new DhSectionPos((byte) 9, 0, 0), 3); + testSet(tree, new DhSectionPos((byte) 9, 1, 0), 4); + testSet(tree, new DhSectionPos((byte) 9, 0, 1), 5); + testSet(tree, new DhSectionPos((byte) 9, 1, 1), 6); @@ -304,7 +304,7 @@ public class QuadTreeTest QuadNode rootNode = tree.getNode(rootNodePosIterator.next()); if (rootNode != null) { - rootNodeCount++; + rootNodeCount++; } } Assert.assertEquals("incorrect root count", 1, rootNodeCount); @@ -332,19 +332,19 @@ public class QuadTreeTest public void NewQuadTreeIterationTest() { AbstractTestTreeParams treeParams = new LargeTestTree(); - QuadNode rootNode = new QuadNode<>(new DhSectionPos((byte)10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(new DhSectionPos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(new DhSectionPos((byte)10, 0, 0), 0); + rootNode.setValue(new DhSectionPos((byte) 10, 0, 0), 0); - rootNode.setValue(new DhSectionPos((byte)9, 0, 0), 1); - rootNode.setValue(new DhSectionPos((byte)9, 1, 0), 1); - rootNode.setValue(new DhSectionPos((byte)9, 0, 1), 1); - rootNode.setValue(new DhSectionPos((byte)9, 1, 1), null); + rootNode.setValue(new DhSectionPos((byte) 9, 0, 0), 1); + rootNode.setValue(new DhSectionPos((byte) 9, 1, 0), 1); + rootNode.setValue(new DhSectionPos((byte) 9, 0, 1), 1); + rootNode.setValue(new DhSectionPos((byte) 9, 1, 1), null); - rootNode.setValue(new DhSectionPos((byte)8, 0, 0), 2); - rootNode.setValue(new DhSectionPos((byte)8, 1, 0), 2); - rootNode.setValue(new DhSectionPos((byte)8, 0, 1), 2); - rootNode.setValue(new DhSectionPos((byte)8, 1, 1), null); + rootNode.setValue(new DhSectionPos((byte) 8, 0, 0), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 1, 0), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 0, 1), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 1, 1), null); @@ -366,7 +366,7 @@ public class QuadTreeTest if (!iteratedNodes.add(node)) { - Assert.fail("Iterator passed over the same node multiple times. Section Pos: "+node.sectionPos); + Assert.fail("Iterator passed over the same node multiple times. Section Pos: " + node.sectionPos); } totalNodeCount++; @@ -395,7 +395,7 @@ public class QuadTreeTest if (!iteratedLeafNodes.add(node)) { - Assert.fail("Iterator passed over the same node multiple times. Section Pos: "+node.sectionPos); + Assert.fail("Iterator passed over the same node multiple times. Section Pos: " + node.sectionPos); } totalLeafCount++; @@ -561,21 +561,21 @@ public class QuadTreeTest public void TreeDetailLevelLimitTest() { AbstractTestTreeParams treeParams = new MediumTestTree(); - QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte)8); + QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte) 8); Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMaxDetailLevel); // valid detail levels - testSet(tree, new DhSectionPos((byte)10, 0, 0), 1); - testSet(tree, new DhSectionPos((byte)9, 0, 0), 2); - testSet(tree, new DhSectionPos((byte)8, 0, 0), 3); + testSet(tree, new DhSectionPos((byte) 10, 0, 0), 1); + testSet(tree, new DhSectionPos((byte) 9, 0, 0), 2); + testSet(tree, new DhSectionPos((byte) 8, 0, 0), 3); // detail level too low - testSet(tree, new DhSectionPos((byte)7, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, new DhSectionPos((byte)6, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, new DhSectionPos((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, new DhSectionPos((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); // detail level too high - testSet(tree, new DhSectionPos((byte)11, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, new DhSectionPos((byte)12, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, new DhSectionPos((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, new DhSectionPos((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); } @@ -583,12 +583,12 @@ public class QuadTreeTest public void QuadNodeDetailLimitTest() { AbstractTestTreeParams treeParams = new MediumTestTree(); - QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte)6); + QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte) 6); Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMaxDetailLevel); - + // create the root node - testSet(tree, new DhSectionPos((byte)10, 0, 0), 1); - + testSet(tree, new DhSectionPos((byte) 10, 0, 0), 1); + AtomicInteger minimumDetailLevelReachedRef = new AtomicInteger(tree.treeMaxDetailLevel); @@ -649,7 +649,7 @@ public class QuadTreeTest DhSectionPos sectionPos = directChildIterator.next(); QuadNode childNode = node.getNode(sectionPos); - Assert.assertTrue("Child node recurred too low. Min detail level: "+minDetailLevel+", node detail level: "+childNode.sectionPos.sectionDetailLevel, childNode.sectionPos.sectionDetailLevel >= minDetailLevel); + Assert.assertTrue("Child node recurred too low. Min detail level: " + minDetailLevel + ", node detail level: " + childNode.sectionPos.sectionDetailLevel, childNode.sectionPos.sectionDetailLevel >= minDetailLevel); recursivelyCreateNodeChildren(childNode, minDetailLevel, minimumDetailLevelReachedRef); childNodesIterated = true; @@ -671,14 +671,14 @@ public class QuadTreeTest } if (childNodesIterated) { - Assert.assertTrue("node children iterated below minimum detail level", node.sectionPos.sectionDetailLevel-1 >= minDetailLevel); + Assert.assertTrue("node children iterated below minimum detail level", node.sectionPos.sectionDetailLevel - 1 >= minDetailLevel); } } @Test public void quadNodeChildPositionIndexTest() { - QuadNode rootNode = new QuadNode<>(new DhSectionPos((byte)10, 0, 0), (byte)0); + QuadNode rootNode = new QuadNode<>(new DhSectionPos((byte) 10, 0, 0), (byte) 0); Iterator directChildPosIterator = rootNode.getChildPosIterator(); while (directChildPosIterator.hasNext()) { @@ -694,7 +694,7 @@ public class QuadTreeTest { DhSectionPos childPos = rootNode.sectionPos.getChildByIndex(i); QuadNode childNode = rootNode.getChildByIndex(i); - Assert.assertEquals("child position not the same as "+DhSectionPos.class.getSimpleName()+"'s getChildByIndex()", childPos, childNode.sectionPos); + Assert.assertEquals("child position not the same as " + DhSectionPos.class.getSimpleName() + "'s getChildByIndex()", childPos, childNode.sectionPos); } } @@ -703,12 +703,12 @@ public class QuadTreeTest public void quadNodeChildPositionOutOfBoundsTest() { int treeWidthInBlocks = 64; - QuadTree tree = new QuadTree<>(treeWidthInBlocks, new DhBlockPos2D(-2, 0), (byte)0); + QuadTree tree = new QuadTree<>(treeWidthInBlocks, new DhBlockPos2D(-2, 0), (byte) 0); // center root node - DhSectionPos centerNodePos = new DhSectionPos((byte)1, 0, 0); + DhSectionPos centerNodePos = new DhSectionPos((byte) 1, 0, 0); // create node tree.setValue(centerNodePos, 0); @@ -727,7 +727,7 @@ public class QuadTreeTest // edge root node - DhSectionPos offsetNodePos = new DhSectionPos((byte)1, -17, -16); + DhSectionPos offsetNodePos = new DhSectionPos((byte) 1, -17, -16); // create node tree.setValue(offsetNodePos, 0); @@ -751,7 +751,7 @@ public class QuadTreeTest public void toStringTest() { AbstractTestTreeParams treeParams = new MediumTestTree(); - QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte)6); + QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), new DhBlockPos2D(0, 0), (byte) 6); String treeString = tree.toString(); Assert.assertNotNull(treeString); @@ -772,9 +772,9 @@ public class QuadTreeTest // - testSet(tree, new DhSectionPos((byte)0, 0, 0), 1); + testSet(tree, new DhSectionPos((byte) 0, 0, 0), 1); Assert.assertEquals(1, tree.count()); - tree.setCenterBlockPos(new DhBlockPos2D(treeWidth + (treeWidth/2), 0)); + tree.setCenterBlockPos(new DhBlockPos2D(treeWidth + (treeWidth / 2), 0)); Assert.assertEquals(0, tree.count()); } @@ -783,21 +783,21 @@ public class QuadTreeTest //@Test public void autoDeleteNullQuadNodeChildTest() { - QuadNode rootNode = new QuadNode<>(new DhSectionPos((byte)10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(new DhSectionPos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(new DhSectionPos((byte)10, 0, 0), 0); + rootNode.setValue(new DhSectionPos((byte) 10, 0, 0), 0); - DhSectionPos midNodePos = new DhSectionPos((byte)9, 0, 0); + DhSectionPos midNodePos = new DhSectionPos((byte) 9, 0, 0); //rootNode.setValue(midNodePos, null); // holds detail 8 - rootNode.setValue(new DhSectionPos((byte)9, 1, 0), 1); - rootNode.setValue(new DhSectionPos((byte)9, 0, 1), 1); - rootNode.setValue(new DhSectionPos((byte)9, 1, 1), 1); + rootNode.setValue(new DhSectionPos((byte) 9, 1, 0), 1); + rootNode.setValue(new DhSectionPos((byte) 9, 0, 1), 1); + rootNode.setValue(new DhSectionPos((byte) 9, 1, 1), 1); - rootNode.setValue(new DhSectionPos((byte)8, 0, 0), 2); - rootNode.setValue(new DhSectionPos((byte)8, 1, 0), 2); - rootNode.setValue(new DhSectionPos((byte)8, 0, 1), 2); - rootNode.setValue(new DhSectionPos((byte)8, 1, 1), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 0, 0), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 1, 0), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 0, 1), 2); + rootNode.setValue(new DhSectionPos((byte) 8, 1, 1), 2); @@ -810,12 +810,12 @@ public class QuadTreeTest // test removing nodes // // remove two leaf nodes from the root - DhSectionPos leafPos = new DhSectionPos((byte)9, 1, 1); + DhSectionPos leafPos = new DhSectionPos((byte) 9, 1, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(3, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); - leafPos = new DhSectionPos((byte)9, 0, 1); + leafPos = new DhSectionPos((byte) 9, 0, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(2, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); @@ -827,13 +827,13 @@ public class QuadTreeTest Assert.assertEquals(4, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove all but one, mid-node should still be present - rootNode.setValue(new DhSectionPos((byte)8, 0, 0), null); - rootNode.setValue(new DhSectionPos((byte)8, 0, 1), null); - rootNode.setValue(new DhSectionPos((byte)8, 1, 0), null); + rootNode.setValue(new DhSectionPos((byte) 8, 0, 0), null); + rootNode.setValue(new DhSectionPos((byte) 8, 0, 1), null); + rootNode.setValue(new DhSectionPos((byte) 8, 1, 0), null); Assert.assertEquals(1, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove last mid-node child, mid-node should now be removed - rootNode.setValue(new DhSectionPos((byte)8, 1, 1), null); + rootNode.setValue(new DhSectionPos((byte) 8, 1, 1), null); Assert.assertNull("Mid node not deleted.", rootNode.getNode(midNodePos)); Assert.assertEquals(3, rootNode.getNonNullChildCount()); @@ -860,7 +860,7 @@ public class QuadTreeTest if (expectedExceptionClass == null || e.getClass() != expectedExceptionClass) { e.printStackTrace(); - Assert.fail("set failed "+pos+" with exception "+e.getClass()+", expected exception: "+expectedExceptionClass+". error: "+e.getMessage()); + Assert.fail("set failed " + pos + " with exception " + e.getClass() + ", expected exception: " + expectedExceptionClass + ". error: " + e.getMessage()); } } @@ -875,14 +875,14 @@ public class QuadTreeTest try { Integer getResult = tree.getValue(pos); - Assert.assertEquals("get failed "+pos, getValue, getResult); + Assert.assertEquals("get failed " + pos, getValue, getResult); } catch (Exception e) { if (expectedExceptionClass == null || e.getClass() != expectedExceptionClass) { e.printStackTrace(); - Assert.fail("get failed "+pos+" with exception "+e.getClass()+", expected exception: "+expectedExceptionClass+". error: "+e.getMessage()); + Assert.fail("get failed " + pos + " with exception " + e.getClass() + ", expected exception: " + expectedExceptionClass + ". error: " + e.getMessage()); } } } @@ -901,23 +901,27 @@ public class QuadTreeTest public int getWidthInRootNodes() { return MathUtil.log2(this.getWidthInBlocks()) + 2; } public byte getMaxDetailLevel() { return (byte) MathUtil.log2(this.getWidthInBlocks()); } /** @return the block pos so that the tree's negative corner lines up with (0,0) */ - public DhBlockPos2D getPositiveEdgeCenterPos() { return new DhBlockPos2D(BitShiftUtil.powerOfTwo(this.getMaxDetailLevel())/2, BitShiftUtil.powerOfTwo(this.getMaxDetailLevel())/2); } + public DhBlockPos2D getPositiveEdgeCenterPos() { return new DhBlockPos2D(BitShiftUtil.powerOfTwo(this.getMaxDetailLevel()) / 2, BitShiftUtil.powerOfTwo(this.getMaxDetailLevel()) / 2); } + } private static class LargeTestTree extends AbstractTestTreeParams { public int getWidthInBlocks() { return 8192; } + } private static class MediumTestTree extends AbstractTestTreeParams { public int getWidthInBlocks() { return 1024; } + } private static class TinyTestTree extends AbstractTestTreeParams { // top detail level = 6 public int getWidthInBlocks() { return 32; } + } diff --git a/core/src/test/java/tests/RaycastingTest.java b/core/src/test/java/tests/RaycastingTest.java index fd50bf7dc..bad6a4f06 100644 --- a/core/src/test/java/tests/RaycastingTest.java +++ b/core/src/test/java/tests/RaycastingTest.java @@ -46,21 +46,21 @@ public class RaycastingTest // ray origin left of square double rayX = 0; - testRay(false, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 3, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 3, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin right of square rayX = 2.5; - testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray points left - direction <-1,0> @@ -69,21 +69,21 @@ public class RaycastingTest // ray origin left of square rayX = 0; - testRay(false, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 3, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 3, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin right of square rayX = 2.5; - testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); } @@ -105,28 +105,28 @@ public class RaycastingTest double rayY = 0; // ray origin below square - testRay(false, 0, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 0.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 0, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 0.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 2.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 3, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 2.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 3, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin in square - testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin above square rayY = 2.5; - testRay(false, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); @@ -138,28 +138,28 @@ public class RaycastingTest rayY = 0; // ray origin below square - testRay(false, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin in square - testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin above square rayY = 2.5; - testRay(false, 0, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 0.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 0, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 0.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 2.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 3, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 2.5, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 3, rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); } @@ -177,15 +177,15 @@ public class RaycastingTest // direction <0,0> double xDir = 0; double yDir = 0; - testRay(false, 0, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 0.5, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 0, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 0.5, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 2.5, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, 3, 3, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 2.5, 2.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, 3, 3, xDir, yDir, squareMinX, squareMinY, squareWidth); } @@ -205,30 +205,30 @@ public class RaycastingTest // ray origin bottom left of square double rayX = 0; - testRay(false, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin in square - testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, 1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, 2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin right of square rayX = 2.5; - double rayY = (yDir/xDir) * rayX; // y = mx + b // where b is the constants defined below - testRay(false, rayX, -0.5 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 0 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 0.5 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, 1 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + double rayY = (yDir / xDir) * rayX; // y = mx + b // where b is the constants defined below + testRay(false, rayX, -0.5 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 0 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 0.5 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1 + rayY, xDir, yDir, squareMinX, squareMinY, squareWidth); @@ -242,21 +242,21 @@ public class RaycastingTest // ray origin bottom left of square rayX = 0; - testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin in square - testRay(true, 1, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 1.5, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, 2, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 1.5, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, 2, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); @@ -271,21 +271,21 @@ public class RaycastingTest // ray origin bottom left of square rayX = 0; - testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, 1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, 0, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, -0.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, rayX, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(false, rayX, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(false, rayX, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); // ray origin in square - testRay(true, -1, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, -1.5, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); - testRay(true, -2, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, -1, -1, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, -1.5, -1.5, xDir, yDir, squareMinX, squareMinY, squareWidth); + testRay(true, -2, -2, xDir, yDir, squareMinX, squareMinY, squareWidth); } @@ -299,7 +299,7 @@ public class RaycastingTest private static String failMessage(double rayX, double rayY, double xDir, double yDir, double squareMinX, double squareMinY, double squareWidth) { - return "ray: [" + rayX + ", " + rayY + "] <" + xDir + ", " + yDir + "> square: [" + squareMinX + ", " + squareMinY + "] - [" + (squareMinX+squareWidth) + ", " + (squareMinY+squareWidth) + "]"; + return "ray: [" + rayX + ", " + rayY + "] <" + xDir + ", " + yDir + "> square: [" + squareMinX + ", " + squareMinY + "] - [" + (squareMinX + squareWidth) + ", " + (squareMinY + squareWidth) + "]"; } } diff --git a/core/src/test/java/tests/SquareIntersectTest.java b/core/src/test/java/tests/SquareIntersectTest.java index a3965111f..4502ae7b8 100644 --- a/core/src/test/java/tests/SquareIntersectTest.java +++ b/core/src/test/java/tests/SquareIntersectTest.java @@ -75,24 +75,24 @@ public class SquareIntersectTest @Test public void TestNonOverlappingSquares() { - DhLodPos rect1Min = new DhLodPos((byte)0, 1, 1); + DhLodPos rect1Min = new DhLodPos((byte) 0, 1, 1); int rect1Width = 2; - DhLodPos rect2Min = new DhLodPos((byte)0, 4, 4); + DhLodPos rect2Min = new DhLodPos((byte) 0, 4, 4); int rect2Width = 2; boolean result = DoSquaresOverlap(rect1Min, rect1Width, rect2Min, rect2Width); Assert.assertFalse(result); } - + // The third test case checks that two rectangles with different sizes and overlapping are detected as overlapping. @Test public void TestSquaresWithDifferentSizes() { - DhLodPos rect1Min = new DhLodPos((byte)0, 1, 1); + DhLodPos rect1Min = new DhLodPos((byte) 0, 1, 1); int rect1Width = 4; - DhLodPos rect2Min = new DhLodPos((byte)0, 3, 3); + DhLodPos rect2Min = new DhLodPos((byte) 0, 3, 3); int rect2Width = 3; boolean result = DoSquaresOverlap(rect1Min, rect1Width, rect2Min, rect2Width); @@ -103,10 +103,10 @@ public class SquareIntersectTest @Test public void TestOneRectangleContainsTheOther() { - DhLodPos rect1Min = new DhLodPos((byte)0, 1, 1); + DhLodPos rect1Min = new DhLodPos((byte) 0, 1, 1); int rect1Width = 9; - DhLodPos rect2Min = new DhLodPos((byte)0, 3, 3); + DhLodPos rect2Min = new DhLodPos((byte) 0, 3, 3); int rect2Width = 3; boolean result = DoSquaresOverlap(rect1Min, rect1Width, rect2Min, rect2Width); @@ -117,10 +117,10 @@ public class SquareIntersectTest @Test public void TestOneRectangleContainsTheOtherInverted() { - DhLodPos rect1Min = new DhLodPos((byte)0, 3, 3); + DhLodPos rect1Min = new DhLodPos((byte) 0, 3, 3); int rect1Width = 3; - DhLodPos rect2Min = new DhLodPos((byte)0, 1, 1); + DhLodPos rect2Min = new DhLodPos((byte) 0, 1, 1); int rect2Width = 9; boolean result = DoSquaresOverlap(rect1Min, rect1Width, rect2Min, rect2Width);