Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HealthTags improvements #801

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
92a7c79
HealthTags for mobs
ThisTestUser Mar 17, 2023
36c1044
Update RenderUtils.java
ThisTestUser Mar 17, 2023
1082575
Merge branch 'master' into mobhealthtags
Alexander01998 Mar 21, 2023
d5cd0eb
Display max health for players option
ThisTestUser May 28, 2023
686526d
Unlimited range for mob health tags
ThisTestUser May 28, 2023
f0ba058
Fix range overflowing
ThisTestUser May 28, 2023
edd26ae
Use double for height offset
ThisTestUser Jun 5, 2023
ae5ee29
Clean up
ThisTestUser Jun 5, 2023
cd0ca73
Cleanup
ThisTestUser Jun 7, 2023
cda75f9
Merge branch 'master' into mobhealthtags
ThisTestUser Oct 22, 2023
87955b1
Merge branch 'master' into pr/ThisTestUser/801
Alexander01998 Dec 22, 2023
c1d374b
Clean up
Alexander01998 Dec 22, 2023
5a9db98
Let NameTags handle the unlimited range option
Alexander01998 Dec 22, 2023
5307b2a
Refactor max health setting and display logic
Alexander01998 Dec 23, 2023
2c3cc80
Fix inconsistent number formatting
Alexander01998 Dec 23, 2023
684692f
Replace rounding checkbox with precision slider
Alexander01998 Dec 23, 2023
8c90791
Add validation for minimum value in RoundingPrecisionSetting
Alexander01998 Dec 23, 2023
92703c5
Remove unused hasMobHealthTags() method for now
Alexander01998 Dec 23, 2023
5cb8d27
Partially refactor renderTag() method
Alexander01998 Dec 26, 2023
ed1cb1f
Year update
ThisTestUser Jan 2, 2024
31022d1
Merge branch 'master' into mobhealthtags
ThisTestUser Mar 4, 2024
f9c5533
Merge branch 'master' into mobhealthtags
Alexander01998 Apr 4, 2024
305f0b6
Merge branch 'master' into mobhealthtags
ThisTestUser Oct 1, 2024
93149e4
Fix issues with mobhealthtags
ThisTestUser Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 75 additions & 10 deletions src/main/java/net/wurstclient/hacks/HealthTagsHack.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,109 @@
*/
package net.wurstclient.hacks;

import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.wurstclient.Category;
import net.wurstclient.SearchTags;
import net.wurstclient.events.RenderListener;
import net.wurstclient.hack.Hack;
import net.wurstclient.settings.CheckboxSetting;
import net.wurstclient.settings.RoundingPrecisionSetting;
import net.wurstclient.util.RenderUtils;

@SearchTags({"health tags"})
public final class HealthTagsHack extends Hack
public final class HealthTagsHack extends Hack implements RenderListener
{
private final CheckboxSetting mobs = new CheckboxSetting("Mobs",
"Displays health tags above mobs also.", false);

private final CheckboxSetting showMaxHealth =
new CheckboxSetting("Show max health", "Also displays the entity's"
+ " maximum health in addition to its current health.", false);

private final RoundingPrecisionSetting precision =
new RoundingPrecisionSetting("Precision",
"Rounds the health value to the given number of decimal places.", 0,
0, 3);
Alexander01998 marked this conversation as resolved.
Show resolved Hide resolved

public HealthTagsHack()
{
super("HealthTags");
setCategory(Category.RENDER);
addSetting(mobs);
addSetting(showMaxHealth);
addSetting(precision);
}

@Override
public void onEnable()
{
EVENTS.add(RenderListener.class, this);
}

@Override
public void onDisable()
{
EVENTS.remove(RenderListener.class, this);
}

public Text addHealth(LivingEntity entity, Text nametag)
@Override
public void onRender(MatrixStack matrixStack, float partialTicks)
{
if(!mobs.isChecked())
return;

VertexConsumerProvider.Immediate immediate = VertexConsumerProvider
.immediate(Tessellator.getInstance().getBuffer());

for(Entity e : MC.world.getEntities())
{
if(!(e instanceof MobEntity entity))
continue;

Text text = addHealth(entity, Text.literal(""));
RenderUtils.renderTag(matrixStack, text, entity, immediate,
0xffffff, !entity.hasCustomName() ? 0.5 : 1, partialTicks);
}

immediate.draw();
}
Alexander01998 marked this conversation as resolved.
Show resolved Hide resolved

public Text addHealth(LivingEntity entity, MutableText nametag)
{
if(!isEnabled())
return nametag;

int health = (int)entity.getHealth();
float health = entity.getHealth();
float maxHealth = entity.getMaxHealth();
Formatting color = getColor(health, maxHealth);

String healthString = precision.format(health);
if(showMaxHealth.isChecked())
healthString += "/" + precision.format(maxHealth);

Alexander01998 marked this conversation as resolved.
Show resolved Hide resolved
if(!nametag.getString().isEmpty())
nametag = nametag.append(Text.literal(" "));

MutableText formattedHealth = Text.literal(" ")
.append(Integer.toString(health)).formatted(getColor(health));
return ((MutableText)nametag).append(formattedHealth);
return nametag.append(Text.literal(healthString).formatted(color));
}

private Formatting getColor(int health)
private Formatting getColor(float health, float maxHealth)
{
if(health <= 5)
if(health <= maxHealth * 0.25)
return Formatting.DARK_RED;

if(health <= 10)
if(health <= maxHealth * 0.5)
return Formatting.GOLD;

if(health <= 15)
if(health <= maxHealth * 0.75)
return Formatting.YELLOW;

return Formatting.GREEN;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/wurstclient/mixin/EntityRendererMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.wurstclient.WurstClient;
import net.wurstclient.hacks.NameTagsHack;
Expand All @@ -44,7 +45,7 @@ private void onRenderLabelIfPresent(T entity, Text text,
// add HealthTags info
if(entity instanceof LivingEntity)
text = WurstClient.INSTANCE.getHax().healthTagsHack
.addHealth((LivingEntity)entity, text);
.addHealth((LivingEntity)entity, (MutableText)text);

// do NameTags adjustments
wurstRenderLabelIfPresent(entity, text, matrixStack,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2014-2024 Wurst-Imperium and contributors.
*
* This source code is subject to the terms of the GNU General Public
* License, version 3. If a copy of the GPL was not distributed with this
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
*/
package net.wurstclient.settings;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

public final class RoundingPrecisionSetting extends SliderSetting
{
private static final DecimalFormatSymbols SYMBOLS =
new DecimalFormatSymbols(Locale.ENGLISH);

private final DecimalFormat[] FORMATS;

public RoundingPrecisionSetting(String name, String description, int value,
int min, int max)
{
super(name, description, value, min, max, 1,
ValueDisplay.ROUNDING_PRECISION);

if(min < 0)
throw new IllegalArgumentException(
"min must be greater than or equal to 0");

FORMATS = new DecimalFormat[max + 1];
}

public DecimalFormat getFormat()
{
int value = getValueI();

if(FORMATS[value] == null)
{
String pattern = "0";
if(value > 0)
pattern += "." + "#".repeat(value);

FORMATS[value] = new DecimalFormat(pattern, SYMBOLS);
}

return FORMATS[value];
}

public String format(double value)
{
return getFormat().format(value);
}
Alexander01998 marked this conversation as resolved.
Show resolved Hide resolved
}
3 changes: 3 additions & 0 deletions src/main/java/net/wurstclient/settings/SliderSetting.java
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ public String getValueString(double v)

public static final ValueDisplay DEGREES = INTEGER.withSuffix("\u00b0");

public static final ValueDisplay ROUNDING_PRECISION =
v -> (int)v == 0 ? "1" : "0." + "0".repeat((int)v - 1) + "1";

public static final ValueDisplay NONE = v -> "";

public String getValueString(double value);
Expand Down
60 changes: 53 additions & 7 deletions src/main/java/net/wurstclient/util/RenderUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,23 @@

import net.minecraft.block.Blocks;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.font.TextRenderer.TextLayerType;
import net.minecraft.client.gl.VertexBuffer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.*;
import net.minecraft.client.render.BufferBuilder.BuiltBuffer;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.chunk.Chunk;
import net.wurstclient.WurstClient;
import net.wurstclient.hacks.NameTagsHack;
Alexander01998 marked this conversation as resolved.
Show resolved Hide resolved

public enum RenderUtils
{
Expand Down Expand Up @@ -893,4 +892,51 @@ public static void drawItem(DrawContext context, ItemStack stack, int x,

RenderSystem.setShaderColor(1, 1, 1, 1);
}

public static void renderTag(MatrixStack matrixStack, Text text,
Entity entity, VertexConsumerProvider provider, int color,
double vOffset, float partialTicks)
{
NameTagsHack nameTags = WurstClient.INSTANCE.getHax().nameTagsHack;

EntityRenderDispatcher dispatcher =
WurstClient.MC.getEntityRenderDispatcher();
double dist = dispatcher.getSquaredDistanceToCamera(entity);
if(dist > 4096 && !nameTags.isUnlimitedRange())
return;

matrixStack.push();

Vec3d camPos = RenderUtils.getCameraPos();
Vec3d tagPos = EntityUtils.getLerpedPos(entity, partialTicks)
.subtract(camPos).add(0, entity.getHeight() + vOffset, 0);
matrixStack.translate(tagPos.x, tagPos.y, tagPos.z);

matrixStack.multiply(dispatcher.getRotation());

float scale = 0.025F;
if(nameTags.isEnabled())
{
double distance = WurstClient.MC.player.distanceTo(entity);
if(distance > 10)
scale *= distance / 10;
}
matrixStack.scale(-scale, -scale, scale);

float bgOpacity =
WurstClient.MC.options.getTextBackgroundOpacity(0.25f);
int bgColor = (int)(bgOpacity * 255F) << 24;

Matrix4f matrix = matrixStack.peek().getPositionMatrix();
TextRenderer tr = WurstClient.MC.textRenderer;
int labelX = -tr.getWidth(text) / 2;

tr.draw(text, labelX, 0, color, false, matrix, provider,
TextLayerType.NORMAL, bgColor, 15728880);

tr.draw(text, labelX, 0, -1, false, matrix, provider,
TextLayerType.SEE_THROUGH, 0, 15728880);

matrixStack.pop();
}
}