Merge pull request #79 from saturnclientmc/nametags-patch

Nametags patch
This commit is contained in:
2026-04-08 20:45:27 +02:00
committed by GitHub
17 changed files with 128 additions and 236 deletions
@@ -0,0 +1,10 @@
package org.saturnclient.saturnclient;
import org.saturnclient.client.player.SaturnPlayer;
import net.fabricmc.fabric.api.client.rendering.v1.RenderStateDataKey;
public class SaturnRenderState {
public static RenderStateDataKey<SaturnPlayer> saturnDataKey = RenderStateDataKey
.create(() -> "saturn-client-player");
}
@@ -1,67 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.render.command.OrderedRenderCommandQueue;
import net.minecraft.client.render.entity.EntityRenderManager;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.render.state.CameraRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
import java.util.UUID;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(value = EntityRenderer.class, priority = 1800)
public abstract class NameTagMixin<S extends EntityRenderState> {
@Shadow
public EntityRenderManager dispatcher;
/**
* @author HexLeo
* @reason Adds the Saturn Client icon to the player's name if they are online
* with Saturn Client
*/
@Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true)
protected void renderLabelIfPresent(S state, MatrixStack matrices, OrderedRenderCommandQueue queue,
CameraRenderState cameraRenderState, CallbackInfo ci) {
if (state.displayName == null)
return;
UUID uuid = isSaturn(state);
if (uuid != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(uuid)));
Text nameText = state.displayName.copy().styled(style -> style.withColor(Formatting.WHITE));
queue.submitLabel(matrices, state.nameLabelPos, 0, iconText.append(nameText), !state.sneaking, state.light,
state.squaredDistanceToCamera, cameraRenderState);
ci.cancel();
}
}
private UUID isSaturn(S state) {
if (state instanceof PlayerEntityRenderState) {
String name = ((PlayerEntityRenderState) state).displayName.getString();
SaturnPlayer player = SaturnPlayer.get(name);
if (player != null) {
return player.uuid;
}
}
return null;
}
}
@@ -1,14 +1,22 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.network.ClientPlayerLikeEntity;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.PlayerEntityModel;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.entity.PlayerLikeEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.impl.cosmetics.CloakFeatureRenderer;
import org.saturnclient.impl.cosmetics.HatFeatureRenderer;
import org.saturnclient.saturnclient.SaturnRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -27,4 +35,27 @@ public abstract class PlayerEntityRendererMixin
this.addFeature(new HatFeatureRenderer(this));
this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader()));
}
@Inject(method = "updateRenderState", at = @At("TAIL"))
public <A extends PlayerLikeEntity & ClientPlayerLikeEntity> void updateRenderState(
A entity, PlayerEntityRenderState state,
float f, CallbackInfo ci) {
if (entity == null) {
return;
}
SaturnPlayer player = SaturnPlayer.get(entity.getUuid());
state.setData(SaturnRenderState.saturnDataKey, player);
if (player != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(player.uuid)));
state.displayName = Text.empty()
.append(iconText.copy())
.append(Text.empty().formatted(Formatting.RESET))
.append(state.displayName.copy());
}
}
}
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",
@@ -10,6 +10,7 @@ import net.minecraft.entity.PlayerLikeEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
@@ -47,11 +48,14 @@ public abstract class PlayerEntityRendererMixin
state.setData(SaturnRenderState.saturnDataKey, player);
if (player != null) {
if (player != null && state.displayName != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(player.uuid)));
state.displayName = iconText.append(state.displayName);
state.displayName = Text.empty()
.append(iconText.copy())
.append(Text.empty().formatted(Formatting.RESET))
.append(state.displayName.copy());
}
}
}
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",
@@ -0,0 +1,10 @@
package org.saturnclient.saturnclient;
import org.saturnclient.client.player.SaturnPlayer;
import net.fabricmc.fabric.api.client.rendering.v1.RenderStateDataKey;
public class SaturnRenderState {
public static RenderStateDataKey<SaturnPlayer> saturnDataKey = RenderStateDataKey
.create(() -> "saturn-client-player");
}
@@ -1,93 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.font.TextRenderer.TextLayerType;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Vec3d;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.saturnclient.SaturnClient;
import java.util.UUID;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(value = EntityRenderer.class, priority = 1800)
public abstract class NameTagMixin<S extends EntityRenderState> {
@Shadow
public EntityRenderDispatcher dispatcher;
/**
* @author HexLeo
* @reason Adds the Saturn Client icon to the player's name if they are online
* with Saturn Client
*/
@Inject(method = "renderLabelIfPresent(Lnet/minecraft/client/render/entity/state/EntityRenderState;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At("HEAD"), cancellable = true)
private void onRenderLabelIfPresent(S state, Text text, MatrixStack matrices,
VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
UUID uuid = isSaturn(state);
if (uuid != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(uuid)));
Text nameText = text.copy().styled(style -> style.withColor(Formatting.WHITE));
renderLabel(state, iconText.append(nameText), matrices,
vertexConsumers, light);
ci.cancel();
}
}
private UUID isSaturn(S state) {
if (state instanceof PlayerEntityRenderState) {
String name = ((PlayerEntityRenderState) state).name;
SaturnPlayer player = SaturnPlayer.get(name);
if (player != null) {
return player.uuid;
}
}
return null;
}
private void renderLabel(S state, Text text, MatrixStack matrices,
VertexConsumerProvider vertexConsumers, int light) {
Vec3d vec3d = state.nameLabelPos;
if (vec3d != null) {
boolean bl = !state.sneaking;
int i = "deadmau5".equals(text.getString()) ? -10 : 0;
matrices.push();
matrices.translate(vec3d.x, vec3d.y + 0.5, vec3d.z);
matrices.multiply(this.dispatcher.getRotation());
matrices.scale(0.025F, -0.025F, 0.025F);
Matrix4f matrix4f = matrices.peek().getPositionMatrix();
TextRenderer textRenderer = SaturnClient.client.textRenderer;
float f = (float) (-textRenderer.getWidth(text)) / 2.0F;
int j = (int) (SaturnClient.client.options.getTextBackgroundOpacity(0.25F) * 255.0F) << 24;
textRenderer.draw(text, f, (float) i, -2130706433, false, matrix4f, vertexConsumers,
bl ? TextLayerType.SEE_THROUGH : TextLayerType.NORMAL, j, light);
if (bl) {
textRenderer.draw(text, f, (float) i, -1, false, matrix4f, vertexConsumers, TextLayerType.NORMAL, 0,
light);
}
matrices.pop();
}
}
}
@@ -1,14 +1,21 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.PlayerEntityModel;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.impl.cosmetics.CloakFeatureRenderer;
import org.saturnclient.impl.cosmetics.HatFeatureRenderer;
import org.saturnclient.saturnclient.SaturnRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -27,4 +34,27 @@ public abstract class PlayerEntityRendererMixin
this.addFeature(new HatFeatureRenderer(this));
this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader()));
}
@Inject(method = "updateRenderState", at = @At("TAIL"))
public void updateRenderState(
AbstractClientPlayerEntity entity, PlayerEntityRenderState state,
float f, CallbackInfo ci) {
if (entity == null) {
return;
}
SaturnPlayer player = SaturnPlayer.get(entity.getUuid());
state.setData(SaturnRenderState.saturnDataKey, player);
if (player != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(player.uuid)));
state.displayName = Text.empty()
.append(iconText.copy())
.append(Text.empty().formatted(Formatting.RESET))
.append(state.displayName.copy());
}
}
}
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",
@@ -0,0 +1,10 @@
package org.saturnclient.saturnclient;
import org.saturnclient.client.player.SaturnPlayer;
import net.fabricmc.fabric.api.client.rendering.v1.RenderStateDataKey;
public class SaturnRenderState {
public static RenderStateDataKey<SaturnPlayer> saturnDataKey = RenderStateDataKey
.create(() -> "saturn-client-player");
}
@@ -1,67 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.render.command.OrderedRenderCommandQueue;
import net.minecraft.client.render.entity.EntityRenderManager;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.render.state.CameraRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
import java.util.UUID;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(value = EntityRenderer.class, priority = 1800)
public abstract class NameTagMixin<S extends EntityRenderState> {
@Shadow
public EntityRenderManager dispatcher;
/**
* @author HexLeo
* @reason Adds the Saturn Client icon to the player's name if they are online
* with Saturn Client
*/
@Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true)
protected void renderLabelIfPresent(S state, MatrixStack matrices, OrderedRenderCommandQueue queue,
CameraRenderState cameraRenderState, CallbackInfo ci) {
if (state.displayName == null)
return;
UUID uuid = isSaturn(state);
if (uuid != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(uuid)));
Text nameText = state.displayName.copy().styled(style -> style.withColor(Formatting.WHITE));
queue.submitLabel(matrices, state.nameLabelPos, 0, iconText.append(nameText), !state.sneaking, state.light,
state.squaredDistanceToCamera, cameraRenderState);
ci.cancel();
}
}
private UUID isSaturn(S state) {
if (state instanceof PlayerEntityRenderState) {
String name = ((PlayerEntityRenderState) state).displayName.getString();
SaturnPlayer player = SaturnPlayer.get(name);
if (player != null) {
return player.uuid;
}
}
return null;
}
}
@@ -1,14 +1,22 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.network.ClientPlayerLikeEntity;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer;
import net.minecraft.client.render.entity.model.PlayerEntityModel;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.entity.PlayerLikeEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.impl.cosmetics.CloakFeatureRenderer;
import org.saturnclient.impl.cosmetics.HatFeatureRenderer;
import org.saturnclient.saturnclient.SaturnRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -27,4 +35,27 @@ public abstract class PlayerEntityRendererMixin
this.addFeature(new HatFeatureRenderer(this));
this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader()));
}
@Inject(method = "updateRenderState", at = @At("TAIL"))
public <A extends PlayerLikeEntity & ClientPlayerLikeEntity> void updateRenderState(
A entity, PlayerEntityRenderState state,
float f, CallbackInfo ci) {
if (entity == null) {
return;
}
SaturnPlayer player = SaturnPlayer.get(entity.getUuid());
state.setData(SaturnRenderState.saturnDataKey, player);
if (player != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(player.uuid)));
state.displayName = Text.empty()
.append(iconText.copy())
.append(Text.empty().formatted(Formatting.RESET))
.append(state.displayName.copy());
}
}
}
@@ -5,7 +5,6 @@
"compatibilityLevel": "JAVA_21",
"client": [
"TabListMixin",
"NameTagMixin",
"PlayerEntityRendererMixin",
"WhoAmI",
"DrawContextAccessor",