Fix FullDataPointIdMap (de)serialization duplicate Entries
Potentially fix serializing Biomes/Blocks after a level has been shut down. Also increase DATA_FORMAT_VERSION 2 -> 3
This commit is contained in:
+75
-34
@@ -33,8 +33,6 @@ import net.minecraft.resources.RegistryOps;
|
||||
#endif
|
||||
|
||||
#if POST_MC_1_19_2
|
||||
import net.minecraft.data.worldgen.biome.EndBiomes;
|
||||
import net.minecraft.data.worldgen.biome.NetherBiomes;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -54,12 +52,17 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
#if !PRE_MC_1_18_2
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
#endif
|
||||
|
||||
|
||||
/** This class wraps the minecraft BlockPos.Mutable (and BlockPos) class */
|
||||
public class BiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
|
||||
#if PRE_MC_1_18_2
|
||||
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
|
||||
public final Biome biome;
|
||||
@@ -67,7 +70,19 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
|
||||
public final Holder<Biome> biome;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Cached so it can be quickly used as a semi-stable hashing method. <br>
|
||||
* This may also fix the issue where we can serialize and save after a level has been shut down.
|
||||
*/
|
||||
private String serializationResult = null;
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
static public IBiomeWrapper getBiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif biome)
|
||||
{
|
||||
return biomeWrapperMap.computeIfAbsent(biome, BiomeWrapper::new);
|
||||
@@ -77,61 +92,80 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
#if PRE_MC_1_18_2
|
||||
return biome.toString();
|
||||
#else
|
||||
return biome.unwrapKey().orElse(Biomes.THE_VOID).registry().toString();
|
||||
return this.biome.unwrapKey().orElse(Biomes.THE_VOID).registry().toString();
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BiomeWrapper that = (BiomeWrapper) o;
|
||||
return Objects.equals(biome, that.biome);
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj == null || this.getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(biome);
|
||||
}
|
||||
public int hashCode() { return Objects.hash(this.serialize()); }
|
||||
|
||||
@Override
|
||||
public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
{
|
||||
|
||||
net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess();
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
#if MC_1_16_5 || MC_1_17_1
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
|
||||
#elif MC_1_18_2 || MC_1_19_2
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value());
|
||||
#else
|
||||
resourceLocation = registryAccess.registryOrThrow(Registries.BIOME).getKey(this.biome.value());
|
||||
#endif
|
||||
|
||||
if (resourceLocation == null)
|
||||
if (this.serializationResult == null)
|
||||
{
|
||||
// shouldn't normally happen, but just in case
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
String resourceLocationString = resourceLocation.getNamespace()+":"+resourceLocation.getPath();
|
||||
return resourceLocationString;
|
||||
net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess();
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
#if MC_1_16_5 || MC_1_17_1
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
|
||||
#elif MC_1_18_2 || MC_1_19_2
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value());
|
||||
#else
|
||||
resourceLocation = registryAccess.registryOrThrow(Registries.BIOME).getKey(this.biome.value());
|
||||
#endif
|
||||
|
||||
if (resourceLocation == null)
|
||||
{
|
||||
LOGGER.warn("unable to serialize: "+this.biome.value());
|
||||
// shouldn't normally happen, but just in case
|
||||
this.serializationResult = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.serializationResult = resourceLocation.getNamespace()+":"+resourceLocation.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
return this.serializationResult;
|
||||
}
|
||||
|
||||
public static IBiomeWrapper deserialize(String resourceLocationString) throws IOException // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
{
|
||||
if (resourceLocationString.trim().isEmpty() || resourceLocationString.equals(""))
|
||||
{
|
||||
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)
|
||||
}
|
||||
@@ -157,6 +191,10 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
Holder<Biome> 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);
|
||||
}
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#endif
|
||||
|
||||
@@ -172,4 +210,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
@Override
|
||||
public Object getWrappedMcObject() { return this.biome; }
|
||||
|
||||
@Override
|
||||
public String toString() { return this.serialize(); }
|
||||
|
||||
}
|
||||
|
||||
+40
-21
@@ -6,6 +6,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -39,10 +40,13 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
public static final BlockStateWrapper AIR = new BlockStateWrapper(null);
|
||||
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> cache = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public static ConcurrentHashMap<BlockState, BlockStateWrapper> cache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cached so it can be quickly used as a semi-stable hashing method. <br>
|
||||
* This may also fix the issue where we can serialize and save after a level has been shut down.
|
||||
*/
|
||||
private String serializationResult = null;
|
||||
|
||||
|
||||
//==============//
|
||||
@@ -95,25 +99,36 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
@Override
|
||||
public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
{
|
||||
if (this.blockState == null)
|
||||
// cache the serialization result so it can be quickly used as a semi-stable hashing method
|
||||
if (this.serializationResult == null)
|
||||
{
|
||||
return "AIR";
|
||||
if (this.blockState == null)
|
||||
{
|
||||
return "AIR";
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
#if MC_1_16_5 || MC_1_17_1
|
||||
resourceLocation = Registry.BLOCK.getKey(this.blockState.getBlock());
|
||||
#elif MC_1_18_2 || MC_1_19_2
|
||||
net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess();
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).getKey(this.blockState.getBlock());
|
||||
#else
|
||||
net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess();
|
||||
resourceLocation = registryAccess.registryOrThrow(Registries.BLOCK).getKey(this.blockState.getBlock());
|
||||
#endif
|
||||
|
||||
if (resourceLocation == null)
|
||||
{
|
||||
LOGGER.warn("unable to serialize: "+this.blockState);
|
||||
}
|
||||
|
||||
this.serializationResult = resourceLocation.getNamespace() + RESOURCE_LOCATION_SEPARATOR + resourceLocation.getPath()
|
||||
+ STATE_STRING_SEPARATOR + serializeBlockStateProperties(this.blockState);
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
#if MC_1_16_5 || MC_1_17_1
|
||||
resourceLocation = Registry.BLOCK.getKey(this.blockState.getBlock());
|
||||
#elif MC_1_18_2 || MC_1_19_2
|
||||
net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess();
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).getKey(this.blockState.getBlock());
|
||||
#else
|
||||
net.minecraft.core.RegistryAccess registryAccess = Minecraft.getInstance().level.registryAccess();
|
||||
resourceLocation = registryAccess.registryOrThrow(Registries.BLOCK).getKey(this.blockState.getBlock());
|
||||
#endif
|
||||
|
||||
String resourceStateString = resourceLocation.getNamespace() + RESOURCE_LOCATION_SEPARATOR + resourceLocation.getPath()
|
||||
+ STATE_STRING_SEPARATOR + serializeBlockStateProperties(this.blockState);
|
||||
return resourceStateString;
|
||||
return this.serializationResult;
|
||||
}
|
||||
|
||||
public static BlockStateWrapper deserialize(String resourceStateString) throws IOException // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
@@ -175,7 +190,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
// use the default if no state was found
|
||||
if (foundState == null)
|
||||
{
|
||||
LOGGER.debug("Unable to find BlockState for Block ["+resourceLocation+"] with properties: ["+blockStatePropertiesString+"].");
|
||||
LOGGER.warn("Unable to find BlockState for Block ["+resourceLocation+"] with properties: ["+blockStatePropertiesString+"].");
|
||||
foundState = block.defaultBlockState();
|
||||
}
|
||||
return new BlockStateWrapper(foundState);
|
||||
@@ -231,11 +246,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
}
|
||||
|
||||
BlockStateWrapper that = (BlockStateWrapper) obj;
|
||||
return Objects.equals(this.blockState, that.blockState);
|
||||
// the serialized value is used so we can test the contents instead of the references
|
||||
return Objects.equals(this.serialize(), that.serialize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() { return Objects.hash(this.blockState); }
|
||||
public int hashCode() { return Objects.hash(this.serialize()); }
|
||||
|
||||
|
||||
@Override
|
||||
@@ -270,4 +286,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return this.serialize(); }
|
||||
|
||||
}
|
||||
|
||||
+1
-1
Submodule coreSubProjects updated: c2f7ca8f38...d3cf47ccd7
Reference in New Issue
Block a user