feat: Update rendering block ignores
Barrier blocks, structure void blocks, light blocks, and air blocks now share 2 `HashMap`s that define blocks that should be ignored by the LOD builder.
This commit is contained in:
@@ -22,8 +22,8 @@ package com.seibel.distanthorizons.common.wrappers;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
|
||||
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
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.wrapperInterfaces.IWrapperFactory;
|
||||
@@ -35,6 +35,7 @@ import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This handles creating abstract wrapper objects.
|
||||
@@ -71,6 +72,9 @@ public class WrapperFactory implements IWrapperFactory
|
||||
@Override
|
||||
public IBlockStateWrapper getAirBlockStateWrapper() { return BlockStateWrapper.AIR; }
|
||||
|
||||
@Override
|
||||
public HashMap<String, ? extends IBlockStateWrapper> getRendererIgnoredBlocks() { return BlockStateWrapper.RENDERER_IGNORED_BLOCKS; }
|
||||
|
||||
|
||||
/**
|
||||
* Note: when this is updated for different MC versions, make sure you also update the documentation in
|
||||
|
||||
+95
-38
@@ -3,16 +3,15 @@ package com.seibel.distanthorizons.common.wrappers.block;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
#if MC_1_16_5 || MC_1_17_1
|
||||
@@ -39,8 +38,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
// must be defined before AIR, otherwise a null pointer will be thrown
|
||||
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 final ConcurrentHashMap<BlockState, BlockStateWrapper> cache = new ConcurrentHashMap<>();
|
||||
public static final BlockStateWrapper AIR = fromBlockState(BuiltInRegistries.BLOCK.get(ResourceLocation.tryParse("minecraft:air")).defaultBlockState(), false);
|
||||
public static final String[] RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS = {"minecraft:air", "minecraft:barrier", "minecraft:structure_void"};
|
||||
public static final HashMap<BlockState, String> RENDERER_IGNORED_BLOCKS_INTERNAL = getRendererIgnoredBlocksInternal(RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS);
|
||||
public static final HashMap<String, ? extends IBlockStateWrapper> RENDERER_IGNORED_BLOCKS = getRendererIgnoredBlocks(RENDERER_IGNORED_BLOCKS_INTERNAL);
|
||||
|
||||
/**
|
||||
* Cached so it can be quickly used as a semi-stable hashing method. <br>
|
||||
@@ -53,21 +55,75 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public static BlockStateWrapper fromBlockState(BlockState blockState)
|
||||
public static BlockStateWrapper fromBlockState(BlockState blockState)
|
||||
{
|
||||
if (blockState == null || blockState.isAir())
|
||||
{
|
||||
return fromBlockState(blockState, true);
|
||||
}
|
||||
|
||||
private static BlockStateWrapper fromBlockState(BlockState blockState, boolean nullCheck)
|
||||
{
|
||||
if (Objects.requireNonNull(blockState).isAir() && AIR != null)
|
||||
return AIR;
|
||||
}
|
||||
|
||||
return cache.computeIfAbsent(blockState, BlockStateWrapper::new);
|
||||
return cache.computeIfAbsent(blockState, blockState1 -> new BlockStateWrapper(blockState1, nullCheck));
|
||||
}
|
||||
|
||||
public final BlockState blockState;
|
||||
BlockStateWrapper(BlockState blockState)
|
||||
/**
|
||||
* Only meant for use in the {@code RENDERER_IGNORED_BLOCKS_INTERNAL} list. Do not use elsewhere, since the {@code levelWrapper} parameter of each {@code IBlockStateWrapper} will be {@code null}, causing issues.
|
||||
* @param resourceLocations The resource location(s) of the block(s) that should be ignored by the renderer, may only contain {@code [a-z0-9/._-)} characters.
|
||||
* @return The default blockstate(s) of the block(s), paired with the serialized resource location(s) of the block(s), which should be passed into the {@code RENDERER_IGNORED_BLOCKS_INTERNAL} map and the {@code getRendererIgnoredBlocks} method.
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static @NotNull HashMap<BlockState, String> getRendererIgnoredBlocksInternal(String @NotNull ... resourceLocations)
|
||||
{
|
||||
HashMap<BlockState, String> blockStates = new HashMap<>();
|
||||
|
||||
for (String resourceLocation : resourceLocations)
|
||||
{
|
||||
ResourceLocation fetchedResourceLocation = Objects.requireNonNull(ResourceLocation.tryParse(resourceLocation), String.format("Supplied a resource location that couldn't be parsed by Minecraft: %s", resourceLocation));
|
||||
var splitResourceLocation = resourceLocation.split(":");
|
||||
|
||||
if (splitResourceLocation.length == 0) {
|
||||
LOGGER.warn("A resource location that should be ignored by the renderer was in an invalid format: {}", resourceLocation);
|
||||
continue;
|
||||
}
|
||||
|
||||
blockStates.put(BuiltInRegistries.BLOCK.get(fetchedResourceLocation).defaultBlockState(), splitResourceLocation[1].toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
return blockStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only meant for use in the {@code RENDERER_IGNORED_BLOCKS} list. Do not use elsewhere, since the {@code levelWrapper} parameter of each {@code IBlockStateWrapper} will be {@code null}, causing issues.
|
||||
* @param rendererIgnoredBlocks A map containing the blockstate(s) of the block(s), paired with the resource location(s) of the block(s) that should be ignored by the renderer.
|
||||
* @return The blockstate wrapper(s) of the blockstate(s), which should be passed into the {@code RENDERER_IGNORED_BLOCKS} list.
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static @NotNull HashMap<String, ? extends IBlockStateWrapper> getRendererIgnoredBlocks(@NotNull Map<BlockState, String> rendererIgnoredBlocks)
|
||||
{
|
||||
HashMap<String, BlockStateWrapper> blockStateWrappers = new HashMap<>();
|
||||
|
||||
for (Map.Entry<BlockState, String> blockStateResourceLocations : rendererIgnoredBlocks.entrySet())
|
||||
{
|
||||
blockStateWrappers.put(blockStateResourceLocations.getValue(), fromBlockState(blockStateResourceLocations.getKey(), false));
|
||||
}
|
||||
|
||||
return blockStateWrappers;
|
||||
}
|
||||
|
||||
public final BlockState blockState;
|
||||
|
||||
BlockStateWrapper(BlockState blockState)
|
||||
{
|
||||
this(blockState, true);
|
||||
}
|
||||
|
||||
// TODO: Pass in levelwrapper so nullCheck has a use
|
||||
private BlockStateWrapper(BlockState blockState, boolean nullCheck) {
|
||||
this.blockState = blockState;
|
||||
LOGGER.trace("Created BlockStateWrapper for [" + blockState + "]");
|
||||
|
||||
LOGGER.trace("Created BlockStateWrapper for [{}]", blockState);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,49 +151,50 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
||||
@Override
|
||||
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
|
||||
|
||||
|
||||
@Override
|
||||
public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
{
|
||||
// cache the serialization result so it can be quickly used as a semi-stable hashing method
|
||||
if (this.serializationResult == null)
|
||||
// the result can be quickly used as a semi-stable hashing method, so it's going to be cached
|
||||
if (this.serializationResult != null)
|
||||
return this.serializationResult;
|
||||
|
||||
if (this.blockState == null)
|
||||
{
|
||||
if (this.blockState == null)
|
||||
{
|
||||
return "AIR";
|
||||
}
|
||||
|
||||
ResourceLocation resourceLocation;
|
||||
return "AIR";
|
||||
}
|
||||
|
||||
if (RENDERER_IGNORED_BLOCKS_INTERNAL.containsKey(this.blockState))
|
||||
return this.serializationResult = RENDERER_IGNORED_BLOCKS_INTERNAL.get(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());
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
return this.serializationResult;
|
||||
}
|
||||
|
||||
public static BlockStateWrapper deserialize(String resourceStateString) throws IOException // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
public static IBlockStateWrapper deserialize(String resourceStateString) throws IOException // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
|
||||
{
|
||||
if (resourceStateString.equals("AIR") || resourceStateString.equals("")) // the empty string shouldn't normally happen, but just in case
|
||||
{
|
||||
return AIR;
|
||||
}
|
||||
if (resourceStateString.isEmpty())
|
||||
throw new IOException("resourceStateString is empty");
|
||||
|
||||
if (RENDERER_IGNORED_BLOCKS_INTERNAL.containsValue(resourceStateString))
|
||||
return RENDERER_IGNORED_BLOCKS.get(resourceStateString);
|
||||
|
||||
|
||||
// parse the BlockState
|
||||
|
||||
+1
-1
@@ -484,7 +484,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
ChunkAccess chunk = totalChunks.get(x, z);
|
||||
if (chunk != null)
|
||||
{
|
||||
chunkWrapperList.set(x, z, new ChunkWrapper(chunk, region, null));
|
||||
chunkWrapperList.set(x, z, new ChunkWrapper(chunk, region, serverlevel.getLevelWrapper()));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user