Narrow and make damage overlay a config option (#1886)

This commit is contained in:
Eclipse-Sol authored and GitHub committed 2026-06-27 10:12:39 -07:00
1 parent eb0ecb0483
commit b27834cbd9
3 files changed
+27 -72

No files matched your search

@@ -357,8 +357,13 @@ public class AngelicaConfig {
@Config.RequiresMcRestart @Config.RequiresMcRestart
public static boolean disableErrorChecks; public static boolean disableErrorChecks;
@Config.Comment("Fixes various issues with entity overlays, such as z-fighting, damage animations and eyes.") @Config.Comment("Fixes various issues with entity overlays, such as z-fighting and eyes.")
@Config.DefaultBoolean(true) @Config.DefaultBoolean(true)
@Config.RequiresMcRestart @Config.RequiresMcRestart
public static boolean entityOverlayFixes; public static boolean entityOverlayFixes;
@Config.Comment("Swap the vanilla damage overlay with one similar to modern. Fixes specific issues with z-fighting.")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean entityModernDamageOverlay;
} }
@@ -64,7 +64,15 @@ public enum Mixins implements IMixins {
.addExcludedMod(TargetedMod.CUSTOM_PLAYER_MODELS) .addExcludedMod(TargetedMod.CUSTOM_PLAYER_MODELS)
.addClientMixins( .addClientMixins(
"angelica.bugfixes.MixinRendererLivingEntity_EyeDepth" "angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
, "angelica.bugfixes.MixinRendererLivingEntity_OverlayTint" )
),
ANGELICA_DAMAGE_OVERLAY(new MixinBuilder()
.setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.entityModernDamageOverlay)
.addExcludedMod(TargetedMod.CUSTOM_PLAYER_MODELS)
.addClientMixins(
"angelica.bugfixes.MixinRendererLivingEntity_OverlayTint"
) )
), ),
@@ -13,7 +13,6 @@ import net.minecraft.client.renderer.entity.RendererLivingEntity;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -23,6 +22,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/** /**
* Single-pass damage-overlay tint, modeled on modern Minecraft's OverlayTexture. * Single-pass damage-overlay tint, modeled on modern Minecraft's OverlayTexture.
* The tint is applied only while the main body model renders.
*/ */
@Mixin(RendererLivingEntity.class) @Mixin(RendererLivingEntity.class)
public class MixinRendererLivingEntity_OverlayTint { public class MixinRendererLivingEntity_OverlayTint {
@@ -33,8 +33,6 @@ public class MixinRendererLivingEntity_OverlayTint {
@Unique private boolean angelica$ffpOverlayActive; @Unique private boolean angelica$ffpOverlayActive;
@Unique private boolean angelica$shaderEntityColorActive; @Unique private boolean angelica$shaderEntityColorActive;
@Unique private boolean angelica$emissivePass;
@Inject( @Inject(
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V", method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
at = @At(value = "INVOKE", at = @At(value = "INVOKE",
@@ -64,20 +62,13 @@ public class MixinRendererLivingEntity_OverlayTint {
@Inject( @Inject(
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V", method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
at = @At(value = "INVOKE", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;F)V"), target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderModel(Lnet/minecraft/entity/EntityLivingBase;FFFFFF)V",
shift = At.Shift.AFTER),
require = 1, expect = 1 require = 1, expect = 1
) )
private void angelica$teardownOverlay(EntityLivingBase entity, double x, double y, double z, private void angelica$clearBodyTint(EntityLivingBase entity, double x, double y, double z,
float yaw, float partialTick, CallbackInfo ci) { float yaw, float partialTick, CallbackInfo ci) {
if (angelica$ffpOverlayActive) { angelica$clearOverlayColor();
GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F);
angelica$ffpOverlayActive = false;
}
if (angelica$shaderEntityColorActive) {
// Don't tint held items
CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F);
angelica$shaderEntityColorActive = false;
}
} }
/** /**
@@ -100,64 +91,17 @@ public class MixinRendererLivingEntity_OverlayTint {
original.call(model, entity, p1, p2, p3, p4, p5, p6); original.call(model, entity, p1, p2, p3, p4, p5, p6);
} }
/**
* Prevent bleed by saving last state and comparing with current blend state.
*/
@WrapOperation(
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I"),
require = 1, expect = 1
)
private int angelica$detectEmissivePass(RendererLivingEntity self, EntityLivingBase entity, int pass,
float partialTick, Operation<Integer> original) {
GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
final int result = original.call(self, entity, pass, partialTick);
final int srcAfter = GLStateManager.glGetInteger(GL14.GL_BLEND_SRC_RGB);
final int dstAfter = GLStateManager.glGetInteger(GL14.GL_BLEND_DST_RGB);
angelica$emissivePass = srcAfter == GL11.GL_ONE && dstAfter == GL11.GL_ONE;
return result;
}
/**
* Skip the overlay on emissive eye pass.
*/
@WrapOperation(
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/model/ModelBase;render(Lnet/minecraft/entity/Entity;FFFFFF)V"),
slice = @Slice(
from = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;shouldRenderPass(Lnet/minecraft/entity/EntityLivingBase;IF)I"),
to = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderEquippedItems(Lnet/minecraft/entity/EntityLivingBase;F)V")
),
require = 1, expect = 1
)
private void angelica$untintEmissivePass(ModelBase model, Entity entity,
float p1, float p2, float p3, float p4, float p5, float p6, Operation<Void> original) {
if (!angelica$skipReRender || !angelica$emissivePass) {
original.call(model, entity, p1, p2, p3, p4, p5, p6);
return;
}
if (angelica$ffpOverlayActive) {
GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F);
original.call(model, entity, p1, p2, p3, p4, p5, p6);
GLStateManager.setOverlayColor(1.0F, 0.0F, 0.0F, ANGELICA$RED_MIX);
} else if (angelica$shaderEntityColorActive) {
CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F);
original.call(model, entity, p1, p2, p3, p4, p5, p6);
CapturedRenderingState.INSTANCE.setCurrentEntityColor(1.0F, 0.0F, 0.0F, ANGELICA$RED_MIX);
} else {
original.call(model, entity, p1, p2, p3, p4, p5, p6);
}
}
@Inject( @Inject(
method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V", method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V",
at = @At("RETURN") at = @At("RETURN")
) )
private void angelica$reset(CallbackInfo ci) { private void angelica$reset(CallbackInfo ci) {
angelica$clearOverlayColor();
angelica$skipReRender = false;
}
@Unique
private void angelica$clearOverlayColor() {
if (angelica$ffpOverlayActive) { if (angelica$ffpOverlayActive) {
GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F); GLStateManager.setOverlayColor(0.0F, 0.0F, 0.0F, 0.0F);
angelica$ffpOverlayActive = false; angelica$ffpOverlayActive = false;
@@ -166,8 +110,6 @@ public class MixinRendererLivingEntity_OverlayTint {
CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F); CapturedRenderingState.INSTANCE.setCurrentEntityColor(0.0F, 0.0F, 0.0F, 0.0F);
angelica$shaderEntityColorActive = false; angelica$shaderEntityColorActive = false;
} }
angelica$skipReRender = false;
angelica$emissivePass = false;
} }
@Unique @Unique