diff --git a/src/main/java/com/mitchej123/hodgepodge/config/FixesConfig.java b/src/main/java/com/mitchej123/hodgepodge/config/FixesConfig.java index 18b8c48dc..a7879e8be 100644 --- a/src/main/java/com/mitchej123/hodgepodge/config/FixesConfig.java +++ b/src/main/java/com/mitchej123/hodgepodge/config/FixesConfig.java @@ -28,6 +28,10 @@ public class FixesConfig { @Config.DefaultBoolean(true) public static boolean fixBogusIntegratedServerNPEs; + @Config.Comment("Do not flip bottom face textures (1.8+ behavior, see MC-47811)") + @Config.DefaultBoolean(true) + public static boolean fixBottomFaceUV; + @Config.Comment("Fix wrapped chat lines missing colors") @Config.DefaultBoolean(true) public static boolean fixChatWrappedColors; diff --git a/src/main/java/com/mitchej123/hodgepodge/core/HodgepodgeCore.java b/src/main/java/com/mitchej123/hodgepodge/core/HodgepodgeCore.java index 0d03161c2..7c42d1990 100644 --- a/src/main/java/com/mitchej123/hodgepodge/core/HodgepodgeCore.java +++ b/src/main/java/com/mitchej123/hodgepodge/core/HodgepodgeCore.java @@ -56,6 +56,9 @@ public HodgepodgeCore() { if (TweaksConfig.enableTagCompoundStringPooling || TweaksConfig.enableNBTStringPooling) { StringPooler.setupPooler(); } + if (FixesConfig.fixBottomFaceUV) { + Launch.blackboard.put("hodgepodge.FixesConfig.fixBottomFaceUV", Boolean.TRUE); + } } catch (ConfigException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java b/src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java index 26013c97e..c636cd17a 100644 --- a/src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java +++ b/src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java @@ -144,6 +144,10 @@ public enum Mixins implements IMixins { .addCommonMixins("minecraft.MixinBlockFence") .setApplyIf(() -> FixesConfig.fixFenceConnections) .setPhase(Phase.EARLY)), + FIX_BOTTOM_FACE_UV(new MixinBuilder() + .addClientMixins("minecraft.MixinRenderBlocks_FaceYNegUV") + .setApplyIf(() -> FixesConfig.fixBottomFaceUV) + .setPhase(Phase.EARLY)), FIX_INVENTORY_OFFSET_WITH_POTIONS(new MixinBuilder() .addClientMixins("minecraft.MixinInventoryEffectRenderer_PotionOffset") .setApplyIf(() -> TweaksConfig.fixPotionRenderOffset) diff --git a/src/main/java/com/mitchej123/hodgepodge/mixins/early/minecraft/MixinRenderBlocks_FaceYNegUV.java b/src/main/java/com/mitchej123/hodgepodge/mixins/early/minecraft/MixinRenderBlocks_FaceYNegUV.java new file mode 100644 index 000000000..d69bba899 --- /dev/null +++ b/src/main/java/com/mitchej123/hodgepodge/mixins/early/minecraft/MixinRenderBlocks_FaceYNegUV.java @@ -0,0 +1,147 @@ +package com.mitchej123.hodgepodge.mixins.early.minecraft; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.IIcon; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +/** + * Patched {@link RenderBlocks} to fix {@link #renderFaceYNeg} texture UV + *
+ *
Suppressed warnings:
+ *
{@code ClassWithTooManyFields}: Legacy class design
+ *
{@code UnusedMixin}: Dynamically applied at run-time
+ *
+ */ +@SuppressWarnings({ "ClassWithTooManyFields", "UnusedMixin" }) +@Mixin(value = RenderBlocks.class, priority = 100) +public abstract class MixinRenderBlocks_FaceYNegUV { + + @Shadow + public IIcon overrideBlockTexture; + @Shadow + public double renderMinX, renderMaxX, renderMinZ, renderMaxZ, renderMinY; + @Shadow + public int uvRotateBottom; + @Shadow + public boolean renderFromInside; + @Shadow + public boolean enableAO; + @Shadow + public int brightnessTopLeft, brightnessTopRight, brightnessBottomLeft, brightnessBottomRight; + @Shadow + public float colorRedTopLeft, colorGreenTopLeft, colorBlueTopLeft; + @Shadow + public float colorRedTopRight, colorGreenTopRight, colorBlueTopRight; + @Shadow + public float colorRedBottomLeft, colorGreenBottomLeft, colorBlueBottomLeft; + @Shadow + public float colorRedBottomRight, colorGreenBottomRight, colorBlueBottomRight; + + @Shadow + public abstract boolean hasOverrideBlockTexture(); + + /** + * @author leagris + * @reason Fixes horizontal flip bug in bottom face textures prior to Minecraft 1.8. + * @link MC-47811 + */ + @SuppressWarnings("OverlyComplexMethod") // Complex by nature + @Overwrite + public void renderFaceYNeg(Block block, double x, double y, double z, IIcon icon) { + Tessellator tessellator = Tessellator.instance; + + if (this.hasOverrideBlockTexture()) { + icon = this.overrideBlockTexture; + } + + double uMinX = icon.getInterpolatedU(16.0D - this.renderMinX * 16.0D); + double uMaxX = icon.getInterpolatedU(16.0D - this.renderMaxX * 16.0D); + double vMinZ = icon.getInterpolatedV(this.renderMinZ * 16.0D); + double vMaxZ = icon.getInterpolatedV(this.renderMaxZ * 16.0D); + + if (this.renderMinX < 0.0D || this.renderMaxX > 1.0D) { + uMinX = icon.getMaxU(); + uMaxX = icon.getMinU(); + } + + if (this.renderMinZ < 0.0D || this.renderMaxZ > 1.0D) { + vMinZ = icon.getMinV(); + vMaxZ = icon.getMaxV(); + } + + double uMaxXCopy = uMaxX; + double uMinXCopy = uMinX; + double vMinZCopy = vMinZ; + double vMaxZCopy = vMaxZ; + + if (this.uvRotateBottom == 2) { + uMinX = icon.getInterpolatedU(16.0D - this.renderMinZ * 16.0D); + vMinZ = icon.getInterpolatedV(16.0D - this.renderMaxX * 16.0D); + uMaxX = icon.getInterpolatedU(16.0D - this.renderMaxZ * 16.0D); + vMaxZ = icon.getInterpolatedV(16.0D - this.renderMinX * 16.0D); + vMinZCopy = vMinZ; + vMaxZCopy = vMaxZ; + uMaxXCopy = uMinX; + uMinXCopy = uMaxX; + vMinZ = vMaxZ; + vMaxZ = vMinZCopy; + } else if (this.uvRotateBottom == 1) { + uMinX = icon.getInterpolatedU(this.renderMaxZ * 16.0D); + vMinZ = icon.getInterpolatedV(this.renderMinX * 16.0D); + uMaxX = icon.getInterpolatedU(this.renderMinZ * 16.0D); + vMaxZ = icon.getInterpolatedV(this.renderMaxX * 16.0D); + uMaxXCopy = uMaxX; + uMinXCopy = uMinX; + uMinX = uMaxX; + uMaxX = uMinXCopy; + vMinZCopy = vMaxZ; + vMaxZCopy = vMinZ; + } else if (this.uvRotateBottom == 3) { + uMinX = icon.getInterpolatedU(this.renderMinX * 16.0D); + uMaxX = icon.getInterpolatedU(this.renderMaxX * 16.0D); + vMinZ = icon.getInterpolatedV(16.0D - this.renderMinZ * 16.0D); + vMaxZ = icon.getInterpolatedV(16.0D - this.renderMaxZ * 16.0D); + uMaxXCopy = uMaxX; + uMinXCopy = uMinX; + vMinZCopy = vMinZ; + vMaxZCopy = vMaxZ; + } + + double xMin = x + this.renderMinX; + double xMax = x + this.renderMaxX; + double yMin = y + this.renderMinY; + double zMin = z + this.renderMinZ; + double zMax = z + this.renderMaxZ; + + if (this.renderFromInside) { + xMin = x + this.renderMaxX; + xMax = x + this.renderMinX; + } + + if (this.enableAO) { + tessellator.setColorOpaque_F(this.colorRedTopLeft, this.colorGreenTopLeft, this.colorBlueTopLeft); + tessellator.setBrightness(this.brightnessTopLeft); + tessellator.addVertexWithUV(xMin, yMin, zMax, uMinXCopy, vMaxZCopy); + tessellator.setColorOpaque_F(this.colorRedBottomLeft, this.colorGreenBottomLeft, this.colorBlueBottomLeft); + tessellator.setBrightness(this.brightnessBottomLeft); + tessellator.addVertexWithUV(xMin, yMin, zMin, uMinX, vMinZ); + tessellator + .setColorOpaque_F(this.colorRedBottomRight, this.colorGreenBottomRight, this.colorBlueBottomRight); + tessellator.setBrightness(this.brightnessBottomRight); + tessellator.addVertexWithUV(xMax, yMin, zMin, uMaxXCopy, vMinZCopy); + tessellator.setColorOpaque_F(this.colorRedTopRight, this.colorGreenTopRight, this.colorBlueTopRight); + tessellator.setBrightness(this.brightnessTopRight); + tessellator.addVertexWithUV(xMax, yMin, zMax, uMaxX, vMaxZ); + } else { + tessellator.addVertexWithUV(xMin, yMin, zMax, uMinXCopy, vMaxZCopy); + tessellator.addVertexWithUV(xMin, yMin, zMin, uMinX, vMinZ); + tessellator.addVertexWithUV(xMax, yMin, zMin, uMaxXCopy, vMinZCopy); + tessellator.addVertexWithUV(xMax, yMin, zMax, uMaxX, vMaxZ); + } + } +}