diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java index dd71daf24..7b885fc5f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java @@ -32,6 +32,7 @@ import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.level.IDhServerLevel; +import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; @@ -83,10 +84,21 @@ public class WrapperFactory implements IWrapperFactory @Override public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); } + @Override + public IBiomeWrapper getPlainsBiomeWrapper(ILevelWrapper levelWrapper) // TODO is there a way we could get this without the levelWrapper? it isn't necessary but would clean up the code a bit + { + try + { + return BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, levelWrapper); + } + catch (IOException e) + { + throw new LodUtil.AssertFailureException("Unable to parse plains resource string ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], error:\n " + e.getMessage()); + } + } @Override public IBlockStateWrapper deserializeBlockStateWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BlockStateWrapper.deserialize(str, levelWrapper); } - @Override public IBlockStateWrapper getAirBlockStateWrapper() { return BlockStateWrapper.AIR; } 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 9b8f889f6..f7282de12 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 @@ -64,6 +64,8 @@ public class BiomeWrapper implements IBiomeWrapper public static final ConcurrentMap, BiomeWrapper> WRAPPER_BY_BIOME = new ConcurrentHashMap<>(); #endif + public static final ConcurrentHashMap WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>(); + public static final String EMPTY_BIOME_STRING = "EMPTY"; public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(null, null); @@ -249,8 +251,12 @@ public class BiomeWrapper implements IBiomeWrapper return this.serialString; } + // TODO would it be worth while to cache these objects in a ConcurrentHashMap? public static IBiomeWrapper deserialize(String resourceLocationString, ILevelWrapper levelWrapper) throws IOException { + // we need the final string for the concurrent hash map later + final String finalResourceStateString = resourceLocationString; + if (resourceLocationString.equals(EMPTY_BIOME_STRING)) { if (!emptyStringWarningLogged) @@ -266,53 +272,78 @@ public class BiomeWrapper implements IBiomeWrapper return EMPTY_WRAPPER; } - - - // parse the resource location - int separatorIndex = resourceLocationString.indexOf(":"); - if (separatorIndex == -1) + if (WRAPPER_BY_RESOURCE_LOCATION.containsKey(finalResourceStateString)) { - throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "]."); + return WRAPPER_BY_RESOURCE_LOCATION.get(finalResourceStateString); } - ResourceLocation resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1)); + + // if no wrapper is found, default to the empty wrapper + BiomeWrapper foundWrapper = EMPTY_WRAPPER; try { - Level level = (Level)levelWrapper.getWrappedMcObject(); - net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); - - boolean success; - #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 - Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); - success = (biome != null); - #elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2 - Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); - success = (unwrappedBiome != null); - Holder biome = new Holder.Direct<>(unwrappedBiome); - #else - Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation); - success = (unwrappedBiome != null); - Holder biome = new Holder.Direct<>(unwrappedBiome); - #endif - - - - if (!success) + // parse the resource location + int separatorIndex = resourceLocationString.indexOf(":"); + if (separatorIndex == -1) { - if (!brokenResourceLocationStrings.contains(resourceLocationString)) - { - brokenResourceLocationStrings.add(resourceLocationString); - LOGGER.warn("Unable to deserialize biome from string: [" + resourceLocationString + "]"); - } - return EMPTY_WRAPPER; + throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "]."); } - return getBiomeWrapper(biome, levelWrapper); + ResourceLocation resourceLocation; + try + { + resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1)); + } + catch (Exception e) + { + throw new IOException("No Resource Location found for the string: [" + resourceLocationString + "] Error: [" + e.getMessage() + "]."); + } + + + try + { + Level level = (Level) levelWrapper.getWrappedMcObject(); + net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); + + boolean success; + #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 + Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); + success = (biome != null); + #elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2 + Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); + success = (unwrappedBiome != null); + Holder biome = new Holder.Direct<>(unwrappedBiome); + #else + Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation); + success = (unwrappedBiome != null); + Holder biome = new Holder.Direct<>(unwrappedBiome); + #endif + + + + if (!success) + { + if (!brokenResourceLocationStrings.contains(resourceLocationString)) + { + brokenResourceLocationStrings.add(resourceLocationString); + LOGGER.warn("Unable to deserialize biome from string: [" + resourceLocationString + "]"); + } + return EMPTY_WRAPPER; + } + + + foundWrapper = (BiomeWrapper) getBiomeWrapper(biome, levelWrapper); + return foundWrapper; + } + catch (Exception e) + { + throw new IOException("Failed to deserialize the string [" + finalResourceStateString + "] into a BiomeWrapper: " + e.getMessage(), e); + } } - catch (Exception e) + finally { - throw new IOException("Failed to deserialize the string [" + resourceLocationString + "] into a BiomeWrapper: " + e.getMessage(), e); + WRAPPER_BY_RESOURCE_LOCATION.putIfAbsent(finalResourceStateString, foundWrapper); } } 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 4b2d1e0c5..4a40c6e1f 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 @@ -65,6 +65,7 @@ public class BlockStateWrapper implements IBlockStateWrapper private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public static final ConcurrentHashMap WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>(); + public static final ConcurrentHashMap WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>(); public static final String AIR_STRING = "AIR"; public static final BlockStateWrapper AIR = new BlockStateWrapper(null, null); @@ -339,103 +340,135 @@ public class BlockStateWrapper implements IBlockStateWrapper /** will only work if a level is currently loaded */ public static IBlockStateWrapper deserialize(String resourceStateString, ILevelWrapper levelWrapper) throws IOException { - if (resourceStateString.equals(AIR_STRING) || resourceStateString.equals("")) // the empty string shouldn't normally happen, but just in case + // we need the final string for the concurrent hash map later + final String finalResourceStateString = resourceStateString; + + if (finalResourceStateString.equals(AIR_STRING) || finalResourceStateString.equals("")) // the empty string shouldn't normally happen, but just in case { return AIR; } - - - // try to parse out the BlockState - String blockStatePropertiesString = null; // will be null if no properties were included - int stateSeparatorIndex = resourceStateString.indexOf(STATE_STRING_SEPARATOR); - if (stateSeparatorIndex != -1) + // attempt to use the existing wrapper + if (WRAPPER_BY_RESOURCE_LOCATION.containsKey(finalResourceStateString)) { - // blockstate properties found - blockStatePropertiesString = resourceStateString.substring(stateSeparatorIndex + STATE_STRING_SEPARATOR.length()); - resourceStateString = resourceStateString.substring(0, stateSeparatorIndex); + return WRAPPER_BY_RESOURCE_LOCATION.get(finalResourceStateString); } - // parse the resource location - int resourceSeparatorIndex = resourceStateString.indexOf(RESOURCE_LOCATION_SEPARATOR); - if (resourceSeparatorIndex == -1) - { - throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "]."); - } - ResourceLocation resourceLocation = new ResourceLocation(resourceStateString.substring(0, resourceSeparatorIndex), resourceStateString.substring(resourceSeparatorIndex + 1)); - - // attempt to get the BlockState from all possible BlockStates + // if no wrapper is found, default to air + BlockStateWrapper foundWrapper = AIR; try { - - #if MC_VER > MC_1_17_1 - // use the given level if possible, otherwise try using the currently loaded one - Level level = (levelWrapper != null ? (Level)levelWrapper.getWrappedMcObject() : null); - level = (level == null ? Minecraft.getInstance().level : level); - #endif - - Block block; - #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 - block = Registry.BLOCK.get(resourceLocation); - #elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2 - net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); - block = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).get(resourceLocation); - #else - net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); - block = registryAccess.registryOrThrow(Registries.BLOCK).get(resourceLocation); - #endif - - - if (block == null) + // try to parse out the BlockState + String blockStatePropertiesString = null; // will be null if no properties were included + int stateSeparatorIndex = resourceStateString.indexOf(STATE_STRING_SEPARATOR); + if (stateSeparatorIndex != -1) { - // shouldn't normally happen, but here to make the compiler happy - if (!BrokenResourceLocations.contains(resourceLocation)) - { - BrokenResourceLocations.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."); - } - return AIR; + // blockstate properties found + blockStatePropertiesString = resourceStateString.substring(stateSeparatorIndex + STATE_STRING_SEPARATOR.length()); + resourceStateString = resourceStateString.substring(0, stateSeparatorIndex); + } + + // parse the resource location + int separatorIndex = resourceStateString.indexOf(RESOURCE_LOCATION_SEPARATOR); + if (separatorIndex == -1) + { + throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "]."); + } + + ResourceLocation resourceLocation; + try + { + resourceLocation = new ResourceLocation(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1)); + } + catch (Exception e) + { + throw new IOException("No Resource Location found for the string: [" + resourceStateString + "] Error: [" + e.getMessage() + "]."); } - // attempt to find the blockstate from all possibilities - BlockState foundState = null; - if (blockStatePropertiesString != null) - { - List possibleStateList = block.getStateDefinition().getPossibleStates(); - for (BlockState possibleState : possibleStateList) - { - String possibleStatePropertiesString = serializeBlockStateProperties(possibleState); - if (possibleStatePropertiesString.equals(blockStatePropertiesString)) - { - foundState = possibleState; - break; - } - } - } - // use the default if no state was found or given - if (foundState == null) + // attempt to get the BlockState from all possible BlockStates + try { - if (blockStatePropertiesString != null) + + #if MC_VER > MC_1_17_1 + // use the given level if possible, otherwise try using the currently loaded one + Level level = (levelWrapper != null ? (Level) levelWrapper.getWrappedMcObject() : null); + level = (level == null ? Minecraft.getInstance().level : level); + #endif + + Block block; + #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 + block = Registry.BLOCK.get(resourceLocation); + #elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2 + net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); + block = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).get(resourceLocation); + #else + net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); + block = registryAccess.registryOrThrow(Registries.BLOCK).get(resourceLocation); + #endif + + + if (block == null) { - // we should have found a blockstate, but didn't + // shouldn't normally happen, but here to make the compiler happy if (!BrokenResourceLocations.contains(resourceLocation)) { BrokenResourceLocations.add(resourceLocation); - LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state."); + LOGGER.warn("Unable to find BlockState with the resourceLocation [" + resourceLocation + "] and properties: [" + blockStatePropertiesString + "]. Air will be used instead, some data may be lost."); + } + + return AIR; + } + + + // attempt to find the blockstate from all possibilities + BlockState foundState = null; + if (blockStatePropertiesString != null) + { + List possibleStateList = block.getStateDefinition().getPossibleStates(); + for (BlockState possibleState : possibleStateList) + { + String possibleStatePropertiesString = serializeBlockStateProperties(possibleState); + if (possibleStatePropertiesString.equals(blockStatePropertiesString)) + { + foundState = possibleState; + break; + } } } - foundState = block.defaultBlockState(); + // use the default if no state was found or given + if (foundState == null) + { + if (blockStatePropertiesString != null) + { + // we should have found a blockstate, but didn't + if (!BrokenResourceLocations.contains(resourceLocation)) + { + BrokenResourceLocations.add(resourceLocation); + LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state."); + } + } + + foundState = block.defaultBlockState(); + } + + foundWrapper = new BlockStateWrapper(foundState, levelWrapper); + return foundWrapper; + } + catch (Exception e) + { + throw new IOException("Failed to deserialize the string [" + finalResourceStateString + "] into a BlockStateWrapper: " + e.getMessage(), e); } - return new BlockStateWrapper(foundState, levelWrapper); } - catch (Exception e) + finally { - throw new IOException("Failed to deserialize the string [" + resourceStateString + "] into a BlockStateWrapper: " + e.getMessage(), e); + // put if absent in case two threads deserialize at the same time + // unfortunately we can't put everything in a computeIfAbsent() since we also throw exceptions + WRAPPER_BY_RESOURCE_LOCATION.putIfAbsent(finalResourceStateString, foundWrapper); } } diff --git a/coreSubProjects b/coreSubProjects index 7e45a98e8..c67712d97 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 7e45a98e8fb43b670d95ec01dff817f5cf128531 +Subproject commit c67712d9733defa6e50ff073b39504484a9b7d3b diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java index bf77cd8f6..6f96d189b 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricMain.java @@ -77,7 +77,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti // If sodium is installed Indium is also necessary in order to use the Fabric rendering API if (!modChecker.isModLoaded("indium")) { - String indiumMissingMessage = ModInfo.READABLE_NAME + " now relies on Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium"; + String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium"; LOGGER.fatal(indiumMissingMessage); if (!GraphicsEnvironment.isHeadless()) diff --git a/versionProperties/1.16.5.properties b/versionProperties/1.16.5.properties index 9740ae07d..b43755a1a 100644 --- a/versionProperties/1.16.5.properties +++ b/versionProperties/1.16.5.properties @@ -22,7 +22,7 @@ fabric_api_version=0.42.0+1.16 canvas_version= fabric_incompatibility_list={ "iris": "*" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.17.1.properties b/versionProperties/1.17.1.properties index bd823e4ae..9b059c06d 100644 --- a/versionProperties/1.17.1.properties +++ b/versionProperties/1.17.1.properties @@ -22,7 +22,7 @@ fabric_api_version=0.46.1+1.17 canvas_version= fabric_incompatibility_list={ "iris": "*" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.18.2.properties b/versionProperties/1.18.2.properties index a14c7cacb..e4b01723e 100644 --- a/versionProperties/1.18.2.properties +++ b/versionProperties/1.18.2.properties @@ -23,7 +23,7 @@ fabric_api_version=0.76.0+1.18.2 canvas_version=mc118:1.0.2616 fabric_incompatibility_list={ "iris": "*" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.19.2.properties b/versionProperties/1.19.2.properties index 0e0576876..cc8479a27 100644 --- a/versionProperties/1.19.2.properties +++ b/versionProperties/1.19.2.properties @@ -22,7 +22,7 @@ fabric_api_version=0.76.1+1.19.2 canvas_version=mc119-1.0.2480 fabric_incompatibility_list={ "iris": "*" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.19.4.properties b/versionProperties/1.19.4.properties index c5c107ea3..7ba9a7565 100644 --- a/versionProperties/1.19.4.properties +++ b/versionProperties/1.19.4.properties @@ -21,7 +21,7 @@ fabric_api_version=0.87.1+1.19.4 canvas_version= fabric_incompatibility_list={ "iris": "*" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.20.1.properties b/versionProperties/1.20.1.properties index 3c73bd063..69cede1c0 100644 --- a/versionProperties/1.20.1.properties +++ b/versionProperties/1.20.1.properties @@ -21,7 +21,7 @@ fabric_api_version=0.90.4+1.20.1 canvas_version= fabric_incompatibility_list={ "iris": "<=1.6.20" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.20.2.properties b/versionProperties/1.20.2.properties index f443bc41c..62f394c8a 100644 --- a/versionProperties/1.20.2.properties +++ b/versionProperties/1.20.2.properties @@ -21,7 +21,7 @@ fabric_api_version=0.90.4+1.20.2 canvas_version= fabric_incompatibility_list={ "iris": "<=1.6.20" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.20.4.properties b/versionProperties/1.20.4.properties index 843ea79af..380a3fd7c 100644 --- a/versionProperties/1.20.4.properties +++ b/versionProperties/1.20.4.properties @@ -22,7 +22,7 @@ fabric_api_version=0.91.2+1.20.4 canvas_version= fabric_incompatibility_list={ "iris": "<=1.6.20" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run diff --git a/versionProperties/1.20.6.properties b/versionProperties/1.20.6.properties index c2fc9045a..f7d546e14 100644 --- a/versionProperties/1.20.6.properties +++ b/versionProperties/1.20.6.properties @@ -22,7 +22,7 @@ fabric_api_version=0.97.8+1.20.6 canvas_version= fabric_incompatibility_list={ "iris": "<=1.6.20" } - fabric_recommend_list={ "indium": "*" } + fabric_recommend_list={} # Fabric mod run # 0 = Don't enable and don't run