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:
Steveplays28
2023-08-21 03:41:26 +02:00
parent 172b05aeac
commit 91334c0e5c
2 changed files with 89 additions and 23 deletions
@@ -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;
@@ -36,6 +36,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.
@@ -72,6 +73,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
@@ -13,9 +13,7 @@ import net.minecraft.world.level.block.state.BlockState;
import org.apache.logging.log4j.Logger;
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
@@ -27,6 +25,7 @@ import net.minecraft.core.Registry;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.EmptyBlockGetter;
import org.jetbrains.annotations.NotNull;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
@@ -44,8 +43,10 @@ public class BlockStateWrapper implements IBlockStateWrapper
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> cache = new ConcurrentHashMap<>();
public static final BlockStateWrapper AIR = fromBlockState(BuiltInRegistries.BLOCK.get(ResourceLocation.tryParse("minecraft:air")).defaultBlockState(), null);
public static final String AIR_SERIALIZATION_RESULT = "AIR";
public static final BlockStateWrapper AIR = fromBlockState(BuiltInRegistries.BLOCK.get(ResourceLocation.tryParse("minecraft:air")).defaultBlockState(), null, false);
public static final String[] RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS = {"minecraft:air", "minecraft:barrier", "minecraft:structure_void", "minecraft:light"};
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>
@@ -58,28 +59,89 @@ public class BlockStateWrapper implements IBlockStateWrapper
// constructors //
//==============//
public static BlockStateWrapper fromBlockState(BlockState blockState, @Nullable ILevelWrapper levelWrapper)
public static BlockStateWrapper fromBlockState(BlockState blockState, @NotNull ILevelWrapper levelWrapper)
{
return fromBlockState(blockState, levelWrapper, true);
}
private static BlockStateWrapper fromBlockState(BlockState blockState, @Nullable ILevelWrapper levelWrapper, boolean nullCheck)
{
if (Objects.requireNonNull(blockState).isAir() && AIR != null)
return AIR;
return cache.computeIfAbsent(blockState, blockState1 -> new BlockStateWrapper(blockState1, levelWrapper));
}
return cache.computeIfAbsent(blockState, blockState1 -> new BlockStateWrapper(blockState1, levelWrapper, nullCheck));
}
/**
* 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(), null, false));
}
return blockStateWrappers;
}
public final BlockState blockState;
@CheckForNull
public final ILevelWrapper levelWrapper;
BlockStateWrapper(BlockState blockState, @Nullable ILevelWrapper levelWrapper)
{
this.blockState = blockState;
this.levelWrapper = blockState.isAir()
? null
: Objects.requireNonNull(levelWrapper);
LOGGER.trace("Created BlockStateWrapper for ["+blockState+"]");
this(blockState, levelWrapper, true);
}
private BlockStateWrapper(BlockState blockState, @Nullable ILevelWrapper levelWrapper, boolean nullCheck) {
this.blockState = blockState;
if (nullCheck)
{
this.levelWrapper = RENDERER_IGNORED_BLOCKS_INTERNAL.containsKey(blockState)
? null
: Objects.requireNonNull(levelWrapper);
}
else
{
this.levelWrapper = levelWrapper;
}
LOGGER.trace("Created BlockStateWrapper for [{}]", blockState);
}
//=========//
@@ -104,7 +166,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
@Override
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; }
@Override
public String serialize()
{
@@ -112,8 +174,8 @@ public class BlockStateWrapper implements IBlockStateWrapper
if (this.serializationResult != null)
return this.serializationResult;
if (this.blockState.isAir())
return this.serializationResult = AIR_SERIALIZATION_RESULT;
if (RENDERER_IGNORED_BLOCKS_INTERNAL.containsKey(this.blockState))
return this.serializationResult = RENDERER_IGNORED_BLOCKS_INTERNAL.get(this.blockState);
Objects.requireNonNull(levelWrapper);
RegistryAccess registryAccess = ((Level) levelWrapper.getWrappedMcObject()).registryAccess();
@@ -140,13 +202,13 @@ public class BlockStateWrapper implements IBlockStateWrapper
return levelWrapper;
}
public static BlockStateWrapper deserialize(String resourceStateString, ILevelWrapper levelWrapper) throws IOException
public static IBlockStateWrapper deserialize(String resourceStateString, ILevelWrapper levelWrapper) throws IOException
{
if (resourceStateString.isEmpty())
throw new IOException("resourceStateString is empty");
if (resourceStateString.equals(AIR_SERIALIZATION_RESULT))
return AIR;
if (RENDERER_IGNORED_BLOCKS_INTERNAL.containsValue(resourceStateString))
return RENDERER_IGNORED_BLOCKS.get(resourceStateString);
// Parse the BlockState
int stateSeparatorIndex = resourceStateString.indexOf(STATE_STRING_SEPARATOR);