From c578ae0fa458a1784ba4dd95848f15e5ae80aff3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 7 Feb 2024 07:06:39 -0600 Subject: [PATCH 01/15] Add Lod Shading to the api config --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 556550fea..b255e0ac6 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 556550fea802c5e7ad526204a40916ba9b698ad0 +Subproject commit b255e0ac686a10a1486513eaf491e489d31682cf From aa084c885d61abbff1009604dc18142254bf5070 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 7 Feb 2024 07:34:49 -0600 Subject: [PATCH 02/15] Attempt to reduce queuing duplicate world gen tasks --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index b255e0ac6..2651e3d43 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit b255e0ac686a10a1486513eaf491e489d31682cf +Subproject commit 2651e3d43590637914e068e4a53a62b6407ed84d From 0ccdcfbb6d3e8918cb15be7010be6366cc8c7676 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 7 Feb 2024 18:19:41 -0600 Subject: [PATCH 03/15] Fix 1.20.4 compling --- .../neoforge/wrappers/modAccessor/ModChecker.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/wrappers/modAccessor/ModChecker.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/wrappers/modAccessor/ModChecker.java index 775869e49..6494d6edf 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/wrappers/modAccessor/ModChecker.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/wrappers/modAccessor/ModChecker.java @@ -22,14 +22,22 @@ package com.seibel.distanthorizons.neoforge.wrappers.modAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; import net.neoforged.fml.ModList; +import java.io.File; + public class ModChecker implements IModChecker { public static final ModChecker INSTANCE = new ModChecker(); @Override - public boolean isModLoaded(String modid) + public boolean isModLoaded(String modid) { - return ModList.get().isLoaded(modid); + return ModList.get().isLoaded(modid); + } + + @Override + public File modLocation(String modid) + { + return ModList.get().getModFileById(modid).getFile().getFilePath().toFile(); } } From 6a6a87a3f772fd55b9b6573784672db2de889cfc Mon Sep 17 00:00:00 2001 From: coolGi Date: Thu, 8 Feb 2024 17:47:13 +1030 Subject: [PATCH 04/15] Fixed joml being embedded on versions where mc already embeds it --- build.gradle | 8 ++++++-- versionProperties/1.16.5.properties | 1 + versionProperties/1.17.1.properties | 1 + versionProperties/1.18.2.properties | 1 + versionProperties/1.19.2.properties | 1 + versionProperties/1.19.4.properties | 1 + 6 files changed, 11 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d995fbf11..f0261f6b9 100644 --- a/build.gradle +++ b/build.gradle @@ -200,7 +200,10 @@ subprojects { p -> implementation("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}") // JOML - forgeShadowMe("org.joml:joml:${rootProject.joml_version}") + if (project.hasProperty("embed_joml") && embed_joml == "true") + forgeShadowMe("org.joml:joml:${rootProject.joml_version}") + else + implementation("org.joml:joml:${rootProject.joml_version}") // JUnit tests implementation("org.junit.jupiter:junit-jupiter:5.8.2") @@ -300,7 +303,8 @@ subprojects { p -> // relocate "org.sqlite", "${librariesLocation}.sqlite" // JOML - relocate "org.joml", "${librariesLocation}.joml" + if (project.hasProperty("embed_joml") && embed_joml == "true") + relocate "org.joml", "${librariesLocation}.joml" // NightConfig (includes Toml & Json) relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig" diff --git a/versionProperties/1.16.5.properties b/versionProperties/1.16.5.properties index dc8d54645..dae7f1dc0 100644 --- a/versionProperties/1.16.5.properties +++ b/versionProperties/1.16.5.properties @@ -5,6 +5,7 @@ parchment_version=1.16.5:2022.03.06 compatible_minecraft_versions=["1.16.4", "1.16.5"] accessWidenerVersion=1_16 builds_for=fabric,forge +embed_joml=true # Fabric loader fabric_loader_version=0.14.24 diff --git a/versionProperties/1.17.1.properties b/versionProperties/1.17.1.properties index 44be229a8..4b5b8dfc9 100644 --- a/versionProperties/1.17.1.properties +++ b/versionProperties/1.17.1.properties @@ -5,6 +5,7 @@ parchment_version=1.17.1:2021.12.12 compatible_minecraft_versions=["1.17", "1.17.1"] accessWidenerVersion=1_17 builds_for=fabric,forge +embed_joml=true # Fabric loader fabric_loader_version=0.14.24 diff --git a/versionProperties/1.18.2.properties b/versionProperties/1.18.2.properties index e987c439f..e168e4f1b 100644 --- a/versionProperties/1.18.2.properties +++ b/versionProperties/1.18.2.properties @@ -5,6 +5,7 @@ parchment_version=1.18.2:2022.11.06 compatible_minecraft_versions=["1.18.2"] accessWidenerVersion=1_18 builds_for=fabric,forge +embed_joml=true # Fabric loader fabric_loader_version=0.14.24 diff --git a/versionProperties/1.19.2.properties b/versionProperties/1.19.2.properties index c4fe3195f..34e38b150 100644 --- a/versionProperties/1.19.2.properties +++ b/versionProperties/1.19.2.properties @@ -5,6 +5,7 @@ parchment_version=1.19.2:2022.11.27 compatible_minecraft_versions=["1.19.2"] accessWidenerVersion=1_19_2 builds_for=fabric,forge +embed_joml=true # Fabric loader fabric_loader_version=0.14.24 diff --git a/versionProperties/1.19.4.properties b/versionProperties/1.19.4.properties index c3a91dfda..0d0691a44 100644 --- a/versionProperties/1.19.4.properties +++ b/versionProperties/1.19.4.properties @@ -5,6 +5,7 @@ parchment_version=1.19.4:2023.06.26 compatible_minecraft_versions=["1.19.4"] accessWidenerVersion=1_19_4 builds_for=fabric,forge +embed_joml=true # Fabric loader fabric_loader_version=0.14.24 From 3bba08723ff1f00e10faf1f22457b2881e12bc2f Mon Sep 17 00:00:00 2001 From: coolGi Date: Thu, 8 Feb 2024 10:28:33 +0000 Subject: [PATCH 05/15] joml is included in vanilla 1.19.4 --- versionProperties/1.19.4.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/versionProperties/1.19.4.properties b/versionProperties/1.19.4.properties index 0d0691a44..c3a91dfda 100644 --- a/versionProperties/1.19.4.properties +++ b/versionProperties/1.19.4.properties @@ -5,7 +5,6 @@ parchment_version=1.19.4:2023.06.26 compatible_minecraft_versions=["1.19.4"] accessWidenerVersion=1_19_4 builds_for=fabric,forge -embed_joml=true # Fabric loader fabric_loader_version=0.14.24 From 0ebe8db2688f7f24b46944839463203808d5e4b5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 21:38:44 -0600 Subject: [PATCH 06/15] Add IDhApiShadowCullingFrustum and a config for shadow culling --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 2651e3d43..b4269afc9 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 2651e3d43590637914e068e4a53a62b6407ed84d +Subproject commit b4269afc9fba5cfeb1a619ae4a9de8c90f019fde From ec8d1b5538fe7fe047992f77be9da4c41516a3c6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 21:38:55 -0600 Subject: [PATCH 07/15] Fix Lava Iris block material ID --- .../common/wrappers/block/BlockStateWrapper.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java index 3e3fbd24e..e44a30e0a 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java @@ -489,6 +489,10 @@ public class BlockStateWrapper implements IBlockStateWrapper { return IrisBlockMaterial.LEAVES; } + else if (this.blockState.is(Blocks.LAVA)) + { + return IrisBlockMaterial.LAVA; + } else if (this.isLiquid() || this.blockState.is(Blocks.WATER)) { return IrisBlockMaterial.WATER; @@ -524,10 +528,6 @@ public class BlockStateWrapper implements IBlockStateWrapper ) { return IrisBlockMaterial.DIRT; - } - else if (this.blockState.is(Blocks.LAVA)) - { - return IrisBlockMaterial.LAVA; } #if MC_VER >= MC_1_17_1 else if (this.blockState.getSoundType() == SoundType.DEEPSLATE From 8a5bca3136b0753291873d9bb084dbe96af6e772 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 21:58:24 -0600 Subject: [PATCH 08/15] Fix using the wrong near clip plane --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index b4269afc9..97e7f0563 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit b4269afc9fba5cfeb1a619ae4a9de8c90f019fde +Subproject commit 97e7f0563640465c089625990e687fd9de8d6fb4 From 91ac4309df130668f327dc2f689e2e3689b1b2e4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 22:02:19 -0600 Subject: [PATCH 09/15] Fix the API seeing the wrong far clip plane --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 97e7f0563..c71873310 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 97e7f0563640465c089625990e687fd9de8d6fb4 +Subproject commit c718733104e77e3e5284193e891d17dd140909ce From 56167a137e39af5b41ab1b9eabe1e036d63944c9 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 14:56:16 -0600 Subject: [PATCH 10/15] Default to no culling for the shadow pass --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index c71873310..cc134092e 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit c718733104e77e3e5284193e891d17dd140909ce +Subproject commit cc134092ed8d92ed73fefcc92c1d6e1fcffd1c0e From e87823aa29c95dabfd614ef9de2b232b68bbe432 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 16:39:29 -0600 Subject: [PATCH 11/15] Close #615 (lag when rapidly breaking/placing blocks) --- coreSubProjects | 2 +- .../fabric/FabricClientProxy.java | 52 +++++++++++-------- .../forge/ForgeClientProxy.java | 10 ++++ .../neoforge/NeoforgeClientProxy.java | 10 ++++ 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/coreSubProjects b/coreSubProjects index cc134092e..b8f90ddc5 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit cc134092ed8d92ed73fefcc92c1d6e1fcffd1c0e +Subproject commit b8f90ddc551302b5b9202375e1cc4b14e4e49cfc diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java index 931113d95..d9216458d 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java @@ -32,6 +32,8 @@ import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; @@ -123,17 +125,20 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy // if we have access to the server, use the chunk save event instead if (MC.clientConnectedToDedicatedServer()) { - // Since fabric doesn't have a client-side break-block API event, this is the next best thing - ChunkAccess chunk = level.getChunk(blockPos); - if (chunk != null) + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ())) { - LOGGER.trace("attack block at blockPos: " + blockPos); - - IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); - SharedApi.INSTANCE.chunkBlockChangedEvent( - new ChunkWrapper(chunk, level, wrappedLevel), - wrappedLevel - ); + // Since fabric doesn't have a client-side break-block API event, this is the next best thing + ChunkAccess chunk = level.getChunk(blockPos); + if (chunk != null) + { + LOGGER.trace("attack block at blockPos: " + blockPos); + + IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); + SharedApi.INSTANCE.chunkBlockChangedEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + } } } @@ -147,20 +152,23 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy // if we have access to the server, use the chunk save event instead if (MC.clientConnectedToDedicatedServer()) { - // Since fabric doesn't have a client-side place-block API event, this is the next best thing - if (hitResult.getType() == HitResult.Type.BLOCK - && !hitResult.isInside()) + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ())) { - ChunkAccess chunk = level.getChunk(hitResult.getBlockPos()); - if (chunk != null) + // Since fabric doesn't have a client-side place-block API event, this is the next best thing + if (hitResult.getType() == HitResult.Type.BLOCK + && !hitResult.isInside()) { - LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos()); - - IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); - SharedApi.INSTANCE.chunkBlockChangedEvent( - new ChunkWrapper(chunk, level, wrappedLevel), - wrappedLevel - ); + ChunkAccess chunk = level.getChunk(hitResult.getBlockPos()); + if (chunk != null) + { + LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos()); + + IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); + SharedApi.INSTANCE.chunkBlockChangedEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + } } } } diff --git a/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java b/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java index 469f7b134..9b1b03c49 100644 --- a/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java +++ b/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java @@ -173,6 +173,11 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy @SubscribeEvent public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event) { + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ())) + { + return; + } + LOGGER.trace("interact or block place event at blockPos: " + event.getPos()); #if MC_VER < MC_1_19_2 @@ -187,6 +192,11 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy @SubscribeEvent public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event) { + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ())) + { + return; + } + LOGGER.trace("break or block attack at blockPos: " + event.getPos()); #if MC_VER < MC_1_19_2 diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java index d46be455c..69da1d5e1 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java @@ -146,6 +146,11 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy @SubscribeEvent public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event) { + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ())) + { + return; + } + LOGGER.trace("interact or block place event at blockPos: " + event.getPos()); LevelAccessor level = event.getLevel(); @@ -156,6 +161,11 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy @SubscribeEvent public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event) { + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ())) + { + return; + } + LOGGER.trace("break or block attack at blockPos: " + event.getPos()); LevelAccessor level = event.getLevel(); From f4f234a159431431317e3e0edbdfade3969572b4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 18:29:51 -0600 Subject: [PATCH 12/15] Fix NeverCullFrustum casting error --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index b8f90ddc5..7df442878 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit b8f90ddc551302b5b9202375e1cc4b14e4e49cfc +Subproject commit 7df442878dc533a4b85623c9bb5dd416e401b2b9 From 2da444d03cef5dc89abc4ddd5005207396269327 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 20:24:36 -0600 Subject: [PATCH 13/15] Fix BiomeWrapper warning about null level on startup --- .../common/wrappers/block/BiomeWrapper.java | 10 ++++++++-- coreSubProjects | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java index 843817892..9cbdd9816 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java @@ -65,7 +65,7 @@ public class BiomeWrapper implements IBiomeWrapper #endif public static final String EMPTY_STRING = "EMPTY"; - public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(null, null); + public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(); /** keep track of broken biomes so we don't log every time */ private static final HashSet brokenResourceLocationStrings = new HashSet<>(); @@ -115,7 +115,6 @@ public class BiomeWrapper implements IBiomeWrapper return newWrapper; } } - private BiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder #endif biome, ILevelWrapper levelWrapper) { this.biome = biome; @@ -123,6 +122,13 @@ public class BiomeWrapper implements IBiomeWrapper LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]"); } + /** should only be used to create {@link BiomeWrapper#EMPTY_WRAPPER} */ + private BiomeWrapper() + { + this.biome = null; + this.serialString = EMPTY_STRING; + } + //=========// diff --git a/coreSubProjects b/coreSubProjects index 7df442878..5c30d077d 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 7df442878dc533a4b85623c9bb5dd416e401b2b9 +Subproject commit 5c30d077ddf6cf21e5ba2b47c18a2c98d3d15738 From 4e6e727799460c0c560bd8b5f7c4e9e5da4e5ef6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 21:32:08 -0600 Subject: [PATCH 14/15] Fix ocean floors showing at very low detail levels Partially fixes #632 --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index 5c30d077d..d7c96bbba 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 5c30d077ddf6cf21e5ba2b47c18a2c98d3d15738 +Subproject commit d7c96bbba4895009f851c0affe1ab6ed6d8395be From 2e7cc9f4b634a46716f52221b9ccec161c8c40e8 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 13 Feb 2024 07:53:08 -0600 Subject: [PATCH 15/15] Temp fix for near clip plane going too far in some cases --- coreSubProjects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreSubProjects b/coreSubProjects index d7c96bbba..cd20fb1e3 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit d7c96bbba4895009f851c0affe1ab6ed6d8395be +Subproject commit cd20fb1e345f0661af0b9e9b3bb242c04ba8cf18