nametags module

This commit is contained in:
RudideC
2026-02-19 13:22:30 +01:00
parent 6bfdf66cdd
commit 38041b01cf
7 changed files with 155 additions and 2 deletions
@@ -22,7 +22,8 @@ public class ModManager {
new DayCounter(),
new Speedometer(),
new Zoom(),
new HealthDisplay()
new HealthDisplay(),
new Nametags()
};
public static void init() {
@@ -0,0 +1,54 @@
package org.saturnclient.modules.mods;
import org.saturnclient.modules.Module;
import org.saturnclient.modules.ModuleDetails;
import org.saturnclient.modules.mods.utils.HealthRenderState;
import org.saturnclient.saturnclient.config.Property;
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
public class Nametags extends Module {
private static Property<Boolean> enabled = Property.bool(false);
private static Property<Boolean> healthDisplay = Property.bool(false);
public Nametags() {
super(
new ModuleDetails("Nametags", "zoom")
.description("Allows you to modify entity nametags")
.tags("Camera", "Utility")
.version("0.1.0"),
enabled.named("Enabled"),
healthDisplay.named("Display health")
);
}
@Override
public void tick() {
}
public static String getNametagString(LivingEntityRenderState state) {
if (state.customName == null) return null;
if (!healthDisplay.value) return state.customName.getString(); // name only
if (!(state instanceof HealthRenderState hrs)) return null;
return state.customName.getString()
+ " §c" + String.format("%.1f", hrs.saturn$getHealth())
+ " / " + String.format("%.1f", hrs.saturn$getMaxHealth()) + " ❤";
}
public static boolean shouldReplaceName() {
return enabled.value;
}
@Override
public void onEnabled(boolean e) {
enabled.value = e;
}
@Override
public boolean isEnabled() {
return enabled.value;
}
}
@@ -0,0 +1,19 @@
package org.saturnclient.modules.mods.mixins;
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(LivingEntityRenderState.class)
public class LivingEntityRenderStateMixin implements org.saturnclient.modules.mods.utils.HealthRenderState {
@Unique private float saturn$health = 0f;
@Unique private float saturn$maxHealth = 1f;
@Override public float saturn$getHealth() { return saturn$health; }
@Override public float saturn$getMaxHealth() { return saturn$maxHealth; }
@Override public void saturn$setHealth(float health, float maxHealth) {
this.saturn$health = health;
this.saturn$maxHealth = maxHealth;
}
}
@@ -0,0 +1,21 @@
package org.saturnclient.modules.mods.mixins;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
import net.minecraft.entity.LivingEntity;
import org.saturnclient.modules.mods.utils.HealthRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LivingEntityRenderer.class)
public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extends LivingEntityRenderState> {
@Inject(method = "updateRenderState", at = @At("TAIL"))
private void saturn$captureHealth(T entity, S state, float tickDelta, CallbackInfo ci) {
if (state instanceof HealthRenderState hrs) {
hrs.saturn$setHealth(entity.getHealth(), entity.getMaxHealth());
}
}
}
@@ -0,0 +1,48 @@
package org.saturnclient.modules.mods.mixins;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import org.saturnclient.modules.mods.Nametags;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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;
@Mixin(EntityRenderer.class)
public abstract class NametagsMixin {
@Unique
private static final ThreadLocal<Boolean> saturn$rendering = ThreadLocal.withInitial(() -> false);
@Shadow
protected abstract <S extends EntityRenderState> void renderLabelIfPresent(
S state, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light
);
@Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true)
private <S extends EntityRenderState> void saturn$replaceNametag(S state, Text text,
MatrixStack matrices, VertexConsumerProvider vertexConsumers,
int light, CallbackInfo ci) {
if (saturn$rendering.get()) return;
if (!Nametags.shouldReplaceName()) return;
if (!(state instanceof LivingEntityRenderState living)) return;
String replacement = Nametags.getNametagString(living);
if (replacement == null) return;
ci.cancel();
saturn$rendering.set(true);
try {
renderLabelIfPresent(state, Text.literal(replacement), matrices, vertexConsumers, light);
} finally {
saturn$rendering.set(false);
}
}
}
@@ -0,0 +1,7 @@
package org.saturnclient.modules.mods.utils;
public interface HealthRenderState {
float saturn$getHealth();
float saturn$getMaxHealth();
void saturn$setHealth(float health, float maxHealth);
}
+4 -1
View File
@@ -9,7 +9,10 @@
"RenderMixin",
"LightmapTextureManagerMixin",
"BackgroundRendererMixin",
"GameRendererMixin"
"GameRendererMixin",
"NametagsMixin",
"LivingEntityRenderStateMixin",
"LivingEntityRendererMixin"
],
"injectors": {
"defaultRequire": 1