diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ce00c7c..7d2b218 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -6,16 +6,16 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '21' - name: Validate gradlew integrity - uses: gradle/wrapper-validation-action@v1 + uses: gradle/actions/wrapper-validation@v3 - name: Cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -35,7 +35,7 @@ jobs: run: | MC=$(awk -F '=' '/mc_version/ { print $2; }' gradle.properties) BUILD=$(awk -F '=' '/build_number/ { print $2; }' gradle.properties) - echo "forge=Forge/build/libs/Neat-${MC}-${BUILD}-FORGE.jar" >> "$GITHUB_OUTPUT" + echo "neoforge=NeoForge/build/libs/Neat-${MC}-${BUILD}-NEOFORGE.jar" >> "$GITHUB_OUTPUT" echo "fabric=Fabric/build/libs/Neat-${MC}-${BUILD}-FABRIC.jar" >> "$GITHUB_OUTPUT" - name: Sign jars env: @@ -44,18 +44,18 @@ jobs: run: | echo "${SIGNING_KEY}" | gpg --import - gpg --local-user "Violet Moon Signing Key" --armor \ - --detach-sign ${{ steps.calculate_artifact_names.outputs.forge }} + --detach-sign ${{ steps.calculate_artifact_names.outputs.neoforge }} gpg --local-user "Violet Moon Signing Key" --armor \ --detach-sign ${{ steps.calculate_artifact_names.outputs.fabric }} - - name: Archive Forge Artifacts - uses: actions/upload-artifact@v2 + - name: Archive NeoForge Artifacts + uses: actions/upload-artifact@v4 with: - name: Forge + name: NeoForge path: | - ${{ steps.calculate_artifact_names.outputs.forge }} - ${{ steps.calculate_artifact_names.outputs.forge }}.asc + ${{ steps.calculate_artifact_names.outputs.neoforge }} + ${{ steps.calculate_artifact_names.outputs.neoforge }}.asc - name: Archive Fabric Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: Fabric path: | @@ -67,7 +67,7 @@ jobs: GH_TOKEN: ${{ github.token }} GIT_REF: ${{ github.ref }} FABRIC_JAR: ${{ steps.calculate_artifact_names.outputs.fabric }} - FORGE_JAR: ${{ steps.calculate_artifact_names.outputs.forge }} + NEOFORGE_JAR: ${{ steps.calculate_artifact_names.outputs.neoforge }} CURSEFORGE_TOKEN: ${{ secrets.VAZKII_CURSEFORGE_TOKEN }} MODRINTH_TOKEN: ${{ secrets.VAZKII_MODRINTH_TOKEN }} run: | diff --git a/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java b/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java index d15fe2b..55cf6ba 100644 --- a/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java +++ b/Fabric/src/main/java/vazkii/neat/NeatFiberConfig.java @@ -54,6 +54,7 @@ public static void setup() { private static class Client implements NeatConfig.ConfigAccess { private final PropertyMirror maxDistance = PropertyMirror.create(INTEGER); + private final PropertyMirror maxDistanceWithoutLineOfSight = PropertyMirror.create(INTEGER); private final PropertyMirror renderInF1 = PropertyMirror.create(BOOLEAN); private final PropertyMirror heightAbove = PropertyMirror.create(DOUBLE); private final PropertyMirror drawBackground = PropertyMirror.create(BOOLEAN); @@ -66,15 +67,24 @@ private static class Client implements NeatConfig.ConfigAccess { private final PropertyMirror showArmor = PropertyMirror.create(BOOLEAN); private final PropertyMirror groupArmor = PropertyMirror.create(BOOLEAN); private final PropertyMirror colorByType = PropertyMirror.create(BOOLEAN); + private final PropertyMirror textColor = PropertyMirror.create(STRING); private final PropertyMirror hpTextHeight = PropertyMirror.create(INTEGER); private final PropertyMirror showMaxHP = PropertyMirror.create(BOOLEAN); private final PropertyMirror showCurrentHP = PropertyMirror.create(BOOLEAN); private final PropertyMirror showPercentage = PropertyMirror.create(BOOLEAN); + private final PropertyMirror showOnPassive = PropertyMirror.create(BOOLEAN); + private final PropertyMirror showOnHostile = PropertyMirror.create(BOOLEAN); private final PropertyMirror showOnPlayers = PropertyMirror.create(BOOLEAN); private final PropertyMirror showOnBosses = PropertyMirror.create(BOOLEAN); private final PropertyMirror showOnlyFocused = PropertyMirror.create(BOOLEAN); private final PropertyMirror showFullHealth = PropertyMirror.create(BOOLEAN); 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) { @@ -82,12 +92,16 @@ public ConfigTree configure(ConfigTreeBuilder builder) { .withComment("Maximum distance in blocks at which health bars should render") .finishValue(maxDistance::mirror) + .beginValue("maxDistanceWithoutLineOfSight", INTEGER, 8) + .withComment("Maximum distance in blocks at which health bars should render without line of sight") + .finishValue(maxDistanceWithoutLineOfSight::mirror) + .beginValue("renderInF1", BOOLEAN, false) .withComment("Whether health bars should render when the HUD is disabled with F1") .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) @@ -127,9 +141,13 @@ 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") + .withComment("Text color in hex code format") + .finishValue(textColor::mirror) + .beginValue("hpTextHeight", INTEGER, 14) .withComment("Height of the text on the health bar") .finishValue(hpTextHeight::mirror) @@ -146,6 +164,14 @@ public ConfigTree configure(ConfigTreeBuilder builder) { .withComment("Whether the percentage health of the mob should be shown") .finishValue(showPercentage::mirror) + .beginValue("showOnPassive", BOOLEAN, true) + .withComment("Whether bars on passive mobs should be shown") + .finishValue(showOnPassive::mirror) + + .beginValue("showOnHostile", BOOLEAN, true) + .withComment("Whether bars on hostile mobs should be shown (does not include bosses)") + .finishValue(showOnHostile::mirror) + .beginValue("showOnPlayers", BOOLEAN, true) .withComment("Whether bars on players should be shown") .finishValue(showOnPlayers::mirror) @@ -166,6 +192,30 @@ public ConfigTree configure(ConfigTreeBuilder builder) { .withComment("Show extra debug info on the bar when F3 is enabled") .finishValue(enableDebugInfo::mirror) + .beginValue("showEntityName", BOOLEAN, true) + .withComment("Show entity name") + .finishValue(showEntityName::mirror) + + .beginValue("disableNameTag", BOOLEAN, false) + .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); @@ -178,6 +228,11 @@ public int maxDistance() { return maxDistance.getValue(); } + @Override + public int maxDistanceWithoutLineOfSight() { + return maxDistanceWithoutLineOfSight.getValue(); + } + @Override public boolean renderInF1() { return renderInF1.getValue(); @@ -238,6 +293,11 @@ public boolean colorByType() { return colorByType.getValue(); } + @Override + public String textColor() { + return textColor.getValue(); + } + @Override public int hpTextHeight() { return hpTextHeight.getValue(); @@ -258,6 +318,16 @@ public boolean showPercentage() { return showPercentage.getValue(); } + @Override + public boolean showOnPassive() { + return showOnPassive.getValue(); + } + + @Override + public boolean showOnHostile() { + return showOnHostile.getValue(); + } + @Override public boolean showOnPlayers() { return showOnPlayers.getValue(); @@ -283,6 +353,36 @@ public boolean enableDebugInfo() { return enableDebugInfo.getValue(); } + @Override + public boolean showEntityName() { + return showEntityName.getValue(); + } + + @Override + 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/NeoForge/build.gradle b/NeoForge/build.gradle index 64fc1ea..935ec9b 100644 --- a/NeoForge/build.gradle +++ b/NeoForge/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java-library' id 'idea' - id 'net.neoforged.gradle.userdev' + id 'net.neoforged.gradle.userdev' version '7.0.165' id 'eclipse' } @@ -27,6 +27,12 @@ runs { } } +repositories { + maven { + url "https://cursemaven.com" + } +} + dependencies { implementation "net.neoforged:neoforge:${neoforge_version}" implementation project(":Xplat") diff --git a/NeoForge/src/main/java/vazkii/neat/NeatForgeConfig.java b/NeoForge/src/main/java/vazkii/neat/NeatForgeConfig.java deleted file mode 100644 index a17b97f..0000000 --- a/NeoForge/src/main/java/vazkii/neat/NeatForgeConfig.java +++ /dev/null @@ -1,193 +0,0 @@ -package vazkii.neat; - - -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModLoadingContext; -import net.neoforged.fml.config.ModConfig; -import net.neoforged.neoforge.common.ModConfigSpec; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.List; - -public class NeatForgeConfig { - public static void init(ModContainer container) { - Pair specPair = new ModConfigSpec.Builder().configure(ForgeNeatConfig::new); - NeatConfig.instance = specPair.getLeft(); - container.registerConfig(ModConfig.Type.CLIENT, specPair.getRight()); - //TODO consider using the build-in config ui of neoforge - } - - private static class ForgeNeatConfig implements NeatConfig.ConfigAccess { - private final ModConfigSpec.ConfigValue maxDistance; - private final ModConfigSpec.ConfigValue renderInF1; - private final ModConfigSpec.ConfigValue heightAbove; - private final ModConfigSpec.ConfigValue drawBackground; - private final ModConfigSpec.ConfigValue backgroundPadding; - private final ModConfigSpec.ConfigValue backgroundHeight; - private final ModConfigSpec.ConfigValue barHeight; - private final ModConfigSpec.ConfigValue plateSize; - private final ModConfigSpec.ConfigValue plateSizeBoss; - private final ModConfigSpec.ConfigValue showAttributes; - private final ModConfigSpec.ConfigValue showArmor; - private final ModConfigSpec.ConfigValue groupArmor; - private final ModConfigSpec.ConfigValue colorByType; - private final ModConfigSpec.ConfigValue hpTextHeight; - private final ModConfigSpec.ConfigValue showMaxHP; - private final ModConfigSpec.ConfigValue showCurrentHP; - private final ModConfigSpec.ConfigValue showPercentage; - private final ModConfigSpec.ConfigValue showOnPlayers; - private final ModConfigSpec.ConfigValue showOnBosses; - private final ModConfigSpec.ConfigValue showOnlyFocused; - private final ModConfigSpec.ConfigValue showFullHealth; - private final ModConfigSpec.ConfigValue enableDebugInfo; - private final ModConfigSpec.ConfigValue> blacklist; - - public ForgeNeatConfig(ModConfigSpec.Builder builder) { - builder.push("general"); - - maxDistance = builder.define("max_distance", 24); - renderInF1 = builder.comment("Render if F1 is pressed").define("render_without_gui", 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.comment("Condense 5 iron icons into 1 diamond icon").define("group_armor", true); - colorByType = builder.comment("Color health bar by type instead of health percentage").define("color_health_bar_by_type", false); - 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); - showOnPlayers = builder.define("display_on_players", true); - showOnBosses = builder.define("display_on_bosses", true); - showOnlyFocused = builder.define("only_health_bar_for_target", false); - showFullHealth = builder.define("show_entity_full_health", true); - enableDebugInfo = builder.define("show_debug_with_f3", true); - 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); - - builder.pop(); - } - - @Override - public int maxDistance() { - return maxDistance.get(); - } - - @Override - public boolean renderInF1() { - return renderInF1.get(); - } - - @Override - public double heightAbove() { - return heightAbove.get(); - } - - @Override - public boolean drawBackground() { - return drawBackground.get(); - } - - @Override - public int backgroundPadding() { - return backgroundPadding.get(); - } - - @Override - public int backgroundHeight() { - return backgroundHeight.get(); - } - - @Override - public int barHeight() { - return barHeight.get(); - } - - @Override - public int plateSize() { - return plateSize.get(); - } - - @Override - public int plateSizeBoss() { - return plateSizeBoss.get(); - } - - @Override - public boolean showAttributes() { - return showAttributes.get(); - } - - @Override - public boolean showArmor() { - return showArmor.get(); - } - - @Override - public boolean groupArmor() { - return groupArmor.get(); - } - - @Override - public boolean colorByType() { - return colorByType.get(); - } - - @Override - public int hpTextHeight() { - return hpTextHeight.get(); - } - - @Override - public boolean showMaxHP() { - return showMaxHP.get(); - } - - @Override - public boolean showCurrentHP() { - return showCurrentHP.get(); - } - - @Override - public boolean showPercentage() { - return showPercentage.get(); - } - - @Override - public boolean showOnPlayers() { - return showOnPlayers.get(); - } - - @Override - public boolean showOnBosses() { - return showOnBosses.get(); - } - - @Override - public boolean showOnlyFocused() { - return showOnlyFocused.get(); - } - - @Override - public boolean showFullHealth() { - return showFullHealth.get(); - } - - @Override - public boolean enableDebugInfo() { - return enableDebugInfo.get(); - } - - @SuppressWarnings("unchecked") - @Override - public List blacklist() { - // Safe cast from List to List, as String is final - return (List) blacklist.get(); - } - } -} diff --git a/NeoForge/src/main/java/vazkii/neat/NeatForgeInitializer.java b/NeoForge/src/main/java/vazkii/neat/NeatForgeInitializer.java deleted file mode 100644 index 48b86e3..0000000 --- a/NeoForge/src/main/java/vazkii/neat/NeatForgeInitializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package vazkii.neat; - -import net.neoforged.bus.api.IEventBus; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModLoadingContext; -import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.common.Mod; - -@Mod(NeatConfig.MOD_ID) -public class NeatForgeInitializer { - - public NeatForgeInitializer(IEventBus bus, ModContainer modContainer) { - //ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (incoming, isNetwork) -> true)); - NeatForgeConfig.init(modContainer); - } - -} diff --git a/NeoForge/src/main/java/vazkii/neat/NeatNeoForgeConfig.java b/NeoForge/src/main/java/vazkii/neat/NeatNeoForgeConfig.java new file mode 100644 index 0000000..46f168a --- /dev/null +++ b/NeoForge/src/main/java/vazkii/neat/NeatNeoForgeConfig.java @@ -0,0 +1,261 @@ +package vazkii.neat; + +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.config.ModConfig; +import net.neoforged.neoforge.common.ModConfigSpec; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +public class NeatNeoForgeConfig { + public static void init(ModContainer container) { + Pair specPair = new ModConfigSpec.Builder().configure(ForgeNeatConfig::new); + NeatConfig.instance = specPair.getLeft(); + container.registerConfig(ModConfig.Type.CLIENT, specPair.getRight()); + } + + private static class ForgeNeatConfig implements NeatConfig.ConfigAccess { + private final ModConfigSpec.ConfigValue maxDistance; + private final ModConfigSpec.ConfigValue maxDistanceWithoutLineOfSight; + private final ModConfigSpec.ConfigValue renderInF1; + private final ModConfigSpec.ConfigValue heightAbove; + private final ModConfigSpec.ConfigValue drawBackground; + private final ModConfigSpec.ConfigValue backgroundPadding; + private final ModConfigSpec.ConfigValue backgroundHeight; + private final ModConfigSpec.ConfigValue barHeight; + private final ModConfigSpec.ConfigValue plateSize; + private final ModConfigSpec.ConfigValue plateSizeBoss; + private final ModConfigSpec.ConfigValue showAttributes; + private final ModConfigSpec.ConfigValue showArmor; + private final ModConfigSpec.ConfigValue groupArmor; + private final ModConfigSpec.ConfigValue colorByType; + private final ModConfigSpec.ConfigValue textColor; + private final ModConfigSpec.ConfigValue hpTextHeight; + private final ModConfigSpec.ConfigValue showMaxHP; + private final ModConfigSpec.ConfigValue showCurrentHP; + private final ModConfigSpec.ConfigValue showPercentage; + private final ModConfigSpec.ConfigValue showOnPassive; + private final ModConfigSpec.ConfigValue showOnHostile; + private final ModConfigSpec.ConfigValue showOnPlayers; + private final ModConfigSpec.ConfigValue showOnBosses; + private final ModConfigSpec.ConfigValue showOnlyFocused; + private final ModConfigSpec.ConfigValue showFullHealth; + private final ModConfigSpec.ConfigValue showEntityName; + private final ModConfigSpec.ConfigValue disableNameTag; + private final ModConfigSpec.ConfigValue disableNameTagIfHealthbar; + private final ModConfigSpec.ConfigValue iconOffsetX; + private final ModConfigSpec.ConfigValue iconOffsetY; + private final ModConfigSpec.ConfigValue decimalFormat; + private final ModConfigSpec.ConfigValue enableDebugInfo; + private final ModConfigSpec.ConfigValue> blacklist; + + public ForgeNeatConfig(ModConfigSpec.Builder builder) { + builder.push("general"); + + 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.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); + + builder.pop(); + } + + @Override + public int maxDistance() { + return maxDistance.get(); + } + + @Override + public int maxDistanceWithoutLineOfSight() { + return maxDistanceWithoutLineOfSight.get(); + } + + @Override + public boolean renderInF1() { + return renderInF1.get(); + } + + @Override + public double heightAbove() { + return heightAbove.get(); + } + + @Override + public boolean drawBackground() { + return drawBackground.get(); + } + + @Override + public int backgroundPadding() { + return backgroundPadding.get(); + } + + @Override + public int backgroundHeight() { + return backgroundHeight.get(); + } + + @Override + public int barHeight() { + return barHeight.get(); + } + + @Override + public int plateSize() { + return plateSize.get(); + } + + @Override + public int plateSizeBoss() { + return plateSizeBoss.get(); + } + + @Override + public boolean showAttributes() { + return showAttributes.get(); + } + + @Override + public boolean showArmor() { + return showArmor.get(); + } + + @Override + public boolean groupArmor() { + return groupArmor.get(); + } + + @Override + public boolean colorByType() { + return colorByType.get(); + } + + @Override + public String textColor() { + return textColor.get(); + } + + @Override + public int hpTextHeight() { + return hpTextHeight.get(); + } + + @Override + public boolean showMaxHP() { + return showMaxHP.get(); + } + + @Override + public boolean showCurrentHP() { + return showCurrentHP.get(); + } + + @Override + public boolean showPercentage() { + return showPercentage.get(); + } + + @Override + public boolean showOnPassive() { + return showOnPassive.get(); + } + + @Override + public boolean showOnHostile() { + return showOnHostile.get(); + } + + @Override + public boolean showOnPlayers() { + return showOnPlayers.get(); + } + + @Override + public boolean showOnBosses() { + return showOnBosses.get(); + } + + @Override + public boolean showOnlyFocused() { + return showOnlyFocused.get(); + } + + @Override + public boolean showFullHealth() { + return showFullHealth.get(); + } + + @Override + public boolean enableDebugInfo() { + return enableDebugInfo.get(); + } + + @Override + public boolean showEntityName() { + return showEntityName.get(); + } + + @Override + 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() { + // Safe cast from List to List, as String is final + return (List) blacklist.get(); + } + } +} diff --git a/NeoForge/src/main/java/vazkii/neat/NeatNeoForgeInitializer.java b/NeoForge/src/main/java/vazkii/neat/NeatNeoForgeInitializer.java new file mode 100644 index 0000000..9683598 --- /dev/null +++ b/NeoForge/src/main/java/vazkii/neat/NeatNeoForgeInitializer.java @@ -0,0 +1,15 @@ +package vazkii.neat; + +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; + +@Mod(NeatConfig.MOD_ID) +public class NeatNeoForgeInitializer { + + public NeatNeoForgeInitializer(IEventBus bus, ModContainer modContainer) { + //ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (incoming, isNetwork) -> true)); + NeatNeoForgeConfig.init(modContainer); + } + +} diff --git a/NeoForge/src/main/java/vazkii/neat/NeatNeoforgeClient.java b/NeoForge/src/main/java/vazkii/neat/NeatNeoforgeClient.java index 3e617a6..19d2f5e 100644 --- a/NeoForge/src/main/java/vazkii/neat/NeatNeoforgeClient.java +++ b/NeoForge/src/main/java/vazkii/neat/NeatNeoforgeClient.java @@ -14,12 +14,12 @@ @EventBusSubscriber(modid = NeatConfig.MOD_ID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public class NeatNeoforgeClient { - public NeatNeoforgeClient(IEventBus bus, ModContainer modContainer) { - modContainer.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new); - } + public NeatNeoforgeClient(IEventBus bus, ModContainer modContainer) { + modContainer.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new); + } - @SubscribeEvent - public static void registerKey(RegisterKeyMappingsEvent event) { - event.register(ToggleKeybind.KEY); - } + @SubscribeEvent + public static void registerKey(RegisterKeyMappingsEvent event) { + event.register(ToggleKeybind.KEY); + } } diff --git a/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java b/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java index f98d6ac..e82efa7 100644 --- a/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java +++ b/Xplat/src/main/java/vazkii/neat/HealthBarRenderer.java @@ -4,10 +4,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.RenderType; +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; @@ -18,7 +19,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; @@ -30,13 +30,10 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.Team; -import org.joml.Quaternionf; - import java.text.DecimalFormat; import java.util.*; public class HealthBarRenderer { - private static final DecimalFormat HEALTH_FORMAT = new DecimalFormat("#.##"); private static Entity getEntityLookedAt(Entity e) { Entity foundEntity = null; @@ -99,6 +96,8 @@ private static ItemStack getIcon(LivingEntity entity, boolean boss) { return new ItemStack(Items.SPIDER_EYE); } else if (type.is(EntityTypeTags.UNDEAD)) { return new ItemStack(Items.ROTTEN_FLESH); + } else if (type.is(EntityTypeTags.ILLAGER)) { + return new ItemStack(Items.IRON_AXE); } else { return ItemStack.EMPTY; } @@ -113,11 +112,9 @@ private static int getColor(LivingEntity entity, boolean colorByType, boolean bo r = 128; g = 0; b = 128; - } - if (entity instanceof Monster) { + } else if (!entity.getType().getCategory().isFriendly()) { r = 255; g = 0; - b = 0; } return 0xff000000 | r << 16 | g << 8 | b; } else { @@ -127,14 +124,11 @@ private static int getColor(LivingEntity entity, boolean colorByType, boolean bo } } - private static final TagKey> FORGE_BOSS_TAG = - TagKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath("forge", "bosses")); - - private static final TagKey> FABRIC_BOSS_TAG = + private static final TagKey> BOSS_TAG = TagKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath("c", "bosses")); - private static boolean isBoss(Entity entity) { - return entity.getType().is(FORGE_BOSS_TAG) || entity.getType().is(FABRIC_BOSS_TAG); + public static boolean isBoss(Entity entity) { + return entity.getType().is(BOSS_TAG); } private static boolean shouldShowPlate(LivingEntity living, Entity cameraEntity) { @@ -153,7 +147,8 @@ private static boolean shouldShowPlate(LivingEntity living, Entity cameraEntity) float distance = living.distanceTo(cameraEntity); if (distance > NeatConfig.instance.maxDistance() - || !living.hasLineOfSight(cameraEntity)) { + || (distance > NeatConfig.instance.maxDistanceWithoutLineOfSight() + && !living.hasLineOfSight(cameraEntity))) { return false; } if (!NeatConfig.instance.showOnBosses() && isBoss(living)) { @@ -168,10 +163,34 @@ private static boolean shouldShowPlate(LivingEntity living, Entity cameraEntity) if (NeatConfig.instance.showOnlyFocused() && getEntityLookedAt(cameraEntity) != living) { return false; } + if (!NeatConfig.instance.showOnPassive() && living.getType().getCategory().isFriendly()) { + return false; + } + if (!NeatConfig.instance.showOnHostile() && (!living.getType().getCategory().isFriendly() && !isBoss(living))) { + return false; + } + + if (living.hasPassenger(cameraEntity)) { + return false; + } boolean visible = true; - if (cameraEntity instanceof Player cameraPlayer) { - visible = !living.isInvisibleTo(cameraPlayer); + if (cameraEntity instanceof Player cameraPlayer + && living.isInvisibleTo(cameraPlayer)) { + boolean wearingThings = false; + for (ItemStack armorSlot : living.getArmorSlots()) { + if (!armorSlot.isEmpty()) { + wearingThings = true; + } + } + for (ItemStack handSlot : living.getHandSlots()) { + if (!handSlot.isEmpty()) { + wearingThings = true; + } + } + if (!wearingThings) { + visible = false; + } } Team livingTeam = living.getTeam(); Team cameraTeam = cameraEntity.getTeam(); @@ -188,15 +207,14 @@ 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) || (!living.getPassengers().isEmpty() && living.getPassengers().get(0) instanceof LivingEntity)) { - // TODO handle mob stacks properly + if (!(entity instanceof LivingEntity living)) { return; } - - if (!shouldShowPlate(living, mc.gameRenderer.getMainCamera().getEntity())) { + //This was previously mc.gameRenderer.getMainCamera().getEntity() but that caused an incompatibility with RealCamera + if (!shouldShowPlate(living, camera.getEntity())) { return; } @@ -212,23 +230,29 @@ 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()); poseStack.mulPose(Axis.YP.rotationDegrees(180)); // Plate background, bars, and text operate with globalScale, but icons don't poseStack.pushPose(); poseStack.scale(-globalScale, -globalScale, globalScale); - VertexConsumer builder = buffers.getBuffer(NeatRenderType.BAR_TEXTURE_TYPE); - // Background if (NeatConfig.instance.drawBackground()) { float padding = NeatConfig.instance.backgroundPadding(); int bgHeight = NeatConfig.instance.backgroundHeight(); - - + if (!NeatConfig.instance.showEntityName()) { + bgHeight -= (int) 4F; + } + VertexConsumer builder = buffers.getBuffer(NeatRenderType.BAR_TEXTURE_TYPE); builder.addVertex(poseStack.last().pose(), -halfSize - padding, -bgHeight, 0.01F).setColor(0, 0, 0, 60).setUv(0.0F, 0.0F).setLight(light); builder.addVertex(poseStack.last().pose(), -halfSize - padding, barHeight + padding, 0.01F).setColor(0, 0, 0, 60).setUv(0.0F, 0.5F).setLight(light); builder.addVertex(poseStack.last().pose(), halfSize + padding, barHeight + padding, 0.01F).setColor(0, 0, 0, 60).setUv(1.0F, 0.5F).setLight(light); @@ -246,8 +270,7 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou float maxHealth = Math.max(living.getHealth(), living.getMaxHealth()); float healthHalfSize = halfSize * (living.getHealth() / maxHealth); - //VertexConsumer builder = buffers.getBuffer(NeatRenderType.BAR_TEXTURE_TYPE); - //VertexConsumer builder = buffers.getBuffer(RenderType.LINES); + VertexConsumer builder = buffers.getBuffer(NeatRenderType.BAR_TEXTURE_TYPE); builder.addVertex(poseStack.last().pose(), -halfSize, 0, 0.001F).setColor(r, g, b, 127).setUv(0.0F, 0.75F).setLight(light); builder.addVertex(poseStack.last().pose(), -halfSize, barHeight, 0.001F).setColor(r, g, b, 127).setUv(0.0F, 1.0F).setLight(light); builder.addVertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, barHeight, 0.001F).setColor(r, g, b, 127).setUv(1.0F, 1.0F).setLight(light); @@ -264,16 +287,18 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou // Text { - final int white = 0xFFFFFF; + final int textColor = HexFormat.fromHexDigits(NeatConfig.instance.textColor()); final int black = 0; // Name { - poseStack.pushPose(); - poseStack.translate(-halfSize, -4.5F, 0F); - poseStack.scale(textScale, textScale, textScale); - mc.font.drawInBatch(name, 0, 0, white, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); - poseStack.popPose(); + if (NeatConfig.instance.showEntityName()) { + poseStack.pushPose(); + poseStack.translate(-halfSize, -4.5F, 0F); + poseStack.scale(textScale, textScale, textScale); + mc.font.drawInBatch(name, 0, 0, textColor, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); + poseStack.popPose(); + } } // Health values (and debug ID) @@ -284,22 +309,23 @@ 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()); - mc.font.drawInBatch(hpStr, 2, h, white, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); + 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()); - mc.font.drawInBatch(maxHpStr, (int) (halfSize / healthValueTextScale * 2) - mc.font.width(maxHpStr) - 2, h, white, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); + 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()) { String percStr = (int) (100 * living.getHealth() / living.getMaxHealth()) + "%"; - mc.font.drawInBatch(percStr, (int) (halfSize / healthValueTextScale) - mc.font.width(percStr) / 2.0F, h, white, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); + mc.font.drawInBatch(percStr, (int) (halfSize / healthValueTextScale) - mc.font.width(percStr) / 2.0F, h, textColor, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); } if (NeatConfig.instance.enableDebugInfo() && mc.getDebugOverlay().showDebugScreen()) { var id = BuiltInRegistries.ENTITY_TYPE.getKey(living.getType()); - mc.font.drawInBatch("ID: \"" + id + "\"", 0, h + 16, white, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); + mc.font.drawInBatch("ID: \"" + id + "\"", 0, h + 16, textColor, false, poseStack.last().pose(), buffers, Font.DisplayMode.NORMAL, black, light); } poseStack.popPose(); } @@ -362,11 +388,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 467b61c..5d05417 100644 --- a/Xplat/src/main/java/vazkii/neat/NeatConfig.java +++ b/Xplat/src/main/java/vazkii/neat/NeatConfig.java @@ -9,6 +9,7 @@ public class NeatConfig { public interface ConfigAccess { int maxDistance(); + int maxDistanceWithoutLineOfSight(); boolean renderInF1(); double heightAbove(); boolean drawBackground(); @@ -21,19 +22,28 @@ public interface ConfigAccess { boolean showArmor(); boolean groupArmor(); boolean colorByType(); + String textColor(); int hpTextHeight(); boolean showMaxHP(); boolean showCurrentHP(); boolean showPercentage(); + boolean showOnPassive(); + boolean showOnHostile(); boolean showOnPlayers(); boolean showOnBosses(); boolean showOnlyFocused(); boolean showFullHealth(); boolean enableDebugInfo(); + boolean showEntityName(); + boolean disableNameTag(); + boolean disableNameTagIfHealthbar(); + double iconOffsetX(); + double iconOffsetY(); + String decimalFormat(); List blacklist(); } - public static final List DEFAULT_DISABLED = List.of("minecraft:shulker", "minecraft:armor_stand", "minecraft:cod", "minecraft:salmon", "minecraft:pufferfish", "minecraft:tropical_fish"); + public static final List DEFAULT_DISABLED = List.of("minecraft:shulker", "minecraft:armor_stand", "minecraft:cod", "minecraft:salmon", "minecraft:pufferfish", "minecraft:tropical_fish", "minecraft:tadpole"); public static ConfigAccess instance; } 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 new file mode 100644 index 0000000..daf36e9 --- /dev/null +++ b/Xplat/src/main/java/vazkii/neat/mixin/EntityRendererMixin.java @@ -0,0 +1,47 @@ +package vazkii.neat.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; + +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;IF)V"), cancellable = true) + 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..60716b7 --- /dev/null +++ b/Xplat/src/main/java/vazkii/neat/mixin/LevelRendererMixin.java @@ -0,0 +1,44 @@ +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/assets/neat/lang/en_us.json b/Xplat/src/main/resources/assets/neat/lang/en_us.json index 502d6c7..a071d40 100644 --- a/Xplat/src/main/resources/assets/neat/lang/en_us.json +++ b/Xplat/src/main/resources/assets/neat/lang/en_us.json @@ -23,5 +23,15 @@ "neat.configuration.show_attributes": "Show Attributes", "neat.configuration.color_health_bar_by_type": "Color Health Bar by Type", "neat.configuration.show_current_hp": "Show Current HP", + "neat.configuration.disable_name_tag": "Disable Name Tag", + "neat.configuration.show_on_hostile": "Show on Hostile", + "neat.configuration.text_color": "Text Color", + "neat.configuration.disable_name_tag_if_healthbar": "Disable Name Tag if Healthbar rendered", + "neat.configuration.max_distance_without_line_of_sight": "Max distance without LOS", + "neat.configuration.show_entity_name": "Show Entity Name", + "neat.configuration.icon_offset_y": "Icon Offset Y", + "neat.configuration.decimal_format": "Decimal Format", + "neat.configuration.show_on_passive": "Show on Passive", + "neat.configuration.icon_offset_x": "Icon Offset X", "neat.configuration.blacklist": "Blacklist" } diff --git a/Xplat/src/main/resources/neat.mixins.json b/Xplat/src/main/resources/neat.mixins.json index bf08bd7..1081d02 100644 --- a/Xplat/src/main/resources/neat.mixins.json +++ b/Xplat/src/main/resources/neat.mixins.json @@ -7,7 +7,8 @@ ], "client": [ "AccessorRenderType", - "EntityRenderDispatcherMixin", + "EntityRendererMixin", + "LevelRendererMixin", "MinecraftMixin" ], "injectors": { diff --git a/build.gradle b/build.gradle index 577f512..cbe53be 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.diffplug.spotless' version '5.12.5' apply false + id 'com.diffplug.spotless' version '6.25.0' apply false id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" } diff --git a/gradle.properties b/gradle.properties index 05a9578..a67fe9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,8 +8,8 @@ org.gradle.jvmargs=-Xmx2G \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED group=vazkii.neat -neoforge_version=21.1.1 +neoforge_version=21.1.63 mod_id=neat -build_number=36 +build_number=41 mod_name=Neat mc_version=1.21 diff --git a/scripts/upload_releases.sh b/scripts/upload_releases.sh index 6a96d07..741f604 100755 --- a/scripts/upload_releases.sh +++ b/scripts/upload_releases.sh @@ -22,9 +22,9 @@ function release_github() { echo >&2 'Uploading Fabric Jar and Signature to GitHub' gh release upload "${TAGNAME}" "${FABRIC_JAR}#Fabric Jar" gh release upload "${TAGNAME}" "${FABRIC_JAR}.asc#Fabric Signature" - echo >&2 'Uploading Forge Jar and Signature to GitHub' - gh release upload "${TAGNAME}" "${FORGE_JAR}#Forge Jar" - gh release upload "${TAGNAME}" "${FORGE_JAR}.asc#Forge Signature" + echo >&2 'Uploading NeoForge Jar and Signature to GitHub' + gh release upload "${TAGNAME}" "${NEOFORGE_JAR}#NeoForge Jar" + gh release upload "${TAGNAME}" "${NEOFORGE_JAR}.asc#Forge Signature" } function release_modrinth() { @@ -60,13 +60,13 @@ EOF -F "data=$MODRINTH_FABRIC_SPEC" \ -F "jar=@${FABRIC_JAR}" # TODO modrinth doesn't allow asc files. Remember to readd "signature" to the spec when reenabling this. \ -F "signature=@${FABRIC_JAR}.asc" - echo >&2 'Uploading Forge Jar to Modrinth' - local MODRINTH_FORGE_SPEC - MODRINTH_FORGE_SPEC=$(cat <&2 'Uploading NeoForge Jar to Modrinth' + local MODRINTH_NEOFORGE_SPEC + MODRINTH_NEOFORGE_SPEC=$(cat <&2 'Uploading Forge Jar to CurseForge' - local CURSEFORGE_FORGE_SPEC - CURSEFORGE_FORGE_SPEC=$(cat <