From d32f774b6d27aafcd2f595fbefe5f72a13b15707 Mon Sep 17 00:00:00 2001 From: Uraneptus Date: Wed, 23 Oct 2024 19:41:54 +0200 Subject: [PATCH] backported 1.21 changes --- .../java/vazkii/neat/NeatFiberConfig.java | 44 ++++++++++- Forge/build.gradle | 6 ++ .../java/vazkii/neat/NeatForgeConfig.java | 79 ++++++++++++------- .../java/vazkii/neat/HealthBarRenderer.java | 31 +++++--- .../src/main/java/vazkii/neat/NeatConfig.java | 4 + .../main/java/vazkii/neat/ToggleKeybind.java | 2 +- .../mixin/EntityRenderDispatcherMixin.java | 38 --------- .../neat/mixin/EntityRendererMixin.java | 25 +++++- .../vazkii/neat/mixin/LevelRendererMixin.java | 37 +++++++++ Xplat/src/main/resources/neat.mixins.json | 4 +- gradle.properties | 2 +- 11 files changed, 188 insertions(+), 84 deletions(-) delete mode 100644 Xplat/src/main/java/vazkii/neat/mixin/EntityRenderDispatcherMixin.java create mode 100644 Xplat/src/main/java/vazkii/neat/mixin/LevelRendererMixin.java diff --git a/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java b/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java index e2cc2d3..13e7b28 100644 --- a/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java +++ b/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java @@ -83,6 +83,10 @@ private static class Client implements NeatConfig.ConfigAccess { private final PropertyMirror enableDebugInfo = PropertyMirror.create(BOOLEAN); private final PropertyMirror showEntityName = PropertyMirror.create(BOOLEAN); private final PropertyMirror disableNameTag = PropertyMirror.create(BOOLEAN); + private final PropertyMirror disableNameTagIfHealthbar = PropertyMirror.create(BOOLEAN); + private final PropertyMirror iconOffsetX = PropertyMirror.create(DOUBLE); + private final PropertyMirror iconOffsetY = PropertyMirror.create(DOUBLE); + private final PropertyMirror decimalFormat = PropertyMirror.create(STRING); private final PropertyMirror> blacklist = PropertyMirror.create(ConfigTypes.makeList(STRING)); public ConfigTree configure(ConfigTreeBuilder builder) { @@ -99,7 +103,7 @@ public ConfigTree configure(ConfigTreeBuilder builder) { .finishValue(renderInF1::mirror) .beginValue("heightAbove", DOUBLE, 0.6) - .withComment("How far above the mob health bars should render") + .withComment("How far above the mob the health bars should render") .finishValue(heightAbove::mirror) .beginValue("drawBackground", BOOLEAN, true) @@ -139,7 +143,7 @@ public ConfigTree configure(ConfigTreeBuilder builder) { .finishValue(groupArmor::mirror) .beginValue("colorByType", BOOLEAN, false) - .withComment("Color the bar differently depending on whether the entity is hostile or is a boss") + .withComment("Color health bar by mob type instead of health percentage") .finishValue(colorByType::mirror) .beginValue("textColor", STRING, "FFFFFF") @@ -198,6 +202,22 @@ public ConfigTree configure(ConfigTreeBuilder builder) { .withComment("Disables the rendering of the vanilla name tag") .finishValue(disableNameTag::mirror) + .beginValue("disableNameTagIfHealthbar", BOOLEAN, true) + .withComment("If this is enabled and the \"disableNameTag\" option is true, the vanilla nametag is only hidden if the mob has a Neat healthbar rendered") + .finishValue(disableNameTagIfHealthbar::mirror) + + .beginValue("iconOffsetX", DOUBLE, 0.0) + .withComment("Offsets the healtbar icons on the x axis") + .finishValue(iconOffsetX::mirror) + + .beginValue("iconOffsetY", DOUBLE, 0.0) + .withComment("Offsets the healtbar icons on the y axis") + .finishValue(iconOffsetY::mirror) + + .beginValue("decimalFormat", STRING, "#.##") + .withComment("This value changes the decimal format of the HP. Only change this value if you are familiar with how the decimal format works!") + .finishValue(decimalFormat::mirror) + .beginValue("blacklist", ConfigTypes.makeList(STRING), NeatConfig.DEFAULT_DISABLED) .withComment("Entity ID's that should not have bars rendered") .finishValue(blacklist::mirror); @@ -345,6 +365,26 @@ public boolean disableNameTag() { return disableNameTag.getValue(); } + @Override + public boolean disableNameTagIfHealthbar() { + return disableNameTagIfHealthbar.getValue(); + } + + @Override + public double iconOffsetX() { + return iconOffsetX.getValue(); + } + + @Override + public double iconOffsetY() { + return iconOffsetY.getValue(); + } + + @Override + public String decimalFormat() { + return decimalFormat.getValue(); + } + @Override public List blacklist() { return blacklist.getValue(); diff --git a/Forge/build.gradle b/Forge/build.gradle index 099ada4..62aa8d5 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -46,6 +46,12 @@ minecraft { } } +repositories { + maven { + url "https://cursemaven.com" + } +} + dependencies { minecraft "net.minecraftforge:forge:${project.mc_version}-${project.forge_version}" compileOnly project(":Xplat") diff --git a/Forge/src/main/java/vazkii/neat/NeatForgeConfig.java b/Forge/src/main/java/vazkii/neat/NeatForgeConfig.java index 4ebc3a6..69211e0 100644 --- a/Forge/src/main/java/vazkii/neat/NeatForgeConfig.java +++ b/Forge/src/main/java/vazkii/neat/NeatForgeConfig.java @@ -45,41 +45,49 @@ private static class ForgeNeatConfig implements NeatConfig.ConfigAccess { private final ConfigValue enableDebugInfo; private final ConfigValue showEntityName; private final ConfigValue disableNameTag; + private final ConfigValue disableNameTagIfHealthbar; + private final ConfigValue iconOffsetX; + private final ConfigValue iconOffsetY; + private final ConfigValue decimalFormat; private final ConfigValue> blacklist; public ForgeNeatConfig(ForgeConfigSpec.Builder builder) { builder.push("general"); - maxDistance = builder.define("Max Distance", 24); - maxDistanceWithoutLineOfSight = builder.define("Max Distance Without Line of Sight", 8); - renderInF1 = builder.define("Render with Interface Disabled (F1)", false); - heightAbove = builder.define("Height Above Mob", 0.6); - drawBackground = builder.define("Draw Background", true); - backgroundPadding = builder.define("Background Padding", 2); - backgroundHeight = builder.define("Background Height", 6); - barHeight = builder.define("Health Bar Height", 4); - plateSize = builder.define("Plate Size", 25); - plateSizeBoss = builder.define("Plate Size (Boss)", 50); - showAttributes = builder.define("Show Attributes", true); - showArmor = builder.define("Show Armor", true); - groupArmor = builder.define("Group Armor (condense 5 iron icons into 1 diamond icon)", true); - colorByType = builder.define("Color Health Bar by Type (instead of health percentage)", false); + maxDistance = builder.comment("Maximum distance in blocks at which health bars should render").define("max_distance", 24); + maxDistanceWithoutLineOfSight = builder.comment("Maximum distance in blocks at which health bars should render without line of sight").define("max_distance_without_line_of_sight", 8); + renderInF1 = builder.comment("Whether health bars should render when the HUD is disabled with F1").define("render_without_gui", false); + heightAbove = builder.comment("How far above the mob the health bars should render").define("height_above_mob", 0.6); + drawBackground = builder.comment("Whether the gray background plate should be drawn").define("draw_background", true); + backgroundPadding = builder.comment("Amount of extra padding space around the background plate").define("background_padding", 2); + backgroundHeight = builder.comment("How tall the background plate should be").define("background_height", 6); + barHeight = builder.comment("How tall the health bar should be").define("health_bar_height", 4); + plateSize = builder.comment("How wide the health bar should be. If the entity has a long name, the bar will increase in size to match it.").define("plate_size", 25); + plateSizeBoss = builder.comment("plateSize but for bosses").define("plate_size_boss", 50); + showAttributes = builder.comment("Show mob attributes such as arthropod or undead").define("show_attributes", true); + showArmor = builder.comment("Show armor points").define("show_armor", true); + groupArmor = builder.comment("Group 5 iron icons into 1 diamond icon").define("group_armor", true); + colorByType = builder.comment("Color health bar by mob type instead of health percentage").define("color_health_bar_by_type", false); textColor = builder.comment("Text color in hex code format").define("text_color", "FFFFFF"); - hpTextHeight = builder.define("HP Text Height", 14); - showMaxHP = builder.define("Show Max HP", true); - showCurrentHP = builder.define("Show Current HP", true); - showPercentage = builder.define("Show HP Percentage", true); - showOnPassive = builder.comment("Whether bars on passive mobs should be shown").define("showOnPassive", true); - showOnHostile = builder.comment("Whether bars on hostile mobs should be shown (does not include bosses)").define("showOnHostile", true); - showOnPlayers = builder.define("Display on Players", true); - showOnBosses = builder.define("Display on Bosses", true); - showOnlyFocused = builder.define("Only show the health bar for the entity looked at", false); - showFullHealth = builder.define("Show entities with full health", true); - enableDebugInfo = builder.define("Show Debug Info with F3", true); - showEntityName = builder.define("show_entity_name", true); + hpTextHeight = builder.comment("Height of the text on the health bar").define("hp_text_height", 14); + showMaxHP = builder.comment("Whether the maximum health of the mob should be shown").define("show_max_hp", true); + showCurrentHP = builder.comment("Whether the current health of the mob should be shown").define("show_current_hp", true); + showPercentage = builder.comment("Whether the percentage health of the mob should be shown").define("show_hp_percentage", true); + showOnPassive = builder.comment("Whether bars on passive mobs should be shown").define("show_on_passive", true); + showOnHostile = builder.comment("Whether bars on hostile mobs should be shown (does not include bosses)").define("show_on_hostile", true); + showOnPlayers = builder.comment("Whether bars on players should be shown").define("display_on_players", true); + showOnBosses = builder.comment("Whether bars on bosses should be shown").define("display_on_bosses", true); + showOnlyFocused = builder.comment("Only show bars for mobs you are targeting").define("only_health_bar_for_target", false); + showFullHealth = builder.comment("Show bars for mobs that are at full health").define("show_entity_full_health", true); + enableDebugInfo = builder.comment("Show extra debug info on the bar when F3 is enabled").define("show_debug_with_f3", true); + showEntityName = builder.comment("Show entity name").define("show_entity_name", true); disableNameTag = builder.comment("Disables the rendering of the vanilla name tag").define("disable_name_tag", false); + disableNameTagIfHealthbar = builder.comment("If this is enabled and the \"disableNameTag\" option is true, the vanilla nametag is only hidden if the mob has a Neat healthbar rendered").define("disable_name_tag_if_healthbar", true); + iconOffsetX = builder.comment("Offsets the healtbar icons on the x axis").define("icon_offset_x", 0.0); + iconOffsetY = builder.comment("Offsets the healtbar icons on the y axis").define("icon_offset_y", 0.0); + decimalFormat = builder.comment("This value changes the decimal format of the HP. Only change this value if you are familiar with how the decimal format works!").define("decimal_format", "#.##"); blacklist = builder.comment("Blacklist uses entity IDs, not their display names. Use F3 to see them in the Neat bar.") - .defineList("Blacklist", NeatConfig.DEFAULT_DISABLED, a -> true); + .defineList("blacklist", NeatConfig.DEFAULT_DISABLED, a -> true); builder.pop(); } @@ -224,6 +232,23 @@ public boolean disableNameTag() { return disableNameTag.get(); } + @Override + public boolean disableNameTagIfHealthbar() { + return disableNameTagIfHealthbar.get(); + } + @Override + public double iconOffsetX() { + return iconOffsetX.get(); + } + @Override + public double iconOffsetY() { + return iconOffsetY.get(); + } + @Override + public String decimalFormat() { + return decimalFormat.get(); + } + @SuppressWarnings("unchecked") @Override public List blacklist() { diff --git a/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java b/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java index 277ca2c..b5c522b 100644 --- a/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java +++ b/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java @@ -5,9 +5,11 @@ import com.mojang.math.Axis; import net.minecraft.ChatFormatting; +import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; @@ -36,7 +38,6 @@ import java.util.*; public class HealthBarRenderer { - private static final DecimalFormat HEALTH_FORMAT = new DecimalFormat("#.##"); private static Entity getEntityLookedAt(Entity e) { Entity foundEntity = null; @@ -133,7 +134,7 @@ private static int getColor(LivingEntity entity, boolean colorByType, boolean bo private static final TagKey> FABRIC_BOSS_TAG = TagKey.create(Registries.ENTITY_TYPE, new ResourceLocation("c", "bosses")); - private static boolean isBoss(Entity entity) { + public static boolean isBoss(Entity entity) { return entity.getType().is(FORGE_BOSS_TAG) || entity.getType().is(FABRIC_BOSS_TAG); } @@ -213,7 +214,8 @@ private static boolean shouldShowPlate(LivingEntity living, Entity cameraEntity) } public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSource buffers, - Quaternionf cameraOrientation) { + Camera camera, EntityRenderer entityRenderer, + float partialTicks, double x, double y, double z) { final Minecraft mc = Minecraft.getInstance(); if (!(entity instanceof LivingEntity living)) { @@ -221,7 +223,7 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou } //This was previously mc.gameRenderer.getMainCamera().getEntity() but that caused an incompatibility with RealCamera - if (!shouldShowPlate(living, mc.cameraEntity)) { + if (!shouldShowPlate(living, camera.getEntity())) { return; } @@ -237,9 +239,15 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou final float nameLen = mc.font.width(name) * textScale; final float halfSize = Math.max(NeatConfig.instance.plateSize(), nameLen / 2.0F + 10.0F); + Vec3 vec3 = entityRenderer.getRenderOffset(entity, partialTicks); + double d2 = x + vec3.x(); + double d3 = y + vec3.y(); + double d0 = z + vec3.z(); + poseStack.pushPose(); + poseStack.translate(d2, d3, d0); poseStack.translate(0, living.getBbHeight() + NeatConfig.instance.heightAbove(), 0); - poseStack.mulPose(cameraOrientation); + poseStack.mulPose(camera.rotation()); // Plate background, bars, and text operate with globalScale, but icons don't poseStack.pushPose(); @@ -309,13 +317,14 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou poseStack.scale(healthValueTextScale, healthValueTextScale, healthValueTextScale); int h = NeatConfig.instance.hpTextHeight(); + DecimalFormat health_format = new DecimalFormat(NeatConfig.instance.decimalFormat()); if (NeatConfig.instance.showCurrentHP()) { - String hpStr = HEALTH_FORMAT.format(living.getHealth()); + String hpStr = health_format.format(living.getHealth()); mc.font.drawInBatch(hpStr, 2, h, textColor, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); } if (NeatConfig.instance.showMaxHP()) { - String maxHpStr = ChatFormatting.BOLD + HEALTH_FORMAT.format(living.getMaxHealth()); + String maxHpStr = ChatFormatting.BOLD + health_format.format(living.getMaxHealth()); mc.font.drawInBatch(maxHpStr, (int) (halfSize / healthValueTextScale * 2) - mc.font.width(maxHpStr) - 2, h, textColor, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); } if (NeatConfig.instance.showPercentage()) { @@ -387,11 +396,11 @@ private static void renderIcon(Level level, ItemStack icon, PoseStack poseStack, // halfSize and co. are units operating under the assumption of globalScale, // but in the icon rendering section we don't use globalScale, so we need // to manually multiply it in to ensure the units line up. - float dx = (halfSize - leftShift) * globalScale; - float dy = 3F * globalScale; - float dz = zShift * globalScale; + double dx = (halfSize - leftShift) * globalScale + NeatConfig.instance.iconOffsetX(); + double dy = 3F * globalScale; + double dz = zShift * globalScale; // Need to negate X due to our rotation below - poseStack.translate(-dx, dy, dz); + poseStack.translate(-dx, dy + NeatConfig.instance.iconOffsetY(), dz); poseStack.scale(iconScale, iconScale, iconScale); poseStack.mulPose(Axis.YP.rotationDegrees(180F)); Minecraft.getInstance().getItemRenderer() diff --git a/Xplat/src/main/java/vazkii/neat/NeatConfig.java b/Xplat/src/main/java/vazkii/neat/NeatConfig.java index fe39fd6..5d05417 100644 --- a/Xplat/src/main/java/vazkii/neat/NeatConfig.java +++ b/Xplat/src/main/java/vazkii/neat/NeatConfig.java @@ -36,6 +36,10 @@ public interface ConfigAccess { boolean enableDebugInfo(); boolean showEntityName(); boolean disableNameTag(); + boolean disableNameTagIfHealthbar(); + double iconOffsetX(); + double iconOffsetY(); + String decimalFormat(); List blacklist(); } diff --git a/Xplat/src/main/java/vazkii/neat/ToggleKeybind.java b/Xplat/src/main/java/vazkii/neat/ToggleKeybind.java index 3e3c096..ec5eacc 100644 --- a/Xplat/src/main/java/vazkii/neat/ToggleKeybind.java +++ b/Xplat/src/main/java/vazkii/neat/ToggleKeybind.java @@ -6,7 +6,7 @@ public class ToggleKeybind { - public static final KeyMapping KEY = new KeyMapping("neat.keybind.toggle", GLFW.GLFW_KEY_UNKNOWN, "key.categories.misc");; + public static final KeyMapping KEY = new KeyMapping("neat.keybind.toggle", GLFW.GLFW_KEY_UNKNOWN, "key.categories.misc"); public static void handle() { while (KEY.consumeClick()) { diff --git a/Xplat/src/main/java/vazkii/neat/mixin/EntityRenderDispatcherMixin.java b/Xplat/src/main/java/vazkii/neat/mixin/EntityRenderDispatcherMixin.java deleted file mode 100644 index edb6599..0000000 --- a/Xplat/src/main/java/vazkii/neat/mixin/EntityRenderDispatcherMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -package vazkii.neat.mixin; - -import com.mojang.blaze3d.vertex.PoseStack; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.world.entity.Entity; - -import org.joml.Quaternionf; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import vazkii.neat.HealthBarRenderer; - -@Mixin(EntityRenderDispatcher.class) -public abstract class EntityRenderDispatcherMixin { - @Shadow - public abstract Quaternionf cameraOrientation(); - - /** - * Hooks right after the main entity renderer runs. - * Here we have a good GL state set up, the buffers are still available for fabulous mode, etc. - * It's a much better point to render our bars than something like RenderLevelLastEvent. - */ - @Inject( - method = "render", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;render(Lnet/minecraft/world/entity/Entity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", - shift = At.Shift.AFTER - ) - ) - private void neat_renderHealthBar(Entity entity, double worldX, double worldY, double worldZ, float entityYRot, float partialTicks, PoseStack poseStack, MultiBufferSource buffers, int light, CallbackInfo ci) { - HealthBarRenderer.hookRender(entity, poseStack, buffers, cameraOrientation()); - } -} diff --git a/Xplat/src/main/java/vazkii/neat/mixin/EntityRendererMixin.java b/Xplat/src/main/java/vazkii/neat/mixin/EntityRendererMixin.java index 79c8179..818fe49 100644 --- a/Xplat/src/main/java/vazkii/neat/mixin/EntityRendererMixin.java +++ b/Xplat/src/main/java/vazkii/neat/mixin/EntityRendererMixin.java @@ -4,22 +4,43 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import vazkii.neat.HealthBarRenderer; import vazkii.neat.NeatConfig; @Mixin(EntityRenderer.class) public class EntityRendererMixin { @Inject(method = "render(Lnet/minecraft/world/entity/Entity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;renderNameTag(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V"), cancellable = true) - private void neat_disableNameTag(Entity $$0, float $$1, float $$2, PoseStack $$3, MultiBufferSource $$4, int $$5, CallbackInfo ci) { - if (NeatConfig.instance.disableNameTag()) { + private void neat_disableNameTag(Entity entity, float $$1, float $$2, PoseStack $$3, MultiBufferSource $$4, int $$5, CallbackInfo ci) { + if (NeatConfig.instance.disableNameTag() && (!NeatConfig.instance.disableNameTagIfHealthbar() || neat$allowNameTagDisable(entity))) { ci.cancel(); } } + + @Unique + public boolean neat$allowNameTagDisable(Entity entity) { + if (!(entity instanceof LivingEntity)) + return false; + if (entity instanceof Player && !NeatConfig.instance.showOnPlayers()) + return false; + if (HealthBarRenderer.isBoss(entity) && !NeatConfig.instance.showOnBosses()) + return false; + if (entity.getType().getCategory().isFriendly() && !NeatConfig.instance.showOnPassive()) + return false; + if ((!entity.getType().getCategory().isFriendly() && !HealthBarRenderer.isBoss(entity)) && !NeatConfig.instance.showOnHostile()) + return false; + var id = BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()); + return !NeatConfig.instance.blacklist().contains(id.toString()) && NeatConfig.draw; + } } diff --git a/Xplat/src/main/java/vazkii/neat/mixin/LevelRendererMixin.java b/Xplat/src/main/java/vazkii/neat/mixin/LevelRendererMixin.java new file mode 100644 index 0000000..b64b5ed --- /dev/null +++ b/Xplat/src/main/java/vazkii/neat/mixin/LevelRendererMixin.java @@ -0,0 +1,37 @@ +package vazkii.neat.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import vazkii.neat.HealthBarRenderer; + +@Mixin(LevelRenderer.class) +public class LevelRendererMixin { + + @Shadow + @Final + private EntityRenderDispatcher entityRenderDispatcher; + + /** + * This hooks right after the EntityRenderDispatcher + * + */ + @Inject(method = "renderEntity(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;render(Lnet/minecraft/world/entity/Entity;DDDFFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", + shift = At.Shift.AFTER)) + private void neat_renderHealthBar(Entity entity, double camX, double camY, double camZ, float partialTick, PoseStack poseStack, MultiBufferSource buffers, CallbackInfo ci) { + double d0 = Mth.lerp(partialTick, entity.xOld, entity.getX()); + double d1 = Mth.lerp(partialTick, entity.yOld, entity.getY()); + double d2 = Mth.lerp(partialTick, entity.zOld, entity.getZ()); + HealthBarRenderer.hookRender(entity, poseStack, buffers, entityRenderDispatcher.camera, entityRenderDispatcher.getRenderer(entity), partialTick, d0 - camX, d1 - camY, d2 - camZ); + } +} diff --git a/Xplat/src/main/resources/neat.mixins.json b/Xplat/src/main/resources/neat.mixins.json index 6e4a0c9..f5f51b8 100644 --- a/Xplat/src/main/resources/neat.mixins.json +++ b/Xplat/src/main/resources/neat.mixins.json @@ -4,11 +4,11 @@ "compatibilityLevel": "JAVA_17", "package": "vazkii.neat.mixin", "mixins": [ - "EntityRendererMixin" ], "client": [ "AccessorRenderType", - "EntityRenderDispatcherMixin", + "EntityRendererMixin", + "LevelRendererMixin", "MinecraftMixin" ], "injectors": { diff --git a/gradle.properties b/gradle.properties index 3fc237b..8958fd6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,6 @@ org.gradle.jvmargs=-Xmx1G \ group=vazkii.neat forge_version=47.1.3 mod_id=neat -build_number=38 +build_number=41 mod_name=Neat mc_version=1.20.1