diff --git a/gradle.properties b/gradle.properties index 013c631..bac900b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ yarn_mappings=1.21.4+build.7 loader_version=0.16.10 fabric_version=0.114.0+1.21.4 -mod_version = 0.0.6-beta1 +mod_version = 0.0.7-alpha1 maven_group = org.saturnclient archives_base_name = saturnclient diff --git a/src/main/java/org/saturnclient/modules/ModManager.java b/src/main/java/org/saturnclient/modules/ModManager.java index 13bd833..9a2ef26 100644 --- a/src/main/java/org/saturnclient/modules/ModManager.java +++ b/src/main/java/org/saturnclient/modules/ModManager.java @@ -22,7 +22,11 @@ public class ModManager { new DayCounter(), new Speedometer(), new Zoom(), - new HealthDisplay() + new HealthDisplay(), + new Nametags(), + new Ping(), + new Tps(), + new Clock() }; public static void init() { diff --git a/src/main/java/org/saturnclient/modules/mods/Clock.java b/src/main/java/org/saturnclient/modules/mods/Clock.java new file mode 100644 index 0000000..10170fa --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/Clock.java @@ -0,0 +1,77 @@ +package org.saturnclient.modules.mods; + +import java.time.format.DateTimeFormatter; +import java.time.LocalTime; + +import org.saturnclient.modules.HudMod; +import org.saturnclient.modules.ModDimensions; +import org.saturnclient.modules.Module; +import org.saturnclient.modules.ModuleDetails; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.ui2.RenderScope; +import org.saturnclient.ui2.resources.Fonts; + +public class Clock extends Module implements HudMod { + private static Property enabled = Property.bool(false); + private static Property format = Property.select(0, "24 hour", "12 hour"); + private static Property seconds = Property.bool(false); + private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight()); + + public Clock() { + super(new ModuleDetails("Clock", "clock") + .description("Displays the current real-world time") + .version("v0.1.0") + .tags("Utility"), + enabled.named("Enabled"), + format.named("Format"), + seconds.named("Show seconds"), + dimensions.prop() + ); + } + + @Override + public void renderDummy(RenderScope scope) { + renderClock(scope); + } + + @Override + public void renderHud(RenderScope scope) { + renderClock(scope); + } + + public void renderClock(RenderScope scope) { + String text = ""; + LocalTime currentTime = LocalTime.now(); + + switch (format.value) { + case 0: + if (seconds.value) { text = currentTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")); } + else { text = currentTime.format(DateTimeFormatter.ofPattern("HH:mm")); } + break; + case 1: + if (seconds.value) { text = currentTime.format(DateTimeFormatter.ofPattern("hh:mm:ss a")); } + else { text = currentTime.format(DateTimeFormatter.ofPattern("hh:mm a")); } + break; + } + + scope.drawText(text, + 0, 0, dimensions.font.value, dimensions.fgColor.value); + dimensions.width = Fonts.getWidth(text, dimensions.font.value); + dimensions.height = 18 * text.split("\n").length; + } + + @Override + public boolean isEnabled() { + return enabled.value; + } + + @Override + public ModDimensions getDimensions() { + return dimensions; + } + + @Override + public void onEnabled(boolean e) { + enabled.value = e; + } +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/modules/mods/HealthDisplay.java b/src/main/java/org/saturnclient/modules/mods/HealthDisplay.java index 169e6c7..a3cd80f 100644 --- a/src/main/java/org/saturnclient/modules/mods/HealthDisplay.java +++ b/src/main/java/org/saturnclient/modules/mods/HealthDisplay.java @@ -34,7 +34,7 @@ public class HealthDisplay extends Module implements HudMod { @Override public void renderDummy(RenderScope scope) { - renderSpeed(10, scope); + renderHealth(10, scope); } @Override @@ -44,10 +44,10 @@ public class HealthDisplay extends Module implements HudMod { case 1: health = health / 2; } - renderSpeed(health, scope); + renderHealth(health, scope); } - public void renderSpeed(float health, RenderScope scope) { + public void renderHealth(float health, RenderScope scope) { String text = ""; switch (decimals.value) { diff --git a/src/main/java/org/saturnclient/modules/mods/Nametags.java b/src/main/java/org/saturnclient/modules/mods/Nametags.java new file mode 100644 index 0000000..c1ebeb9 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/Nametags.java @@ -0,0 +1,148 @@ +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; + +// todo: rendering modes, custom names + +public class Nametags extends Module { + private static Property enabled = Property.bool(false); + private static Property healthDisplay = Property.bool(false); + private static Property players = Property.bool(true); + private static Property hostile = Property.bool(false); + private static Property passive = Property.bool(false); + private static Property heartEmoji = Property.bool(true); + private static Property obfuscate = Property.bool(false); + private static Property unit = Property.select(0, "Health", "Hearts"); + private static Property format = Property.select(0, "Value", "Value / Total", "%"); + private static Property nameColor = Property.select(15, + "Black", + "Dark Blue", + "Dark Green", + "Dark Aqua", + "Dark Red", + "Dark Purple", + "Gold", + "Gray", + "Dark Gray", + "Blue", + "Green", + "Aqua", + "Red", + "Light Purple", + "Yellow", + "White" + ); + private static Property healthColor = Property.select(12, + "Black", + "Dark Blue", + "Dark Green", + "Dark Aqua", + "Dark Red", + "Dark Purple", + "Gold", + "Gray", + "Dark Gray", + "Blue", + "Green", + "Aqua", + "Red", + "Light Purple", + "Yellow", + "White" + ); + + private static final String[] COLOR_CODES = { + "§0", "§1", "§2", "§3", "§4", "§5", "§6", "§7", + "§8", "§9", "§a", "§b", "§c", "§d", "§e", "§f" + }; + + public Nametags() { + super( + new ModuleDetails("Nametags", "nametags") + .description("Allows you to modify entity nametags") + .tags("Camera", "Utility") + .version("0.1.0"), + enabled.named("Enabled"), + healthDisplay.named("Display health"), + players.named("Players"), + hostile.named("Hostile"), + passive.named("Passive"), + heartEmoji.named("Heart emoji"), + obfuscate.named("Obfuscate enemy names"), + unit.named("Unit"), + format.named("Format"), + nameColor.named("Name color"), + healthColor.named("Health color") + ); + } + + @Override + public void tick() { + + } + + public static String getHealthString(LivingEntityRenderState state, HealthRenderState hrs, float health, float maxHealth) { + String ret = ""; + + switch (format.value){ + case 0: // value + ret = String.format("%.1f", health / (unit.value + 1)); + break; + + case 1: // value / total + ret = String.format("%.1f", health / (unit.value + 1)) + " / " + String.format("%.1f", maxHealth / (unit.value + 1)); + break; + + case 2: // % + ret = String.format("%.0f%%", (health / maxHealth) * 100); + break; + } + return ret; + } + + 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; + + float health = hrs.saturn$getHealth(); + float maxHealth = hrs.saturn$getMaxHealth(); + + HealthRenderState.EntityType type = hrs.saturn$getEntityType(); + if (type == HealthRenderState.EntityType.PASSIVE && !passive.value) return null; + if (type == HealthRenderState.EntityType.HOSTILE && !hostile.value) return null; + if (type == HealthRenderState.EntityType.PLAYER && !players.value) return null; + if (type == HealthRenderState.EntityType.OTHER) return null; + + if (health < 0f || maxHealth < 0f || health > maxHealth) return null; + + String hpColor = COLOR_CODES[healthColor.value]; + String color = COLOR_CODES[nameColor.value]; + String heart = heartEmoji.value ? " ❤" : ""; + String obf = obfuscate.value ? "§k" : ""; + String reset = "§r"; + + String ret = color + obf + state.customName.getString() + reset + " " + hpColor + getHealthString(state, hrs, health, maxHealth) + heart; + + return ret; + } + + public static boolean shouldReplaceName() { + return enabled.value; + } + + @Override + public void onEnabled(boolean e) { + enabled.value = e; + } + + @Override + public boolean isEnabled() { + return enabled.value; + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/Ping.java b/src/main/java/org/saturnclient/modules/mods/Ping.java new file mode 100644 index 0000000..e75d5ad --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/Ping.java @@ -0,0 +1,60 @@ +package org.saturnclient.modules.mods; + +import org.saturnclient.modules.HudMod; +import org.saturnclient.modules.ModDimensions; +import org.saturnclient.modules.Module; +import org.saturnclient.modules.ModuleDetails; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.ui2.RenderScope; +import org.saturnclient.ui2.resources.Fonts; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; + +public class Ping extends Module implements HudMod { + private static Property enabled = Property.bool(false); + private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight()); + + public Ping() { + super(new ModuleDetails("Ping Display", "ping") + .description("Displays ping") + .version("v0.1.0") + .tags("Utility"), + enabled.named("Enabled"), + dimensions.prop()); + } + + @Override + public void renderHud(RenderScope scope) { + MinecraftClient client = MinecraftClient.getInstance(); + ClientPlayNetworkHandler handler = client.getNetworkHandler(); + String text = "0 ms"; + if (handler != null) { + text = String.valueOf(handler.getPlayerListEntry(client.player.getUuid()).getLatency()) + " ms"; + } + scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value); + dimensions.width = Fonts.getWidth(text, dimensions.font.value); + } + + @Override + public void renderDummy(RenderScope scope) { + String text = "10 ms"; + scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value); + dimensions.width = Fonts.getWidth(text, dimensions.font.value); + } + + @Override + public boolean isEnabled() { + return enabled.value; + } + + @Override + public void onEnabled(boolean e) { + enabled.value = e; + } + + @Override + public ModDimensions getDimensions() { + return dimensions; + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/Tps.java b/src/main/java/org/saturnclient/modules/mods/Tps.java new file mode 100644 index 0000000..923adb9 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/Tps.java @@ -0,0 +1,99 @@ +package org.saturnclient.modules.mods; + +import org.saturnclient.modules.HudMod; +import org.saturnclient.modules.ModDimensions; +import org.saturnclient.modules.Module; +import org.saturnclient.modules.ModuleDetails; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.ui2.RenderScope; +import org.saturnclient.ui2.resources.Fonts; + +public class Tps extends Module implements HudMod { + private static Property enabled = Property.bool(false); + private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight()); + + private static long lastWorldAge = -1; + private static long lastRealTime = -1; + private static double currentTps = 20.0; + + private static final int SAMPLE_COUNT = 2; + private static final double[] samples = new double[SAMPLE_COUNT]; + static { + java.util.Arrays.fill(samples, 20.0); + } + private static int sampleIndex = 0; + private static int samplesFilled = 0; + + public Tps() { + super(new ModuleDetails("TPS Display", "tps") + .description("Displays the TPS") + .version("v0.1.0") + .tags("Utility"), + enabled.named("Enabled"), + dimensions.prop() + ); + } + + public static void onTimePacket(long worldAge) { + long now = System.currentTimeMillis(); + + if (lastWorldAge != -1 && lastRealTime != -1) { + long tickDelta = worldAge - lastWorldAge; + long timeDelta = now - lastRealTime; + + if (timeDelta > 0 && tickDelta > 0) { + double sample = (tickDelta / (double) timeDelta) * 1000.0; + sample = Math.min(sample, 20.0); + + samples[sampleIndex % SAMPLE_COUNT] = sample; + sampleIndex++; + samplesFilled = Math.min(samplesFilled + 1, SAMPLE_COUNT); + + double sum = 0; + for (int i = 0; i < samplesFilled; i++) sum += samples[i]; + currentTps = sum / samplesFilled; + } + } + + lastWorldAge = worldAge; + lastRealTime = now; + } + + public static void reset() { + lastWorldAge = -1; + lastRealTime = -1; + currentTps = 20.0; + sampleIndex = 0; + samplesFilled = SAMPLE_COUNT; + for (int i = 0; i < SAMPLE_COUNT; i++) samples[i] = 20.0; + } + + @Override + public void renderHud(RenderScope scope) { + String text = String.format("%.1f TPS", currentTps); + scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value); + dimensions.width = Fonts.getWidth(text, dimensions.font.value); + } + + @Override + public void renderDummy(RenderScope scope) { + String text = "20.0 TPS"; + scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value); + dimensions.width = Fonts.getWidth(text, dimensions.font.value); + } + + @Override + public boolean isEnabled() { + return enabled.value; + } + + @Override + public void onEnabled(boolean e) { + enabled.value = e; + } + + @Override + public ModDimensions getDimensions() { + return dimensions; + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/LivingEntityRenderStateMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/LivingEntityRenderStateMixin.java new file mode 100644 index 0000000..dacee20 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/mixins/LivingEntityRenderStateMixin.java @@ -0,0 +1,26 @@ +package org.saturnclient.modules.mods.mixins; + +import net.minecraft.client.render.entity.state.LivingEntityRenderState; + +import org.saturnclient.modules.mods.utils.HealthRenderState; +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; + @Unique private HealthRenderState.EntityType saturn$entityType = HealthRenderState.EntityType.OTHER; + + public float saturn$getHealth() { return saturn$health; } + public float saturn$getMaxHealth() { return saturn$maxHealth; } + public void saturn$setHealth(float health, float maxHealth) { + this.saturn$health = health; + this.saturn$maxHealth = maxHealth; + } + + public HealthRenderState.EntityType saturn$getEntityType() { return saturn$entityType; } + public void saturn$setEntityType(HealthRenderState.EntityType type) { this.saturn$entityType = type; } + +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/LivingEntityRendererMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/LivingEntityRendererMixin.java new file mode 100644 index 0000000..34e5d1f --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/mixins/LivingEntityRendererMixin.java @@ -0,0 +1,34 @@ +package org.saturnclient.modules.mods.mixins; + +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.state.LivingEntityRenderState; +import org.saturnclient.modules.mods.utils.HealthRenderState; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.entity.passive.PassiveEntity; +import net.minecraft.entity.player.PlayerEntity; +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 { + + @Inject(method = "updateRenderState", at = @At("TAIL")) + private void saturn$captureHealth(T entity, S state, float tickDelta, CallbackInfo ci) { + if (!(state instanceof HealthRenderState hrs)) return; + + hrs.saturn$setHealth(entity.getHealth(), entity.getMaxHealth()); + + if (entity instanceof PlayerEntity) { + hrs.saturn$setEntityType(HealthRenderState.EntityType.PLAYER); + } else if (entity instanceof HostileEntity) { + hrs.saturn$setEntityType(HealthRenderState.EntityType.HOSTILE); + } else if (entity instanceof PassiveEntity) { + hrs.saturn$setEntityType(HealthRenderState.EntityType.PASSIVE); + } else { + hrs.saturn$setEntityType(HealthRenderState.EntityType.OTHER); + } + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/NametagsMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/NametagsMixin.java new file mode 100644 index 0000000..be17d91 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/mixins/NametagsMixin.java @@ -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 saturn$rendering = ThreadLocal.withInitial(() -> false); + + @Shadow + protected abstract void renderLabelIfPresent( + S state, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light + ); + + @Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true) + private 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); + } + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/TpsMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/TpsMixin.java new file mode 100644 index 0000000..7a9d15e --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/mixins/TpsMixin.java @@ -0,0 +1,18 @@ +package org.saturnclient.modules.mods.mixins; + +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket; +import org.saturnclient.modules.mods.Tps; +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(ClientPlayNetworkHandler.class) +public class TpsMixin { + + @Inject(method = "onWorldTimeUpdate", at = @At("HEAD")) + private void onWorldTimeUpdate(WorldTimeUpdateS2CPacket packet, CallbackInfo ci) { + Tps.onTimePacket(packet.time()); + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/utils/HealthRenderState.java b/src/main/java/org/saturnclient/modules/mods/utils/HealthRenderState.java new file mode 100644 index 0000000..4853754 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/utils/HealthRenderState.java @@ -0,0 +1,14 @@ +package org.saturnclient.modules.mods.utils; + +public interface HealthRenderState { + float saturn$getHealth(); + float saturn$getMaxHealth(); + void saturn$setHealth(float health, float maxHealth); + + EntityType saturn$getEntityType(); + void saturn$setEntityType(EntityType type); + + enum EntityType { + PLAYER, HOSTILE, PASSIVE, OTHER + } +} diff --git a/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java b/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java index dae59f3..b2231a1 100644 --- a/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java +++ b/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java @@ -39,7 +39,7 @@ public class KeyInputHandler { client.setScreen(new ShiftMenu()); } - if (SaturnClientConfig.openEmoteWheel.wasKeyPressed() && client.currentScreen == null) { + if (SaturnClientConfig.openEmoteWheel.wasKeyPressed() && client.currentScreen == null && !InputUtil.isKeyPressed(client.getWindow().getHandle(), GLFW.GLFW_KEY_F3)) { client.setScreen(new EmoteWheel()); } diff --git a/src/main/java/org/saturnclient/ui2/elements/Scroll.java b/src/main/java/org/saturnclient/ui2/elements/Scroll.java index 3114af6..b9c8848 100644 --- a/src/main/java/org/saturnclient/ui2/elements/Scroll.java +++ b/src/main/java/org/saturnclient/ui2/elements/Scroll.java @@ -70,14 +70,14 @@ public class Scroll extends Element { @Override public Element dimensions(int width, int height) { + super.dimensions(width, height); + maxScroll = 0; - for (Element element : children) { - maxScroll = Math.max(maxScroll, element.y + element.height - height); + maxScroll = Math.max(maxScroll, (element.y + element.height + padding) - (height - padding * 2)); } - - maxScroll = Math.max(0, maxScroll); // never negative - return super.dimensions(width, height); + + return this; } int calculateScrollBarHeight() { @@ -88,9 +88,9 @@ public class Scroll extends Element { int calculateScrollBarY() { int scrollBarHeight = calculateScrollBarHeight(); - if (maxScroll <= 0) - return scrollBarPadding.value; - return (scroll * (height - scrollBarHeight)) / maxScroll + scrollBarPadding.value; + if (maxScroll <= 0) return scrollBarPadding.value; + int y = (scroll * (height - scrollBarHeight - scrollBarPadding.value * 2)) / maxScroll + scrollBarPadding.value; + return Math.min(y, height - scrollBarHeight - scrollBarPadding.value); } private void calculateMaxScroll() { diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/clock.png b/src/main/resources/assets/saturnclient/textures/gui/mod/clock.png new file mode 100644 index 0000000..b8d46ec Binary files /dev/null and b/src/main/resources/assets/saturnclient/textures/gui/mod/clock.png differ diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/nametags.png b/src/main/resources/assets/saturnclient/textures/gui/mod/nametags.png new file mode 100644 index 0000000..90a1e97 Binary files /dev/null and b/src/main/resources/assets/saturnclient/textures/gui/mod/nametags.png differ diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/ping.png b/src/main/resources/assets/saturnclient/textures/gui/mod/ping.png new file mode 100644 index 0000000..01a53a6 Binary files /dev/null and b/src/main/resources/assets/saturnclient/textures/gui/mod/ping.png differ diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/tps.png b/src/main/resources/assets/saturnclient/textures/gui/mod/tps.png new file mode 100644 index 0000000..634c7f4 Binary files /dev/null and b/src/main/resources/assets/saturnclient/textures/gui/mod/tps.png differ diff --git a/src/main/resources/mods.mixins.json b/src/main/resources/mods.mixins.json index fea0c0c..6cd236b 100644 --- a/src/main/resources/mods.mixins.json +++ b/src/main/resources/mods.mixins.json @@ -9,7 +9,11 @@ "RenderMixin", "LightmapTextureManagerMixin", "BackgroundRendererMixin", - "GameRendererMixin" + "GameRendererMixin", + "NametagsMixin", + "LivingEntityRenderStateMixin", + "LivingEntityRendererMixin", + "TpsMixin" ], "injectors": { "defaultRequire": 1