Compact CTM: Decouple block face and rendered face (#1907)

This commit is contained in:
tiffit authored and GitHub committed 2026-07-04 03:22:04 +03:00
1 parent 112aae3735
commit 610209605f
3 files changed
+36 -28

No files matched your search

@@ -6,6 +6,7 @@ import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import com.prupe.mcpatcher.mal.block.BlockStateMatcher;
import net.minecraftforge.common.util.ForgeDirection;
final class BlockOrientation extends RenderBlockState {
@@ -44,7 +45,7 @@ final class BlockOrientation extends RenderBlockState {
private int textureFace;
private int textureFaceOrig;
private int rotateUV;
private boolean flipBottom;
private boolean flipped;
@Override
public void clear() {
@@ -57,7 +58,7 @@ final class BlockOrientation extends RenderBlockState {
offsetsComputed = false;
haveOffsets = false;
dx = dy = dz = 0;
flipBottom = !fixedBottomFaceUV;
flipped = false;
}
@Override
@@ -102,7 +103,10 @@ final class BlockOrientation extends RenderBlockState {
@Override
public int[] getOffset(int blockFace, int relativeDirection) {
return NEIGHBOR_OFFSET[flipBottom && blockFace == 0 ? 1 : blockFace][rotateUV(relativeDirection)];
if(flipped){
blockFace = ForgeDirection.OPPOSITES[blockFace];
}
return NEIGHBOR_OFFSET[blockFace][rotateUV(relativeDirection)];
}
@Override
@@ -146,8 +150,8 @@ final class BlockOrientation extends RenderBlockState {
}
public void setFlipBottom(){
flipBottom = true;
public void flipFace() {
flipped = true;
}
@Override
@@ -175,7 +179,7 @@ final class BlockOrientation extends RenderBlockState {
copy.textureFace = textureFace;
copy.textureFaceOrig = textureFaceOrig;
copy.rotateUV = rotateUV;
copy.flipBottom = flipBottom;
copy.flipped = flipped;
copy.blockAccess = blockAccess;
copy.block = block;
@@ -208,7 +212,7 @@ final class BlockOrientation extends RenderBlockState {
rotateUV = 0;
textureFace = blockFaceToTextureFace(blockFace);
metadataBits = (1 << metadata) | (1 << altMetadata);
flipBottom = !fixedBottomFaceUV;
if(!fixedBottomFaceUV && blockFace == ForgeDirection.DOWN.ordinal()) flipped = true;
}
void setBlockMetadata(Block block, int metadata, int face) {
@@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntMap;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.util.IIcon;
import net.minecraftforge.common.util.ForgeDirection;
public final class CompactCtmQuadProcessor {
@@ -52,29 +53,33 @@ public final class CompactCtmQuadProcessor {
this.override = compact;
}
public boolean processFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon origIcon) {
if(renderBlockState instanceof BlockOrientation blockOrientation){
blockOrientation.setFlipBottom();
public boolean processFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon origIcon, int face) {
boolean shouldFlip = face == ForgeDirection.DOWN.ordinal();
if(ForgeDirection.OPPOSITES[face] == renderBlockState.getBlockFace()){
shouldFlip = !shouldFlip;
}
if(shouldFlip && renderBlockState instanceof BlockOrientation blockOrientation){
blockOrientation.flipFace();
}
int neighborBits = override.getNeighborBits(renderBlockState, origIcon);
int ctmIndex = TileOverride.neighborMap[neighborBits & 0xFF];
IIcon replacement = getReplacementIcon(ctmIndex);
if (replacement != null) {
renderWholeFace(rb, renderBlockState, replacement);
renderWholeFace(rb, renderBlockState, replacement, face);
return true;
}
if (neighborBits == 0 || neighborBits == 0xFF) {
IIcon sprite = sprites[getCompactSpriteIndex(neighborBits)];
if (sprite != null) {
renderWholeFace(rb, renderBlockState, sprite);
renderWholeFace(rb, renderBlockState, sprite, face);
return true;
}
return false;
}
renderSplitFace(rb, renderBlockState, neighborBits);
renderSplitFace(rb, renderBlockState, neighborBits, face);
return true;
}
@@ -117,8 +122,7 @@ public final class CompactCtmQuadProcessor {
return SPRITE_DEFAULT;
}
private void renderSplitFace(RenderBlocks rb, RenderBlockState renderBlockState, int connections) {
final int face = renderBlockState.getBlockFace();
private void renderSplitFace(RenderBlocks rb, RenderBlockState renderBlockState, int connections, int face) {
final double minX = rb.renderMinX, minY = rb.renderMinY, minZ = rb.renderMinZ;
final double maxX = rb.renderMaxX, maxY = rb.renderMaxY, maxZ = rb.renderMaxZ;
@@ -155,7 +159,7 @@ public final class CompactCtmQuadProcessor {
}
setQuadrantBounds(rb, face, q, minX, minY, minZ, maxX, maxY, maxZ);
rb.overrideBlockTexture = icon;
renderFace(rb, renderBlockState, icon);
renderFace(rb, renderBlockState, icon, face);
}
if (ao) {
@@ -219,18 +223,17 @@ public final class CompactCtmQuadProcessor {
return (sky << 16) | (block & 0xFFFF);
}
private void renderWholeFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon icon) {
private void renderWholeFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon icon, int face) {
IIcon saved = rb.overrideBlockTexture;
rb.overrideBlockTexture = icon;
try {
renderFace(rb, renderBlockState, icon);
renderFace(rb, renderBlockState, icon, face);
} finally {
rb.overrideBlockTexture = saved;
}
}
private void renderFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon icon) {
int face = renderBlockState.getBlockFace();
private void renderFace(RenderBlocks rb, RenderBlockState renderBlockState, IIcon icon, int face) {
Block block = renderBlockState.getBlock();
int x = renderBlockState.getX();
int y = renderBlockState.getY();
@@ -21,6 +21,7 @@ import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -185,7 +186,7 @@ public abstract class MixinRenderBlocks {
public IBlockAccess blockAccess;
@Unique
private void angelica$handleCompactCtmFace(IIcon icon, CallbackInfo ci) {
private void angelica$handleCompactCtmFace(IIcon icon, ForgeDirection direction, CallbackInfo ci) {
CTMUtils.CTMCompactContext ctx = CTMUtils.getCurrentCompact();
if (ctx == null) {
return;
@@ -197,39 +198,39 @@ public abstract class MixinRenderBlocks {
return;
}
if (processor.processFace((RenderBlocks)(Object)this, renderBlockState, icon)) {
if (processor.processFace((RenderBlocks)(Object)this, renderBlockState, icon, direction.ordinal())) {
ci.cancel();
}
}
@Inject(method = "renderFaceYNeg", at = @At("HEAD"), cancellable = true)
private void compactCtm_onRenderFaceYNeg(Block block, double x, double y, double z, IIcon icon, CallbackInfo ci) {
angelica$handleCompactCtmFace(icon, ci);
angelica$handleCompactCtmFace(icon, ForgeDirection.DOWN, ci);
}
@Inject(method = "renderFaceYPos", at = @At("HEAD"), cancellable = true)
private void compactCtm_onRenderFaceYPos(Block block, double x, double y, double z, IIcon icon, CallbackInfo ci) {
angelica$handleCompactCtmFace(icon, ci);
angelica$handleCompactCtmFace(icon, ForgeDirection.UP, ci);
}
@Inject(method = "renderFaceZNeg", at = @At("HEAD"), cancellable = true)
private void compactCtm_onRenderFaceZNeg(Block block, double x, double y, double z, IIcon icon, CallbackInfo ci) {
angelica$handleCompactCtmFace(icon, ci);
angelica$handleCompactCtmFace(icon, ForgeDirection.NORTH, ci);
}
@Inject(method = "renderFaceZPos", at = @At("HEAD"), cancellable = true)
private void compactCtm_onRenderFaceZPos(Block block, double x, double y, double z, IIcon icon, CallbackInfo ci) {
angelica$handleCompactCtmFace(icon, ci);
angelica$handleCompactCtmFace(icon, ForgeDirection.SOUTH, ci);
}
@Inject(method = "renderFaceXNeg", at = @At("HEAD"), cancellable = true)
private void compactCtm_onRenderFaceXNeg(Block block, double x, double y, double z, IIcon icon, CallbackInfo ci) {
angelica$handleCompactCtmFace(icon, ci);
angelica$handleCompactCtmFace(icon, ForgeDirection.WEST, ci);
}
@Inject(method = "renderFaceXPos", at = @At("HEAD"), cancellable = true)
private void compactCtm_onRenderFaceXPos(Block block, double x, double y, double z, IIcon icon, CallbackInfo ci) {
angelica$handleCompactCtmFace(icon, ci);
angelica$handleCompactCtmFace(icon, ForgeDirection.EAST, ci);
}
@Inject(method = "renderStandardBlock(Lnet/minecraft/block/Block;III)Z", at = @At("RETURN"))