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 053367f3a..6cce701e2 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 @@ -84,7 +84,7 @@ public class BlockStateWrapper implements IBlockStateWrapper public static HashSet rendererIgnoredCaveBlocks = null; /** keep track of broken blocks so we don't log every time */ - private static final HashSet BrokenResourceLocations = new HashSet<>(); + private static final HashSet BROKEN_RESOURCE_LOCATIONS = new HashSet<>(); @@ -596,9 +596,9 @@ public class BlockStateWrapper implements IBlockStateWrapper if (block == null) { // shouldn't normally happen, but here to make the compiler happy - if (!BrokenResourceLocations.contains(resourceLocation)) + if (!BROKEN_RESOURCE_LOCATIONS.contains(resourceLocation)) { - BrokenResourceLocations.add(resourceLocation); + BROKEN_RESOURCE_LOCATIONS.add(resourceLocation); LOGGER.warn("Unable to find BlockState with the resourceLocation [" + resourceLocation + "] and properties: [" + blockStatePropertiesString + "]. Air will be used instead, some data may be lost."); } @@ -628,9 +628,9 @@ public class BlockStateWrapper implements IBlockStateWrapper if (blockStatePropertiesString != null) { // we should have found a blockstate, but didn't - if (!BrokenResourceLocations.contains(resourceLocation)) + if (!BROKEN_RESOURCE_LOCATIONS.contains(resourceLocation)) { - BrokenResourceLocations.add(resourceLocation); + BROKEN_RESOURCE_LOCATIONS.add(resourceLocation); LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state."); } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index e921ba0a2..4c8e8fb15 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -29,6 +29,7 @@ import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; import it.unimi.dsi.fastutil.shorts.ShortList; @@ -103,6 +104,8 @@ public class ChunkLoader private static boolean lightingSectionErrorLogged = false; + private static final ConcurrentHashMap LOGGED_ERROR_MESSAGE_MAP = new ConcurrentHashMap<>(); + //============// @@ -285,17 +288,18 @@ public class ChunkLoader #endif blockStateContainer = tagSection.contains("block_states", 10) - ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string)) + ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")) + .promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string)) #if MC_VER < MC_1_20_6 - .getOrThrow(false, LOGGER::error) + .getOrThrow(false, (message) -> logWarningOnce(message)) #else - .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)) + .getOrThrow((message) -> logErrorAndReturnException(message)) #endif : new PalettedContainer(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); #if MC_VER < MC_1_18_2 biomeContainer = tagSection.contains("biomes", 10) - ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error) + ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message)) : new PalettedContainer(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); #else @@ -303,11 +307,12 @@ public class ChunkLoader if (tagSection.contains("biomes", 10)) { biomeContainer = - biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string)) + biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")) + .promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string)) #if MC_VER < MC_1_20_6 - .getOrThrow(false, LOGGER::error); + .getOrThrow(false, (message) -> logWarningOnce(message)); #else - .getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null)); + .getOrThrow((message) -> logErrorAndReturnException(message)); #endif } else @@ -387,9 +392,9 @@ public class ChunkLoader Dynamic blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data")); #if MC_VER < MC_1_21_3 - blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null); + blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logWarningOnce(message)).orElse(null); #else - blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null)); + blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logWarningOnce(message)).orElse(null)); #endif } return blendingData; @@ -515,15 +520,61 @@ public class ChunkLoader } } + + + //=========// + // logging // + //=========// + private static void logBlockDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message) { - LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+message+"]. This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); + LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) -> + { + LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " + + "This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); + + return newMessage; + }); } private static void logBiomeDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message) { - LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+message+"]. This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); + LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) -> + { + LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " + + "This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); + + return newMessage; + }); } + private static void logWarningOnce(String message) { logWarningOnce(message, null); } + private static void logWarningOnce(String message, Exception e) + { + LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) -> + { + LOGGER.warn("Parsing error: ["+newMessage+"]. " + + "This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.", + e); + + return newMessage; + }); + } + + private static RuntimeException logErrorAndReturnException(String message) + { + LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) -> + { + LOGGER.warn("Parsing error: ["+newMessage+"]. " + + "This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); + + return newMessage; + }); + + // Currently we want to ignore these errors, if returning null is a problem, we can change this later + return null; //new RuntimeException(message); + } + + //================// diff --git a/coreSubProjects b/coreSubProjects index a3263ba5b..0518da687 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit a3263ba5ba5af962a2e61aeb43067dfbb8c6bea5 +Subproject commit 0518da68721926fbb2928bec172f434326032e5f