From ad97f322b263daa4010b2fb3dff2ffeb6acf3264 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 30 Oct 2023 07:46:21 -0500 Subject: [PATCH 1/2] Fix aether block tinting without breaking vanilla oceans --- .../block/cache/ClientBlockStateCache.java | 74 +++++++++++++++++-- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java index 4d714f78a..85919de37 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java @@ -46,8 +46,8 @@ import java.util.Random; import net.minecraft.world.level.block.state.BlockState; import org.apache.logging.log4j.Logger; +import java.util.HashSet; import java.util.List; -import java.util.Random; /** * @version 2022-9-16 @@ -57,6 +57,9 @@ public class ClientBlockStateCache private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final HashSet BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>(); + private static final HashSet BROKEN_BLOCK_STATES = new HashSet<>(); + #if PRE_MC_1_19_2 public static final Random random = new Random(0); #else @@ -235,11 +238,70 @@ public class ClientBlockStateCache public int getAndResolveFaceColor(BiomeWrapper biome, DhBlockPos pos) { // FIXME: impl per-face colors - if (!needPostTinting) return baseColor; - int tintColor = Minecraft.getInstance().getBlockColors() - .getColor(state, new TintWithoutLevelOverrider(biome), McObjectConverter.Convert(pos), tintIndex); - if (tintColor == -1) return baseColor; - return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor); + + // only get the tint if the block needs to be tinted + if (!this.needPostTinting) + { + return this.baseColor; + } + + // don't try tinting blocks that don't support our method of tint getting + if (BROKEN_BLOCK_STATES.contains(this.state)) + { + return this.baseColor; + } + + + // attempt to get the tint + int tintColor = -1; + try + { + // try to use the fast tint getter logic first + if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.state)) + { + try + { + tintColor = Minecraft.getInstance().getBlockColors() + .getColor(this.state, new TintWithoutLevelOverrider(biome), McObjectConverter.Convert(pos), this.tintIndex); + } + catch (UnsupportedOperationException e) + { + // this exception generally occurs if the tint requires other blocks besides itself + LOGGER.debug("Unable to use ["+TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.state + "] and biome: [" + biome + "] at pos: " + pos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e); + BLOCK_STATES_THAT_NEED_LEVEL.add(this.state); + } + } + + // use the level logic only if requested + if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.state)) + { + // this logic can't be used all the time due to it breaking some blocks tinting + // specifically oceans don't render correctly + tintColor = Minecraft.getInstance().getBlockColors() + .getColor(this.state, new TintGetterOverrideFast(this.level), McObjectConverter.Convert(pos), this.tintIndex); + } + } + catch (Exception e) + { + // only display the error once per block/biome type to reduce log spam + if (!BROKEN_BLOCK_STATES.contains(this.state)) + { + LOGGER.warn("Failed to get block color for block: [" + this.state + "] and biome: [" + biome + "] at pos: " + pos + ". Error: ["+e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e); + BROKEN_BLOCK_STATES.add(this.state); + } + } + + + + if (tintColor != -1) + { + return ColorUtil.multiplyARGBwithRGB(this.baseColor, tintColor); + } + else + { + // unable to get the tinted color, use the base color instead + return this.baseColor; + } } } From 95e29f36ef12dcb73cb3a2bd099d5c7f014505db Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 30 Oct 2023 07:46:46 -0500 Subject: [PATCH 2/2] minor ClientBlockStateCache refactor --- .../block/cache/ClientBlockStateCache.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java index 85919de37..a14db741f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/cache/ClientBlockStateCache.java @@ -66,12 +66,12 @@ public class ClientBlockStateCache public static final RandomSource random = RandomSource.create(); #endif - public final BlockState state; + public final BlockState blockState; public final LevelReader level; public final BlockPos pos; public ClientBlockStateCache(BlockState blockState, IClientLevelWrapper samplingLevel, DhBlockPos samplingPos) { - state = blockState; + this.blockState = blockState; level = (LevelReader) samplingLevel.getWrappedMcObject(); pos = McObjectConverter.Convert(samplingPos); resolveColors(); @@ -189,21 +189,21 @@ public class ClientBlockStateCache private void resolveColors() { if (isColorResolved) return; - if (state.getFluidState().isEmpty()) + if (blockState.getFluidState().isEmpty()) { List quads = null; for (Direction direction : DIRECTION_ORDER) { quads = Minecraft.getInstance().getModelManager().getBlockModelShaper(). - getBlockModel(state).getQuads(state, direction, random); + getBlockModel(blockState).getQuads(blockState, direction, random); if (quads != null && !quads.isEmpty() && - !(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP)) + !(blockState.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP)) break; } ; if (quads == null || quads.isEmpty()) { quads = Minecraft.getInstance().getModelManager().getBlockModelShaper(). - getBlockModel(state).getQuads(state, null, random); + getBlockModel(blockState).getQuads(blockState, null, random); } if (quads != null && !quads.isEmpty()) { @@ -213,15 +213,15 @@ public class ClientBlockStateCache baseColor = calculateColorFromTexture( #if PRE_MC_1_17_1 quads.get(0).sprite, #else quads.get(0).getSprite(), #endif - ColorMode.getColorMode(state.getBlock())); + ColorMode.getColorMode(blockState.getBlock())); } else { // Backup method. needPostTinting = false; needShade = false; tintIndex = 0; - baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state), - ColorMode.getColorMode(state.getBlock())); + baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(blockState), + ColorMode.getColorMode(blockState.getBlock())); } } else @@ -229,8 +229,8 @@ public class ClientBlockStateCache needPostTinting = true; needShade = false; tintIndex = 0; - baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state), - ColorMode.getColorMode(state.getBlock())); + baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(blockState), + ColorMode.getColorMode(blockState.getBlock())); } isColorResolved = true; } @@ -246,7 +246,7 @@ public class ClientBlockStateCache } // don't try tinting blocks that don't support our method of tint getting - if (BROKEN_BLOCK_STATES.contains(this.state)) + if (BROKEN_BLOCK_STATES.contains(this.blockState)) { return this.baseColor; } @@ -257,37 +257,37 @@ public class ClientBlockStateCache try { // try to use the fast tint getter logic first - if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.state)) + if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) { try { tintColor = Minecraft.getInstance().getBlockColors() - .getColor(this.state, new TintWithoutLevelOverrider(biome), McObjectConverter.Convert(pos), this.tintIndex); + .getColor(this.blockState, new TintWithoutLevelOverrider(biome), McObjectConverter.Convert(pos), this.tintIndex); } catch (UnsupportedOperationException e) { // this exception generally occurs if the tint requires other blocks besides itself - LOGGER.debug("Unable to use ["+TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.state + "] and biome: [" + biome + "] at pos: " + pos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e); - BLOCK_STATES_THAT_NEED_LEVEL.add(this.state); + LOGGER.debug("Unable to use ["+TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biome + "] at pos: " + pos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e); + BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState); } } // use the level logic only if requested - if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.state)) + if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) { // this logic can't be used all the time due to it breaking some blocks tinting // specifically oceans don't render correctly tintColor = Minecraft.getInstance().getBlockColors() - .getColor(this.state, new TintGetterOverrideFast(this.level), McObjectConverter.Convert(pos), this.tintIndex); + .getColor(this.blockState, new TintGetterOverrideFast(this.level), McObjectConverter.Convert(pos), this.tintIndex); } } catch (Exception e) { // only display the error once per block/biome type to reduce log spam - if (!BROKEN_BLOCK_STATES.contains(this.state)) + if (!BROKEN_BLOCK_STATES.contains(this.blockState)) { - LOGGER.warn("Failed to get block color for block: [" + this.state + "] and biome: [" + biome + "] at pos: " + pos + ". Error: ["+e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e); - BROKEN_BLOCK_STATES.add(this.state); + LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biome + "] at pos: " + pos + ". Error: ["+e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e); + BROKEN_BLOCK_STATES.add(this.blockState); } }