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 81f95245b..01bcf52f7 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 @@ -70,7 +70,7 @@ public class WrapperFactory implements IWrapperFactory } @Override - public IBiomeWrapper deserializeBiomeWrapper(String str) throws IOException { return BiomeWrapper.deserialize(str); } + public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); } @Override public IBlockStateWrapper deserializeBlockStateWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BlockStateWrapper.deserialize(str, levelWrapper); } 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 be8e7620c..aee4951ca 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 @@ -24,6 +24,8 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +import net.minecraft.world.level.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -63,20 +65,27 @@ public class BiomeWrapper implements IBiomeWrapper { private static final Logger LOGGER = LogManager.getLogger(); - #if PRE_MC_1_18_2 public static final ConcurrentMap biomeWrapperMap = new ConcurrentHashMap<>(); - public final Biome biome; #else public static final ConcurrentMap, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>(); + #endif + + public static final String EMPTY_STRING = "EMPTY"; + public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(null, null); + + + + // properties // + + #if PRE_MC_1_18_2 + public final Biome biome; + #else public final Holder biome; #endif - /** - * Cached so it can be quickly used as a semi-stable hashing method.
- * This may also fix the issue where we can serialize and save after a level has been shut down. - */ - private String serializationResult = null; + /** technically final, but since it requires a method call to generate it can't be marked as such */ + private String serialString = null; @@ -84,14 +93,21 @@ public class BiomeWrapper implements IBiomeWrapper // constructors // //==============// - static public IBiomeWrapper getBiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder #endif biome) + static public IBiomeWrapper getBiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder #endif biome, ILevelWrapper levelWrapper) { - return biomeWrapperMap.computeIfAbsent(biome, BiomeWrapper::new); + if (biome == null) + { + return EMPTY_WRAPPER; + } + + return biomeWrapperMap.computeIfAbsent(biome, newBiome -> new BiomeWrapper(newBiome, levelWrapper)); } - private BiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder #endif biome) + private BiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder #endif biome, ILevelWrapper levelWrapper) { this.biome = biome; + this.serialString = this.serialize(levelWrapper); + LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]"); } @@ -103,6 +119,11 @@ public class BiomeWrapper implements IBiomeWrapper @Override public String getName() { + if (this == EMPTY_WRAPPER) + { + return EMPTY_STRING; + } + #if PRE_MC_1_18_2 return biome.toString(); #else @@ -124,16 +145,36 @@ public class BiomeWrapper implements IBiomeWrapper BiomeWrapper that = (BiomeWrapper) obj; // the serialized value is used so we can test the contents instead of the references - return Objects.equals(this.serialize(), that.serialize()); + return Objects.equals(this.getSerialString(), that.getSerialString()); } @Override - public int hashCode() { return Objects.hash(this.serialize()); } + public int hashCode() { return Objects.hash(this.getSerialString()); } @Override - public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?) + public String getSerialString() { return this.serialString; } + + @Override + public Object getWrappedMcObject() { return this.biome; } + + @Override + public String toString() { return this.getSerialString(); } + + + + //=======================// + // serialization methods // + //=======================// + + public String serialize(ILevelWrapper levelWrapper) { - if (this.serializationResult == null) + if (levelWrapper == null) + { + return EMPTY_STRING; + } + + + if (this.serialString == null) { net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess(); @@ -157,26 +198,30 @@ public class BiomeWrapper implements IBiomeWrapper LOGGER.warn("unable to serialize: " + biomeName); // shouldn't normally happen, but just in case - this.serializationResult = ""; + this.serialString = ""; } else { - this.serializationResult = resourceLocation.getNamespace() + ":" + resourceLocation.getPath(); + this.serialString = resourceLocation.getNamespace() + ":" + resourceLocation.getPath(); } } - return this.serializationResult; + return this.serialString; } - public static IBiomeWrapper deserialize(String resourceLocationString) throws IOException // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?) + public static IBiomeWrapper deserialize(String resourceLocationString, ILevelWrapper levelWrapper) throws IOException { - if (resourceLocationString.trim().isEmpty() || resourceLocationString.equals("")) + if (resourceLocationString.equals(EMPTY_STRING)) { - LOGGER.warn("null biome string deserialized"); - - // shouldn't normally happen, but just in case - new ResourceLocation("minecraft", "the_void"); // just "void" in MC 1.12 through 1.9 (inclusive) + LOGGER.warn("["+EMPTY_STRING+"] biome string deserialized. This may mean there was a file saving error or a biome saving error."); + return EMPTY_WRAPPER; } + else if (resourceLocationString.trim().isEmpty() || resourceLocationString.equals("")) + { + LOGGER.warn("Null biome string deserialized."); + return EMPTY_WRAPPER; + } + // parse the resource location @@ -190,23 +235,32 @@ public class BiomeWrapper implements IBiomeWrapper try { - net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess(); + Level level = (Level)levelWrapper.getWrappedMcObject(); + net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); + boolean success; #if MC_1_16_5 || MC_1_17_1 Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); + success = (biome != null); #elif MC_1_18_2 || 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); - if (unwrappedBiome == null) - { - LOGGER.warn("null biome string deserialized from string: " + resourceLocationString); - } + success = (unwrappedBiome != null); Holder biome = new Holder.Direct<>(unwrappedBiome); #endif - return getBiomeWrapper(biome); + + + if (!success) + { + LOGGER.warn("Unable to deserialize biome from string: [" + resourceLocationString + "]"); + return EMPTY_WRAPPER; + } + + return getBiomeWrapper(biome, levelWrapper); } catch (Exception e) { @@ -214,11 +268,4 @@ public class BiomeWrapper implements IBiomeWrapper } } - - @Override - public Object getWrappedMcObject() { return this.biome; } - - @Override - public String toString() { return this.serialize(); } - } 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 484842367..4923b9441 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 @@ -43,7 +43,7 @@ public class BlockStateWrapper implements IBlockStateWrapper public static final ConcurrentHashMap WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>(); - public static String AIR_STRING = "AIR"; + public static final String AIR_STRING = "AIR"; public static final BlockStateWrapper AIR = new BlockStateWrapper(null, null); public static final String[] RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS = { AIR_STRING, "minecraft:barrier", "minecraft:structure_void", "minecraft:light" }; @@ -52,6 +52,8 @@ public class BlockStateWrapper implements IBlockStateWrapper + // properties // + public final BlockState blockState; /** technically final, but since it requires a method call to generate it can't be marked as such */ private String serialString; @@ -76,7 +78,7 @@ public class BlockStateWrapper implements IBlockStateWrapper { this.blockState = blockState; this.serialString = this.serialize(levelWrapper); - LOGGER.trace("Created BlockStateWrapper for ["+blockState+"]"); + LOGGER.trace("Created BlockStateWrapper ["+this.serialString+"] for ["+blockState+"]"); } @@ -342,7 +344,7 @@ public class BlockStateWrapper implements IBlockStateWrapper if (blockStatePropertiesString != null) { // we should have found a blockstate, but didn't - LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]."); + LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "]. Using the default block state."); } foundState = block.defaultBlockState(); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java index 0c717923f..f9cb65750 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java @@ -158,16 +158,21 @@ public class ChunkWrapper implements IChunkWrapper { #if PRE_MC_1_17_1 return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome( - relX >> 2, relY >> 2, relZ >> 2)); + relX >> 2, relY >> 2, relZ >> 2), + this.wrappedLevel); #elif PRE_MC_1_18_2 return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome( - QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ))); + QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)), + this.wrappedLevel); #elif PRE_MC_1_18_2 return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome( - QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ))); - #else //Now returns a Holder instead of Biome + QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)), + this.wrappedLevel); + #else + //Now returns a Holder instead of Biome return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome( - QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ))); + QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)), + this.wrappedLevel); #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java index 545e8b3b1..0cd35bbda 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java @@ -169,7 +169,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper } @Override - public IBiomeWrapper getBiome(DhBlockPos pos) { return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos))); } + public IBiomeWrapper getBiome(DhBlockPos pos) { return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos)), this); } @Override public ClientLevel getWrappedMcObject() { return this.level; } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java index b2779cf4f..251db4535 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java @@ -162,7 +162,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper @Override public IBiomeWrapper getBiome(DhBlockPos pos) { - return BiomeWrapper.getBiomeWrapper(level.getBiome(McObjectConverter.Convert(pos))); + return BiomeWrapper.getBiomeWrapper(level.getBiome(McObjectConverter.Convert(pos)), this); } @Override diff --git a/coreSubProjects b/coreSubProjects index e62ddc302..269cbf835 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit e62ddc302b76b981cbe3635826f61510a5e5bbc1 +Subproject commit 269cbf83557c16ac6a63aea6a2e57f0c7a7a63b6