Compare commits

...
Author SHA1 Message Date
selimaj-dev b2ba693f92 alpha2 2025-05-03 22:36:48 +02:00
selimaj-dev cf9fd50e4b slight title menu changes 2025-05-03 13:53:42 -05:00
selimaj-dev f1f17d807f updated the title screen with the new ui 2025-05-03 11:32:41 -05:00
selimaj-dev 22ad088ca4 fixed panorama 2025-05-03 11:19:33 -05:00
selimaj-dev 52e8e572be fixed panorama 2025-05-03 10:15:52 -05:00
selimaj-dev a9ec3311c5 added sprint 2025-05-01 18:10:44 +02:00
selimaj-dev be1cca9c9a alpha blending 2025-05-01 09:33:13 -05:00
selimaj-dev 84f76ac577 lowered the blur 2025-05-01 09:26:51 -05:00
selimaj-dev 76b882599b blur and animation abstraction 2025-05-01 16:21:27 +02:00
selimaj-dev 5b6810a32f removed borders 2025-04-30 07:52:30 -05:00
selimaj-dev f0e554d8bc double the resolution 2025-04-29 05:55:09 -05:00
selimaj-dev bb9cc623c7 added animations 2025-04-29 05:42:25 -05:00
selimaj-dev bf4e16d940 added animations 2025-04-29 05:40:10 -05:00
selimaj-dev 9849a38fe9 working animations 2025-04-29 01:10:23 +02:00
selimaj-dev d16b66945f working animations 2025-04-29 01:10:10 +02:00
selimaj-dev c0b088bb8a experiment: animation curve functions 2025-04-28 15:20:16 -05:00
selimaj-dev 5cce4eabaf new ui elements 2025-04-27 10:45:45 -05:00
selimaj-dev 1254cd4b89 few theme stuff to button and rounded corners 2025-04-26 15:43:10 +02:00
selimaj-dev ff02427aa3 Rounded borders 2025-04-26 14:55:13 +02:00
selimaj-dev 79d5419fcc Fixed crash when exit 2025-04-26 00:23:39 +02:00
selimaj-dev ece5a16d34 Fixed crash when exit 2025-04-26 00:10:39 +02:00
selimaj-dev 32c1391336 Fixed crash when exit 2025-04-25 23:52:37 +02:00
selimaj-dev 486232623a added name tags 2025-04-25 17:10:30 +02:00
selimaj-dev 76dd1fe0a4 name icon colors 2025-04-25 09:45:57 -05:00
selimaj-dev 12c53099f2 ui and module improvements 2025-04-24 03:37:37 -05:00
selimaj-dev 3f89760282 Better module system 2025-04-23 08:18:27 -05:00
selimaj-dev 3b5b51e6d2 fixed config load bug 2025-04-23 14:59:23 +02:00
selimaj-dev d2894d0454 small change 2025-04-23 14:14:26 +02:00
selimaj-dev ed23cb44f2 improving modulation, bug: Config not working 2025-04-23 07:05:56 -05:00
selimaj-dev 683a9f41e8 refactor of the module system. Bug: all mods are enabled bc the Module has static enabled 2025-04-22 17:06:41 -05:00
selimaj-dev 052a56bcb0 i almost got cooked 2025-04-22 16:20:35 -05:00
selimaj-dev 81056dd7d7 renamed 2025-04-22 15:23:36 -05:00
selimaj-dev 8dd13364fb replaced getInstance with .client 2025-04-22 15:19:39 -05:00
selimaj-dev 5149194cb3 added theming 2025-04-22 14:52:38 -05:00
selimaj-dev 98330ed8a9 added theming bug needs bug fix 2025-04-22 14:49:44 -05:00
selimaj-dev ad54ed63f3 logo change 2025-04-22 12:17:42 +02:00
selimaj-dev 08a48c8f92 button element 2025-04-21 17:37:28 +02:00
selimaj-dev 404838b70d fixed rounded rectangle 2025-04-21 17:18:23 +02:00
selimaj-dev 4794e12bed almost there 2025-04-21 17:10:28 +02:00
selimaj-dev 3b44ead173 almost there 2025-04-21 16:52:38 +02:00
selimaj-dev d1cc19a9db almost there 2025-04-21 16:48:37 +02:00
selimaj-dev 9b36603f86 almost there 2025-04-21 16:48:11 +02:00
selimaj-dev 2e5d3296d4 weird bug 2025-04-21 16:13:21 +02:00
selimaj-dev 50e5a453a4 Rounded rectangles 2025-04-21 01:28:27 +02:00
selimaj-dev 8f1d1f0ce8 tesing rounded corners 2025-04-21 00:20:43 +02:00
selimaj-dev 1741e8c0b9 tesing new ui scope 2025-04-21 00:15:52 +02:00
selimaj-dev 9f0d5ef78b tesing new ui scope 2025-04-20 17:24:53 +02:00
selimaj-dev 5c15af0590 added renderScope 2025-04-19 10:40:56 -05:00
77 changed files with 1572 additions and 932 deletions
+1
View File
@@ -13,5 +13,6 @@
- Cloak rendering: `IIpho3nix` & `Dhyan Blum` - Cloak rendering: `IIpho3nix` & `Dhyan Blum`
- Who Am I: `FokshaWasTaken` - Who Am I: `FokshaWasTaken`
- Panton font (ui): `Ivan Petrov` & `Fontfabric` - Panton font (ui): `Ivan Petrov` & `Fontfabric`
- Panorama: https://www.planetminecraft.com/texture-pack/minecraft-cavesand-cliffs-part-ii-main-menu-panorama/
If any of the code or assets are in your name and you want to remove them, please submit an issue, we are still in alpha to have any artists so we would also appreciate if you could help us make some cosmetics If any of the code or assets are in your name and you want to remove them, please submit an issue, we are still in alpha to have any artists so we would also appreciate if you could help us make some cosmetics
+1 -1
View File
@@ -43,7 +43,7 @@ processResources {
} }
} }
def targetJavaVersion = 17 def targetJavaVersion = 21
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8" it.options.encoding = "UTF-8"
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
+1 -1
View File
@@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.16.10 loader_version=0.16.10
# Mod Properties # Mod Properties
mod_version = 0.0.1-alpha0 mod_version = 0.0.1-alpha2
maven_group = me.iipho3nix maven_group = me.iipho3nix
archives_base_name = saturnclient archives_base_name = saturnclient
@@ -1,4 +1,4 @@
package org.saturnclient.saturnmods; package org.saturnclient.modules;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
@@ -1,4 +1,4 @@
package org.saturnclient.saturnmods; package org.saturnclient.modules;
import org.saturnclient.saturnclient.config.ConfigManager; import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property; import org.saturnclient.saturnclient.config.Property;
@@ -0,0 +1,58 @@
package org.saturnclient.modules;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.util.math.MatrixStack;
import org.saturnclient.modules.mods.*;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.menus.HudEditor;
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
import org.saturnclient.ui2.RenderScope;
public class ModManager {
public static Module[] MODS = {
new Crosshair(),
new AutoSprint(),
};
public static void init() {
ClientTickEvents.END_CLIENT_TICK.register(client -> {
for (Module m : MODS) {
if (m.isEnabled()) {
m.tick();
}
}
});
HudRenderCallback.EVENT.register((context, _o) -> {
TextRenderer textRenderer = SaturnClient.client.textRenderer;
if (textRenderer != null &&
!(SaturnClient.client.currentScreen instanceof HudEditor)) {
RenderScope renderScope = new RenderScope(context.getMatrices(),
((DrawContextAccessor) context).getVertexConsumers());
for (Module m : MODS) {
if (m instanceof HudMod && m.isEnabled()) {
ModDimensions dim = ((HudMod) m).getDimensions();
MatrixStack matrices = context.getMatrices();
matrices.push();
matrices.translate(dim.x.value, (float) dim.y.value, 0);
matrices.scale(dim.scale.value, dim.scale.value, 1.0f);
((HudMod) m).render(context);
matrices.pop();
} else {
m.render(renderScope);
}
}
}
});
}
}
@@ -0,0 +1,51 @@
package org.saturnclient.modules;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.NamedProperty;
import org.saturnclient.ui.Textures;
import org.saturnclient.ui2.RenderScope;
import net.minecraft.util.Identifier;
public abstract class Module {
private final String name;
private final String namespace;
private final ConfigManager configManager;
public Module(String name, String namespace, NamedProperty<?>... props) {
this.name = name;
this.namespace = namespace;
configManager = new ConfigManager(name);
for (NamedProperty<?> prop : props) {
configManager.property(prop.name, prop.prop);
}
}
public Module(ConfigManager config, String name, String namespace) {
this.name = name;
this.namespace = namespace;
configManager = config;
}
public void render(RenderScope scope) {}
public void tick() {}
public abstract boolean isEnabled();
public abstract void setEnabled(boolean e);
public final String getName() {
return name;
}
public Identifier getIconTexture() {
return Textures.getModIcon(namespace);
}
public ConfigManager getConfig() {
return configManager;
}
}
@@ -0,0 +1,36 @@
package org.saturnclient.modules.mods;
import java.util.Objects;
import org.saturnclient.modules.Module;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.config.Property;
public class AutoSprint extends Module {
private static Property<Boolean> enabled = new Property<>(true);
public AutoSprint() {
super("Auto Sprint", "sprint", enabled.named("Enabled"));
}
@Override
public void tick() {
if (SaturnClient.client.player == null || SaturnClient.client.getNetworkHandler() == null) {
return;
}
if (SaturnClient.client.options.forwardKey.isPressed() && !SaturnClient.client.options.backKey.isPressed() && !SaturnClient.client.player.isSneaking() &&
!SaturnClient.client.player.horizontalCollision) {
Objects.requireNonNull(SaturnClient.client.player).setSprinting(true);
}
}
@Override
public boolean isEnabled() {
return enabled.value;
}
@Override
public void setEnabled(boolean e) {
enabled.value = e;
}
}
@@ -0,0 +1,44 @@
package org.saturnclient.modules.mods;
import org.saturnclient.modules.Module;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.ui2.RenderScope;
import org.saturnclient.ui2.resources.Textures;
import net.minecraft.client.render.RenderLayer;
public class Crosshair extends Module {
public static Property<Boolean> enabled = new Property<>(false);
public static Property<Boolean> range_indicator = new Property<>(false);
public Crosshair() {
super("Crosshair", "crosshair", enabled.named("Enabled"), range_indicator.named("Range Indicator"));
}
@Override
public void render(RenderScope scope) {
if (enabled.value
&& range_indicator.value
&& SaturnClient.client.targetedEntity != null
&& SaturnClient.client.targetedEntity.isAlive()) {
int scaledWidth = 15;
int scaledHeight = 15;
scope.setRenderLayer(RenderLayer::getCrosshair);
scope.drawTexture(Textures.CROSSHAIR_RANGE,
(scope.getScaledWindowWidth() - scaledWidth) / 2,
(scope.getScaledWindowHeight() - scaledHeight) / 2, 0.0F, 0.0F, scaledWidth, scaledHeight);
}
}
@Override
public boolean isEnabled() {
return enabled.value;
}
@Override
public void setEnabled(boolean e) {
enabled.value = e;
}
}
@@ -3,16 +3,17 @@ package org.saturnclient.saturnclient;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.TitleScreen;
import org.saturnclient.modules.ModManager;
import org.saturnclient.saturnclient.auth.Auth; import org.saturnclient.saturnclient.auth.Auth;
import org.saturnclient.saturnclient.config.ConfigManager; import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.ThemeManager;
import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.saturnclient.cosmetics.Hats;
import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks;
import org.saturnclient.saturnclient.event.KeyInputHandler; import org.saturnclient.saturnclient.event.KeyInputHandler;
import org.saturnclient.saturnclient.menus.SaturnMenu; import org.saturnclient.ui2.screens.TitleMenu;
import org.saturnclient.saturnclient.menus.SaturnTitleScreen;
import org.saturnclient.saturnmods.ModManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -25,18 +26,22 @@ public class SaturnClient implements ModInitializer {
public static final String MOD_ID = "saturnclient"; public static final String MOD_ID = "saturnclient";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static MinecraftClient client;
@Override @Override
public void onInitialize() { public void onInitialize() {
LOGGER.info("Initializing " + MOD_ID); LOGGER.info("Initializing " + MOD_ID);
client = MinecraftClient.getInstance();
ModManager.init(); ModManager.init();
SaturnClientConfig.init();
ThemeManager.load();
ConfigManager.load(); ConfigManager.load();
ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> ConfigManager.save()); ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> ConfigManager.save());
ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> { ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
if (SaturnClientConfig.saturnTitleScreen.value && screen instanceof TitleScreen if (SaturnClientConfig.saturnTitleScreen.value && screen instanceof TitleScreen
&& !(screen instanceof SaturnMenu)) { && !(screen instanceof TitleMenu)) {
client.setScreen(new SaturnTitleScreen()); client.setScreen(new TitleMenu());
} }
}); });
@@ -7,35 +7,30 @@ import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.Textures; import org.saturnclient.ui.Textures;
import org.saturnclient.ui.animations.FadeIn; import org.saturnclient.ui.animations.FadeIn;
import net.minecraft.client.font.TextRenderer; import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.ColorHelper;
public class SaturnClientConfig { public class SaturnClientConfig {
public static ConfigManager config = new ConfigManager("Saturn Client"); public static ConfigManager config;
public static Property<Integer> color = config.property( public static Property<Integer> color =
"Primary color",
new Property<>( new Property<>(
ColorHelper.getArgb(255, 251, 60, 79), ColorHelper.getArgb(255, 251, 60, 79),
Property.PropertyType.HEX)); Property.PropertyType.HEX);
public static Property<Integer> normal = config.property( public static Property<Integer> normal =
"Default color",
new Property<>( new Property<>(
ColorHelper.getArgb(255, 182, 182, 182), ColorHelper.getArgb(255, 182, 182, 182),
Property.PropertyType.HEX)); Property.PropertyType.HEX);
public static Property<Boolean> realisticLogo = config.property( public static Property<Boolean> realisticLogo =
"Realistic logo", new Property<>(false);
new Property<>(false));
public static Property<Boolean> saturnTitleScreen = config.property( public static Property<Boolean> saturnTitleScreen =
"Saturn client title screen", new Property<>(true);
new Property<>(true));
public static int WHITE = ColorHelper.getArgb(255, 255, 255, 255); public static int WHITE = ColorHelper.getArgb(255, 255, 255, 255);
public static TextRenderer textRenderer = null;
public static int getWhite(float alpha) { public static int getWhite(float alpha) {
return ((int) (alpha * 255) << 24) | (normal.value & 0x00FFFFFF); return ((int) (alpha * 255) << 24) | (normal.value & 0x00FFFFFF);
@@ -56,4 +51,30 @@ public class SaturnClientConfig {
public static String getSaturnIndicator() { public static String getSaturnIndicator() {
return realisticLogo.value ? "" : ""; return realisticLogo.value ? "" : "";
} }
/*
* Gets the icon color of a specific individual, here are the different colors
*
* - Owner: Dark Red
* - Admin: Red
* - Partners: Gold
* - Contributor: Aqua
* - Other/player: White
*/
public static Formatting getIconColor(String uuid) {
if (uuid.equals("d362a04228bd49e1a807ae74dbe8aba9")) {
return Formatting.DARK_RED; // Owner
}
return Formatting.WHITE;
}
public static void init() {
config = new ConfigManager("Saturn Client");
config.property("Primary color", color);
config.property("Default color", normal);
config.property("Realistic logo", realisticLogo);
config.property("Saturn client title screen", saturnTitleScreen);
}
} }
@@ -3,7 +3,6 @@ package org.saturnclient.saturnclient.auth;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.client.MinecraftClient;
import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.saturnclient.cosmetics.Hats;
import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
@@ -22,13 +21,12 @@ public class Auth {
ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> close()); ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> close());
try { try {
MinecraftClient client = MinecraftClient.getInstance(); if (SaturnClient.client.getSession() == null) {
if (client.getSession() == null) {
SaturnClient.LOGGER.error("No active Minecraft session found"); SaturnClient.LOGGER.error("No active Minecraft session found");
return false; return false;
} }
String accessToken = client.getSession().getAccessToken(); String accessToken = SaturnClient.client.getSession().getAccessToken();
SaturnClient.LOGGER.info("Authenticating"); SaturnClient.LOGGER.info("Authenticating");
Network.init(); Network.init();
@@ -55,7 +53,7 @@ public class Auth {
Cloaks.loadCloak(uuid); Cloaks.loadCloak(uuid);
playerNames.put(client.getSession().getUsername(), uuid); playerNames.put(SaturnClient.client.getSession().getUsername(), uuid);
afterAuth(); afterAuth();
@@ -119,17 +117,22 @@ public class Auth {
private static void startPingThread() { private static void startPingThread() {
pingThread = new Thread(() -> { pingThread = new Thread(() -> {
try { try {
while (running) { while (running && !Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(25000); // 25 seconds Thread.sleep(25000); // 25 seconds
if (running) { if (running) {
Network.write("ping"); Network.write("ping");
} }
}
} catch (InterruptedException e) { } catch (InterruptedException e) {
SaturnClient.LOGGER.warn("Ping thread interrupted", e); Thread.currentThread().interrupt(); // Restore interrupt status
break; // Exit the loop on interruption
}
}
} catch (Exception e) { } catch (Exception e) {
if (!(e instanceof InterruptedException)) {
SaturnClient.LOGGER.error("Error in ping thread", e); SaturnClient.LOGGER.error("Error in ping thread", e);
} }
}
}); });
pingThread.setDaemon(true); pingThread.setDaemon(true);
@@ -184,7 +187,7 @@ public class Auth {
public static void sendReload() { public static void sendReload() {
for (Map.Entry<String, String> player : playerNames.entrySet()) { for (Map.Entry<String, String> player : playerNames.entrySet()) {
if (players.containsKey(player.getValue()) && !player.getValue().equals(uuid)) { if (players.containsKey(player.getValue()) && !player.getValue().equals(uuid)) {
MinecraftClient.getInstance().player.networkHandler SaturnClient.client.player.networkHandler
.sendChatCommand("msg " + player.getKey() + " " .sendChatCommand("msg " + player.getKey() + " "
+ "$SATURN_RELOAD if you are seeing this as a player, please report this to https://github.com/saturnclientmc/saturnclient/issues"); + "$SATURN_RELOAD if you are seeing this as a player, please report this to https://github.com/saturnclientmc/saturnclient/issues");
; ;
@@ -2,8 +2,9 @@ package org.saturnclient.saturnclient.auth;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.MinecraftClient;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -19,7 +20,7 @@ public class PlayerTracker {
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
trackedPlayers.clear(); trackedPlayers.clear();
client.execute(() -> { client.execute(() -> {
checkForNewPlayers(MinecraftClient.getInstance()); checkForNewPlayers(SaturnClient.client);
}); });
}); });
@@ -12,13 +12,12 @@ import java.nio.file.Files;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import net.minecraft.client.MinecraftClient;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
public class ConfigManager { public class ConfigManager {
private static File configFile = new File( private static File configFile = new File(
MinecraftClient.getInstance().runDirectory, SaturnClient.client.runDirectory,
"saturn.json"); "saturn.json");
private static Map<String, Map<String, Property<?>>> properties = new HashMap<>(); private static Map<String, Map<String, Property<?>>> properties = new HashMap<>();
@@ -27,6 +26,7 @@ public class ConfigManager {
public ConfigManager(String namespace) { public ConfigManager(String namespace) {
currentMap = new LinkedHashMap<>(); currentMap = new LinkedHashMap<>();
properties.put(namespace, currentMap); properties.put(namespace, currentMap);
System.out.println("Created namespace: " + namespace);
} }
public ConfigManager(ConfigManager config, String namespace) { public ConfigManager(ConfigManager config, String namespace) {
@@ -36,10 +36,12 @@ public class ConfigManager {
config.property(namespace, namespaceProperty); config.property(namespace, namespaceProperty);
// Update the parent's state // Update the parent's state
config.currentMap.put(namespace, namespaceProperty); config.currentMap.put(namespace, namespaceProperty);
System.out.println("Created sub-namespace: " + namespace);
} }
// Generic method to store any type of property // Generic method to store any type of property
public <T> Property<T> property(String name, Property<T> value) { public <T> Property<T> property(String name, Property<T> value) {
System.out.println("Adding property: " + name);
currentMap.put(name, value); currentMap.put(name, value);
return value; return value;
} }
@@ -56,6 +58,7 @@ public class ConfigManager {
new String(Files.readAllBytes(configFile.toPath()))).getAsJsonObject(); new String(Files.readAllBytes(configFile.toPath()))).getAsJsonObject();
for (String namespace : properties.keySet()) { for (String namespace : properties.keySet()) {
SaturnClient.LOGGER.info("Loading namespace: " + namespace);
JsonElement configElement = jsonObject.get(namespace); JsonElement configElement = jsonObject.get(namespace);
if (configElement == null) if (configElement == null)
@@ -77,6 +80,8 @@ public class ConfigManager {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static void loadProperties(JsonObject config, Map<String, Property<?>> propertyMap) { private static void loadProperties(JsonObject config, Map<String, Property<?>> propertyMap) {
SaturnClient.LOGGER.info("Loading properties: " + propertyMap);
for (String propertyName : propertyMap.keySet()) { for (String propertyName : propertyMap.keySet()) {
JsonElement c = config.get(propertyName); JsonElement c = config.get(propertyName);
@@ -0,0 +1,11 @@
package org.saturnclient.saturnclient.config;
public class NamedProperty<T> {
public String name;
public Property<T> prop;
public NamedProperty(String name, Property<T> value) {
this.name = name;
this.prop = value;
}
}
@@ -139,4 +139,19 @@ public class Property<T> {
public static boolean valueIsNamespace(Object obj) { public static boolean valueIsNamespace(Object obj) {
return obj instanceof Map; return obj instanceof Map;
} }
@SuppressWarnings("unchecked")
public void setValue(Object value) {
this.value = (T) value;
}
@SuppressWarnings("unchecked")
public void setValue(Object value, Object defaultValue) {
this.value = (T) value;
this.defaultValue = (T) defaultValue;
}
public NamedProperty<T> named(String name) {
return new NamedProperty<>(name, this);
}
} }
@@ -0,0 +1,224 @@
package org.saturnclient.saturnclient.config;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.saturnclient.saturnclient.SaturnClient;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
public class ThemeManager {
private static File themeFile = new File(
SaturnClient.client.runDirectory,
"saturn.theme.json");
private static Map<String, Map<String, Property<?>>> properties = new HashMap<>();
// private Map<String, Map<String, Property<?>>> states;
private Map<String, Property<?>> currentStyling;
private String state;
private String[] states;
private String namespace;
public ThemeManager(String namespace, String... states) {
// this.states = new LinkedHashMap<>();
this.namespace = namespace;
this.states = states;
currentStyling = new LinkedHashMap<>();
properties.put(namespace, new LinkedHashMap<>());
for (String s : states) {
properties.put(namespace+"@"+s, new LinkedHashMap<>());
}
}
public void setState(String state) {
this.state = state;
if (this.state != null) {
for (Map.Entry<String, Property<?>> tProp : properties.get(namespace+"@"+state).entrySet()) {
currentStyling.get(tProp.getKey()).setValue(tProp.getValue().value);
}
} else {
for (Map.Entry<String, Property<?>> tProp : properties.get(namespace).entrySet()) {
currentStyling.get(tProp.getKey()).setValue(tProp.getValue().value);
}
}
}
// Generic method to store any type of property
public <T> Property<T> property(String name, Property<T> prop) {
for (String state : states) {
properties.get(namespace+"@"+state).put(name, new Property<T>(prop.value));
}
properties.get(namespace).put(name, new Property<T>(prop.value));
currentStyling.put(name, prop);
return prop;
}
public <T> void propertyStateDefault(String state, String name, T value) {
properties.get(namespace+"@"+state).get(name).setValue(value, value); // sets the current and default value
}
public static void load() {
try {
SaturnClient.LOGGER.info("Starting to load theme...");
if (!themeFile.exists()) {
themeFile.createNewFile();
Files.write(themeFile.toPath(), "{}".getBytes());
}
JsonObject jsonObject = JsonParser.parseString(
new String(Files.readAllBytes(themeFile.toPath()))).getAsJsonObject();
for (String namespace : properties.keySet()) {
JsonElement themeElement = jsonObject.get(namespace);
if (themeElement == null)
continue;
JsonObject theme = jsonObject.get(namespace).getAsJsonObject();
if (theme == null) {
continue;
}
Map<String, Property<?>> propertyMap = properties.get(namespace);
loadProperties(theme, propertyMap);
}
} catch (IOException e) {
SaturnClient.LOGGER.error("Error reading the theme file", e);
}
}
@SuppressWarnings("unchecked")
private static void loadProperties(JsonObject theme, Map<String, Property<?>> propertyMap) {
for (String propertyName : propertyMap.keySet()) {
JsonElement c = theme.get(propertyName);
if (c == null) {
continue;
}
Property<?> p = propertyMap.get(propertyName);
if (p.matchesJson(c)) {
if (p.getType() == Property.PropertyType.NAMESPACE) {
// Handle nested namespace
JsonObject nestedTheme = c.getAsJsonObject();
Map<String, Property<?>> nestedProperties = p.getNamespaceValue();
loadProperties(nestedTheme, nestedProperties);
} else {
// Handle regular properties
switch (p.getType()) {
case BOOLEAN:
((Property<Boolean>) p).value = c.getAsBoolean();
break;
case INTEGER:
((Property<Integer>) p).value = c.getAsInt();
break;
case FLOAT:
((Property<Float>) p).value = c.getAsFloat();
break;
case STRING:
((Property<String>) p).value = c.getAsString();
break;
case HEX:
((Property<Integer>) p).value = c.getAsInt();
break;
default:
break;
}
}
} else {
SaturnClient.LOGGER.warn(
"Property does not match JSON: " + propertyName);
}
}
}
public static void save() {
try {
SaturnClient.LOGGER.info("Starting to save theme...");
JsonObject jsonObject = new JsonObject();
// Iterate through all namespaces and their properties
for (String namespace : properties.keySet()) {
JsonObject namespaceTheme = new JsonObject();
Map<String, Property<?>> propertyMap = properties.get(namespace);
// Save properties for this namespace
saveProperties(namespaceTheme, propertyMap);
// Add the namespace theme to the main JSON object
jsonObject.add(namespace, namespaceTheme);
}
// Format the json so it can easily be edited
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String formattedJson = gson.toJson(jsonObject);
// Write the JSON object to the theme file
Files.write(themeFile.toPath(), formattedJson.getBytes());
SaturnClient.LOGGER.info("Theme saved successfully.");
} catch (IOException e) {
SaturnClient.LOGGER.error("Error saving the theme file", e);
}
}
@SuppressWarnings("unchecked")
private static void saveProperties(JsonObject theme, Map<String, Property<?>> propertyMap) {
// Iterate through each property in the namespace
for (String propertyName : propertyMap.keySet()) {
Property<?> property = propertyMap.get(propertyName);
JsonElement propertyValue = null;
if (property.getType() == Property.PropertyType.NAMESPACE) {
// Handle nested namespace
JsonObject nestedTheme = new JsonObject();
Map<String, Property<?>> nestedProperties = (Map<String, Property<?>>) property.value;
saveProperties(nestedTheme, nestedProperties);
propertyValue = nestedTheme;
} else {
// Convert the property value based on its type
switch (property.getType()) {
case BOOLEAN:
propertyValue = new JsonPrimitive((Boolean) property.value);
break;
case INTEGER:
propertyValue = new JsonPrimitive((Integer) property.value);
break;
case FLOAT:
propertyValue = new JsonPrimitive((Float) property.value);
break;
case STRING:
propertyValue = new JsonPrimitive((String) property.value);
break;
case HEX:
propertyValue = new JsonPrimitive((Integer) property.value);
break;
default:
SaturnClient.LOGGER.warn(
"Unknown property type for: " + propertyName);
break;
}
}
if (propertyValue != null) {
theme.add(propertyName, propertyValue);
}
}
}
}
@@ -3,7 +3,7 @@ package org.saturnclient.saturnclient.cosmetics;
import org.saturnclient.saturnclient.auth.SaturnPlayer; import org.saturnclient.saturnclient.auth.SaturnPlayer;
import org.saturnclient.saturnclient.auth.Auth; import org.saturnclient.saturnclient.auth.Auth;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRenderer;
@@ -48,7 +48,7 @@ public class HatFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState,
customHat.set(DataComponentTypes.EQUIPPABLE, customHat.set(DataComponentTypes.EQUIPPABLE,
EquippableComponent.builder(EquipmentSlot.HEAD).build()); EquippableComponent.builder(EquipmentSlot.HEAD).build());
ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer(); ItemRenderer itemRenderer = SaturnClient.client.getItemRenderer();
itemRenderer.renderItem( itemRenderer.renderItem(
customHat, customHat,
@@ -96,7 +96,7 @@ public class Cloaks {
} }
// Register textures on main thread // Register textures on main thread
net.minecraft.client.MinecraftClient.getInstance().execute(() -> { SaturnClient.client.execute(() -> {
try { try {
List<AnimatedCloakData> animatedFrames = new ArrayList<>(); List<AnimatedCloakData> animatedFrames = new ArrayList<>();
for (int i = 0; i < frameCount; i++) { for (int i = 0; i < frameCount; i++) {
@@ -118,7 +118,7 @@ public class Cloaks {
} }
}).start(); }).start();
} else { } else {
net.minecraft.client.MinecraftClient.getInstance().execute(() -> loadStaticCloak(player.cloak + ".png")); SaturnClient.client.execute(() -> loadStaticCloak(player.cloak + ".png"));
} }
} }
} }
@@ -1,6 +1,6 @@
package org.saturnclient.saturnclient.cosmetics.cloaks.utils; package org.saturnclient.saturnclient.cosmetics.cloaks.utils;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.texture.NativeImage; import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture; import net.minecraft.client.texture.NativeImageBackedTexture;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@@ -20,7 +20,7 @@ public class IdentifierUtils {
ByteBuffer bb = BufferUtils.createByteBuffer(bytes.length).put(bytes); ByteBuffer bb = BufferUtils.createByteBuffer(bytes.length).put(bytes);
bb.flip(); bb.flip();
NativeImageBackedTexture nibt = new NativeImageBackedTexture(NativeImage.read(bb)); NativeImageBackedTexture nibt = new NativeImageBackedTexture(NativeImage.read(bb));
MinecraftClient.getInstance().getTextureManager().registerTexture(i, nibt); SaturnClient.client.getTextureManager().registerTexture(i, nibt);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -3,10 +3,12 @@ package org.saturnclient.saturnclient.event;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.option.Perspective; // import net.minecraft.client.option.Perspective;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
import org.saturnclient.saturnclient.menus.SaturnMenu;
import org.saturnclient.saturnmods.mods.FreeLook; // import org.saturnclient.modules.mods.FreeLook;
import org.saturnclient.ui2.screens.ShiftMenu;
// import org.saturnclient.saturnclient.menus.SaturnMenu;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
/** /**
@@ -19,9 +21,9 @@ public class KeyInputHandler {
private static final int DEFAULT_MENU_KEY = GLFW.GLFW_KEY_RIGHT_SHIFT; private static final int DEFAULT_MENU_KEY = GLFW.GLFW_KEY_RIGHT_SHIFT;
private static KeyBinding mainMenuKeyBinding; private static KeyBinding mainMenuKeyBinding;
private static final String FREELOOK_KEY_ID = "key.saturnclient.freelook"; // private static final String FREELOOK_KEY_ID = "key.saturnclient.freelook";
private static final int FREELOOK_KEY = GLFW.GLFW_KEY_M; // private static final int FREELOOK_KEY = GLFW.GLFW_KEY_M;
private static KeyBinding freelookKeyBinding; // private static KeyBinding freelookKeyBinding;
/** /**
* Registers all keybindings and their associated event handlers. * Registers all keybindings and their associated event handlers.
@@ -35,38 +37,39 @@ public class KeyInputHandler {
DEFAULT_MENU_KEY, DEFAULT_MENU_KEY,
KEY_CATEGORY)); KEY_CATEGORY));
freelookKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( // freelookKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
FREELOOK_KEY_ID, // FREELOOK_KEY_ID,
InputUtil.Type.KEYSYM, // InputUtil.Type.KEYSYM,
FREELOOK_KEY, // FREELOOK_KEY,
KEY_CATEGORY)); // KEY_CATEGORY));
// Register the event handler for the main menu key // Register the event handler for the main menu key
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (mainMenuKeyBinding.wasPressed()) { if (mainMenuKeyBinding.wasPressed()) {
client.setScreen(new SaturnMenu()); client.setScreen(new ShiftMenu());
} else if (freelookKeyBinding.wasPressed() && FreeLook.enabled.value && FreeLook.toggle.value) {
FreeLook.isFreeLooking = !FreeLook.isFreeLooking;
if (FreeLook.isFreeLooking) {
FreeLook.lastPerspective = client.options.getPerspective();
client.options.setPerspective(Perspective.THIRD_PERSON_BACK);
} else if (FreeLook.lastPerspective != null) {
client.options.setPerspective(FreeLook.lastPerspective);
FreeLook.lastPerspective = null;
}
} else if (FreeLook.enabled.value && !FreeLook.toggle.value) {
if (freelookKeyBinding.isPressed()) {
if (!FreeLook.isFreeLooking) {
FreeLook.lastPerspective = client.options.getPerspective();
client.options.setPerspective(Perspective.THIRD_PERSON_BACK);
FreeLook.isFreeLooking = true;
}
} else if (FreeLook.isFreeLooking && FreeLook.lastPerspective != null) {
client.options.setPerspective(FreeLook.lastPerspective);
FreeLook.isFreeLooking = false;
FreeLook.lastPerspective = null;
}
} }
// else if (freelookKeyBinding.wasPressed() && FreeLook.enabled.value && FreeLook.toggle.value) {
// FreeLook.isFreeLooking = !FreeLook.isFreeLooking;
// if (FreeLook.isFreeLooking) {
// FreeLook.lastPerspective = client.options.getPerspective();
// client.options.setPerspective(Perspective.THIRD_PERSON_BACK);
// } else if (FreeLook.lastPerspective != null) {
// client.options.setPerspective(FreeLook.lastPerspective);
// FreeLook.lastPerspective = null;
// }
// } else if (FreeLook.enabled.value && !FreeLook.toggle.value) {
// if (freelookKeyBinding.isPressed()) {
// if (!FreeLook.isFreeLooking) {
// FreeLook.lastPerspective = client.options.getPerspective();
// client.options.setPerspective(Perspective.THIRD_PERSON_BACK);
// FreeLook.isFreeLooking = true;
// }
// } else if (FreeLook.isFreeLooking && FreeLook.lastPerspective != null) {
// client.options.setPerspective(FreeLook.lastPerspective);
// FreeLook.isFreeLooking = false;
// FreeLook.lastPerspective = null;
// }
// }
}); });
} }
} }
@@ -5,11 +5,11 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.saturnclient.modules.HudMod;
import org.saturnclient.modules.ModDimensions;
import org.saturnclient.modules.ModManager;
import org.saturnclient.modules.Module;
import org.saturnclient.saturnclient.config.ConfigManager; import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnmods.HudMod;
import org.saturnclient.saturnmods.ModDimensions;
import org.saturnclient.saturnmods.ModManager;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.SaturnUi; import org.saturnclient.ui.SaturnUi;
import java.util.ArrayList; import java.util.ArrayList;
@@ -24,7 +24,7 @@ public class HudEditor extends Screen {
public HudEditor() { public HudEditor() {
super(Text.literal("HUD Editor")); super(Text.literal("HUD Editor"));
for (SaturnMod m : ModManager.MODS) { for (Module m : ModManager.MODS) {
if (m.isEnabled() && m instanceof HudMod) { if (m.isEnabled() && m instanceof HudMod) {
hudMods.add((HudMod) m); hudMods.add((HudMod) m);
} }
@@ -1,11 +1,12 @@
package org.saturnclient.saturnclient.menus; package org.saturnclient.saturnclient.menus;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.saturnclient.modules.ModManager;
import org.saturnclient.modules.Module;
import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.config.ConfigManager; import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property; import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.ModManager;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.SaturnUi; import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.Textures; import org.saturnclient.ui.Textures;
import org.saturnclient.ui.components.SaturnModComp; import org.saturnclient.ui.components.SaturnModComp;
@@ -117,7 +118,7 @@ public class ModMenu extends SaturnUi {
String[] searchTokens = search.value.toLowerCase().split("\\ "); String[] searchTokens = search.value.toLowerCase().split("\\ ");
outer: for (SaturnMod mod : ModManager.MODS) { outer: for (Module mod : ModManager.MODS) {
String modName = mod.getName().toLowerCase(); String modName = mod.getName().toLowerCase();
for (String searchToken : searchTokens) { for (String searchToken : searchTokens) {
if (!modName.contains(searchToken)) { if (!modName.contains(searchToken)) {
@@ -1,77 +1,13 @@
package org.saturnclient.saturnclient.menus; package org.saturnclient.saturnclient.menus;
import net.minecraft.client.MinecraftClient; import org.saturnclient.ui2.SaturnScreen;
import net.minecraft.text.Text;
import org.saturnclient.saturnclient.SaturnClientConfig; public class SaturnMenu extends SaturnScreen {
import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.Textures;
import org.saturnclient.ui.animations.FadeIn;
import org.saturnclient.ui.animations.Slide;
import org.saturnclient.ui.widgets.SaturnButton;
import org.saturnclient.ui.widgets.SaturnImage;
import org.saturnclient.ui.widgets.SaturnImageButton;
public class SaturnMenu extends SaturnUi {
public SaturnMenu() { public SaturnMenu() {
super(Text.literal("Saturn Client")); super("Saturn Client");
} }
@Override @Override
protected void init() { public void ui() {
SaturnClientConfig.textRenderer = MinecraftClient.getInstance().textRenderer;
int buttonWidth = 96;
int buttonHeight = 25;
draw(
new SaturnButton("Mods", () -> {
client.setScreen(new ModMenu());
})
.setX((width - buttonWidth) / 2)
.setY((height - buttonHeight) / 2)
.setWidth(buttonWidth)
.setHeight(buttonHeight)
.setAnimations(new FadeIn(2)));
draw(
new SaturnImageButton(Textures.HUD_ICON, 14, 14, () -> {
client.setScreen(new HudEditor());
})
.setX((width - buttonWidth - (buttonHeight * 2) - 6) / 2)
.setY((height - buttonHeight) / 2)
.setWidth(buttonHeight)
.setHeight(buttonHeight)
.setAnimations(new FadeIn(2)));
draw(
new SaturnImageButton(Textures.COSMETICS, 14, 14, () -> {
client.setScreen(new CloaksMenu());
})
.setX((width / 2) + (buttonWidth / 2) + 3)
.setY((height - buttonHeight) / 2)
.setWidth(buttonHeight)
.setHeight(buttonHeight)
.setAnimations(new FadeIn(2)));
int logoSize = 49;
draw(
new SaturnImage(Textures.LOGO_TEXT)
.setX((width - logoSize) / 2)
.setY((height - 8) / 2 - 23)
.setWidth(logoSize)
.setHeight(8)
.setAnimations(new FadeIn(2)));
draw(
new SaturnImage(SaturnClientConfig.getLogo())
.setX((width - logoSize) / 2)
.setY(height / 2 - logoSize - 24)
.setWidth(logoSize)
.setHeight(logoSize)
.setAnimations(new Slide(2, 14)));
super.init();
} }
} }
@@ -7,6 +7,7 @@ import org.saturnclient.ui.animations.FadeIn;
import org.saturnclient.ui.animations.Slide; import org.saturnclient.ui.animations.Slide;
import org.saturnclient.ui.widgets.SaturnButton; import org.saturnclient.ui.widgets.SaturnButton;
import org.saturnclient.ui.widgets.SaturnImage; import org.saturnclient.ui.widgets.SaturnImage;
import org.saturnclient.ui2.screens.ShiftMenu;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.option.OptionsScreen;
@@ -69,7 +70,7 @@ public class SaturnTitleScreen extends SaturnUi {
bY += 20; bY += 20;
draw(new SaturnButton("SATURN OPTIONS", () -> { draw(new SaturnButton("SATURN OPTIONS", () -> {
client.setScreen(new SaturnMenu()); client.setScreen(new ShiftMenu());
}).setBold(true).setWidth(210).setHeight(26).setX(bX).setY(bY).setScale(0.69f)); }).setBold(true).setWidth(210).setHeight(26).setX(bX).setY(bY).setScale(0.69f));
super.init(); super.init();
@@ -1,47 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import org.saturnclient.saturnclient.mod_utils.CameraOverriddenEntity;
import org.saturnclient.saturnmods.mods.FreeLook;
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.Shadow;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.Entity;
import net.minecraft.world.BlockView;
@Mixin(Camera.class)
public abstract class CameraMixin {
@Unique
boolean firstTime = true;
@Shadow
protected abstract void setRotation(float yaw, float pitch);
@Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V", ordinal = 1, shift = At.Shift.AFTER))
public void lockRotation(BlockView focusedBlock, Entity cameraEntity, boolean isThirdPerson, boolean isFrontFacing,
float tickDelta, CallbackInfo ci) {
if (FreeLook.isFreeLooking && cameraEntity instanceof ClientPlayerEntity) {
CameraOverriddenEntity cameraOverriddenEntity = (CameraOverriddenEntity) cameraEntity;
if (firstTime && MinecraftClient.getInstance().player != null) {
cameraOverriddenEntity.freelook$setCameraPitch(MinecraftClient.getInstance().player.getPitch());
cameraOverriddenEntity.freelook$setCameraYaw(MinecraftClient.getInstance().player.getYaw());
firstTime = false;
}
this.setRotation(cameraOverriddenEntity.freelook$getCameraYaw(),
cameraOverriddenEntity.freelook$getCameraPitch());
}
if (!FreeLook.isFreeLooking && cameraEntity instanceof ClientPlayerEntity) {
firstTime = true;
}
}
}
@@ -1,47 +0,0 @@
/*
* Code from: https://github.com/Selyss
* Repo: https://github.com/Selyss/CrosshairIndicator/tree/main
*/
package org.saturnclient.saturnclient.mixin;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Final;
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;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.gui.DrawContext;
@Mixin(InGameHud.class)
public class Crosshair {
@Shadow
@Final
private MinecraftClient client;
@Unique
Identifier textureLocation = Identifier.of("saturnclient", "textures/gui/hud/crosshair_range.png");
@Inject(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIII)V", ordinal = 0))
private void drawCrosshair(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
if (org.saturnclient.saturnmods.mods.Crosshair.enabled.value
&& org.saturnclient.saturnmods.mods.Crosshair.range_indicator.value
&& this.client.targetedEntity != null
&& this.client.targetedEntity.isAlive()) {
RenderSystem.setShaderTexture(0, textureLocation);
int scaledWidth = 15;
int scaledHeight = 15;
context.drawTexture(RenderLayer::getCrosshair, textureLocation,
(context.getScaledWindowWidth() - scaledWidth) / 2,
(context.getScaledWindowHeight() - scaledHeight) / 2, 0.0F, 0.0F, scaledWidth, scaledHeight,
scaledWidth, scaledHeight);
}
}
}
@@ -0,0 +1,12 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.VertexConsumerProvider;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(DrawContext.class)
public interface DrawContextAccessor {
@Accessor("vertexConsumers")
VertexConsumerProvider.Immediate getVertexConsumers();
}
@@ -1,62 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.MathHelper;
import org.saturnclient.saturnclient.mod_utils.CameraOverriddenEntity;
import org.saturnclient.saturnmods.mods.FreeLook;
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;
@Mixin(Entity.class)
public class EntityMixin implements CameraOverriddenEntity {
@Unique
private float cameraPitch;
@Unique
private float cameraYaw;
@Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true)
public void changeCameraLookDirection(double xDelta, double yDelta, CallbackInfo ci) {
// noinspection ConstantValue// IntelliJ is incorrect here, this code block is
// reachable
if (FreeLook.isFreeLooking && (Object) this instanceof ClientPlayerEntity) {
double pitchDelta = (yDelta * 0.15);
double yawDelta = (xDelta * 0.15);
this.cameraPitch = MathHelper.clamp(this.cameraPitch + (float) pitchDelta, -90.0f, 90.0f);
this.cameraYaw += (float) yawDelta;
ci.cancel();
}
}
@Override
@Unique
public float freelook$getCameraPitch() {
return this.cameraPitch;
}
@Override
@Unique
public float freelook$getCameraYaw() {
return this.cameraYaw;
}
@Override
@Unique
public void freelook$setCameraPitch(float pitch) {
this.cameraPitch = pitch;
}
@Override
@Unique
public void freelook$setCameraYaw(float yaw) {
this.cameraYaw = yaw;
}
}
@@ -1,6 +1,6 @@
package org.saturnclient.saturnclient.mixin; package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.font.TextRenderer.TextLayerType; import net.minecraft.client.font.TextRenderer.TextLayerType;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
@@ -9,7 +9,9 @@ import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState; import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.SaturnClientConfig;
@@ -34,20 +36,32 @@ public abstract class NameTagMixin<S extends EntityRenderState> {
@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) @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, private void onRenderLabelIfPresent(S state, Text text, MatrixStack matrices,
VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
if (isSaturn(state)) {
renderLabel(state, Text.literal(SaturnClientConfig.getSaturnIndicator()).append(text), matrices, String uuid = isSaturn(state);
if (uuid != null) {
MutableText iconText = Text.literal(SaturnClientConfig.getSaturnIndicator())
.styled(style -> style.withColor(SaturnClientConfig.getIconColor(uuid)));
Text nameText = text.copy().styled(style -> style.withColor(Formatting.WHITE));
renderLabel(state, iconText.append(nameText), matrices,
vertexConsumers, light); vertexConsumers, light);
ci.cancel(); ci.cancel();
} }
} }
private boolean isSaturn(S state) { private String isSaturn(S state) {
if (state instanceof PlayerEntityRenderState) { if (state instanceof PlayerEntityRenderState) {
String name = ((PlayerEntityRenderState) state).name; String name = ((PlayerEntityRenderState) state).name;
String uuid = Auth.playerNames.get(name); String uuid = Auth.playerNames.get(name);
return uuid != null && Auth.players.containsKey(uuid); if (Auth.players.containsKey(uuid)) {
return uuid;
} }
return false; }
return null;
} }
private void renderLabel(S state, Text text, MatrixStack matrices, private void renderLabel(S state, Text text, MatrixStack matrices,
@@ -61,9 +75,9 @@ public abstract class NameTagMixin<S extends EntityRenderState> {
matrices.multiply(this.dispatcher.getRotation()); matrices.multiply(this.dispatcher.getRotation());
matrices.scale(0.025F, -0.025F, 0.025F); matrices.scale(0.025F, -0.025F, 0.025F);
Matrix4f matrix4f = matrices.peek().getPositionMatrix(); Matrix4f matrix4f = matrices.peek().getPositionMatrix();
TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; TextRenderer textRenderer = SaturnClient.client.textRenderer;
float f = (float) (-textRenderer.getWidth(text)) / 2.0F; float f = (float) (-textRenderer.getWidth(text)) / 2.0F;
int j = (int) (MinecraftClient.getInstance().options.getTextBackgroundOpacity(0.25F) * 255.0F) << 24; int j = (int) (SaturnClient.client.options.getTextBackgroundOpacity(0.25F) * 255.0F) << 24;
textRenderer.draw(text, f, (float) i, -2130706433, false, matrix4f, vertexConsumers, textRenderer.draw(text, f, (float) i, -2130706433, false, matrix4f, vertexConsumers,
bl ? TextLayerType.SEE_THROUGH : TextLayerType.NORMAL, j, light); bl ? TextLayerType.SEE_THROUGH : TextLayerType.NORMAL, j, light);
if (bl) { if (bl) {
@@ -1,7 +1,10 @@
package org.saturnclient.saturnclient.mixin; package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.auth.Auth; import org.saturnclient.saturnclient.auth.Auth;
@@ -29,7 +32,11 @@ public abstract class TabListMixin {
String name = profile.getName(); String name = profile.getName();
String uuid = profile.getId().toString().replaceAll("-", ""); String uuid = profile.getId().toString().replaceAll("-", "");
return Text.literal( MutableText iconText = Text.literal(SaturnClientConfig.getSaturnIndicator())
Auth.players.containsKey(uuid) ? SaturnClientConfig.getSaturnIndicator() + name : name); .styled(style -> style.withColor(SaturnClientConfig.getIconColor(uuid)));
Text nameText = Text.literal(name).styled(style -> style.withColor(Formatting.WHITE));
return Auth.players.containsKey(uuid) ? iconText.append(nameText) : Text.literal(name);
} }
} }
@@ -1,37 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.particle.AnimatedParticle;
import net.minecraft.client.particle.SpriteProvider;
import net.minecraft.client.particle.TotemParticle;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.ColorHelper;
import org.saturnclient.saturnmods.mods.Particles;
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(TotemParticle.class)
public class TotemParticleMixin extends AnimatedParticle {
protected TotemParticleMixin(ClientWorld world, double x, double y, double z, SpriteProvider spriteProvider,
float upwardsAcceleration) {
super(world, x, y, z, spriteProvider, upwardsAcceleration);
}
@Inject(at = @At("TAIL"), method = "<init>")
private void colorChanger(ClientWorld world, double x, double y, double z, double velocityX, double velocityY,
double velocityZ, SpriteProvider spriteProvider, CallbackInfo ci) {
if (Particles.enabled.value && Particles.totem_enabled.value) {
if (this.random.nextInt(2) == 0) {
this.setColor(ColorHelper.getRedFloat(Particles.totem_1.value),
ColorHelper.getGreenFloat(Particles.totem_1.value),
ColorHelper.getBlueFloat(Particles.totem_1.value));
} else {
this.setColor(ColorHelper.getRedFloat(Particles.totem_2.value),
ColorHelper.getGreenFloat(Particles.totem_2.value),
ColorHelper.getBlueFloat(Particles.totem_2.value));
}
}
}
}
@@ -1,9 +0,0 @@
package org.saturnclient.saturnclient.mod_utils;
public interface CameraOverriddenEntity {
float freelook$getCameraPitch();
float freelook$getCameraYaw();
void freelook$setCameraPitch(float pitch);
void freelook$setCameraYaw(float yaw);
}
@@ -1,50 +0,0 @@
package org.saturnclient.saturnmods;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.util.math.MatrixStack;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.menus.HudEditor;
import org.saturnclient.saturnmods.mods.*;
public class ModManager {
public static SaturnMod[] MODS = {
new Coordinates(),
new ArmorDisplay(),
new FpsDisplay(),
new Particles(),
new Crosshair(),
new FreeLook()
};
public static void init() {
HudRenderCallback.EVENT.register((context, _o) -> {
MinecraftClient client = MinecraftClient.getInstance();
TextRenderer textRenderer = client.textRenderer;
if (textRenderer != null &&
!(client.currentScreen instanceof HudEditor)) {
SaturnClientConfig.textRenderer = textRenderer;
for (SaturnMod m : MODS) {
if (m instanceof HudMod && m.isEnabled()) {
ModDimensions dim = ((HudMod) m).getDimensions();
MatrixStack matrices = context.getMatrices();
matrices.push();
matrices.translate(dim.x.value, (float) dim.y.value, 0);
matrices.scale(dim.scale.value, dim.scale.value, 1.0f);
((HudMod) m).render(context);
matrices.pop();
}
}
}
});
}
}
@@ -1,17 +0,0 @@
package org.saturnclient.saturnmods;
import org.saturnclient.saturnclient.config.ConfigManager;
import net.minecraft.util.Identifier;
public interface SaturnMod {
public boolean isEnabled();
public void setEnabled(boolean e);
public String getName();
public Identifier getIconTexture();
public ConfigManager getConfig();
}
@@ -1,130 +0,0 @@
package org.saturnclient.saturnmods.mods;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.HudMod;
import org.saturnclient.saturnmods.ModDimensions;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.Textures;
public class ArmorDisplay implements SaturnMod, HudMod {
private static ConfigManager config = new ConfigManager("Armor Display");
public static Property<Boolean> enabled = config.property(
"Enabled",
new Property<>(false));
private static ModDimensions dimensions = new ModDimensions(
config,
0,
0,
34,
75);
public static Property<Integer> fgColor = config.property(
"Foreground color",
new Property<>(SaturnClientConfig.WHITE, Property.PropertyType.HEX));
private boolean renderItem(DrawContext context, ItemStack item, int y) {
if (item.isEmpty()) {
return false;
}
context.drawItem(item, 0, y);
if (item.getMaxDamage() > 0) {
MatrixStack matrices = context.getMatrices();
matrices.push();
matrices.translate(17, y + 5, 0);
matrices.scale(0.8f, 0.8f, 0f);
context.drawText(
SaturnClientConfig.textRenderer,
"" + (item.getMaxDamage() - item.getDamage()),
0,
0,
fgColor.value,
false);
matrices.pop();
}
return true;
}
@Override
public void render(DrawContext context) {
PlayerEntity player = MinecraftClient.getInstance().player;
ItemStack[] items = {
player.getEquippedStack(EquipmentSlot.MAINHAND),
player.getEquippedStack(EquipmentSlot.FEET),
player.getEquippedStack(EquipmentSlot.LEGS),
player.getEquippedStack(EquipmentSlot.CHEST),
player.getEquippedStack(EquipmentSlot.HEAD),
};
int y = 60;
for (ItemStack item : items) {
if (renderItem(context, item, y)) {
y -= 15;
}
}
}
@Override
public void renderDummy(DrawContext context) {
ItemStack[] items = {
new ItemStack(Items.DIAMOND_SWORD),
new ItemStack(Items.DIAMOND_BOOTS),
new ItemStack(Items.DIAMOND_LEGGINGS),
new ItemStack(Items.DIAMOND_CHESTPLATE),
new ItemStack(Items.DIAMOND_HELMET),
};
int y = 60;
for (ItemStack item : items) {
if (renderItem(context, item, y)) {
y -= 15;
}
}
}
public String getName() {
return "Armor display";
}
@Override
public Identifier getIconTexture() {
return Textures.getModIcon("armor");
}
public ModDimensions getDimensions() {
return dimensions;
}
public boolean isEnabled() {
return enabled.value;
}
public void setEnabled(boolean e) {
enabled.value = e;
}
@Override
public ConfigManager getConfig() {
return config;
}
}
@@ -1,92 +0,0 @@
package org.saturnclient.saturnmods.mods;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.HudMod;
import org.saturnclient.saturnmods.ModDimensions;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.Textures;
public class Coordinates implements SaturnMod, HudMod {
private static ConfigManager config = new ConfigManager("Coordinates");
public static Property<Boolean> enabled = config.property(
"Enabled",
new Property<>(false));
private static ModDimensions dimensions = new ModDimensions(config);
public static Property<Integer> fgColor = config.property(
"Foreground color",
new Property<>(SaturnClientConfig.WHITE, Property.PropertyType.HEX));
public Coordinates() {
// Ensure fgColor has a value
if (fgColor.value == null) {
fgColor.value = SaturnClientConfig.WHITE;
}
}
public void renderDummy(DrawContext context) {
int playerX = 124;
int playerY = 69;
int playerZ = 83;
context.drawText(
SaturnClientConfig.textRenderer,
playerX + " " + playerY + " " + playerZ,
0,
0,
fgColor.value,
false);
dimensions.width = SaturnClientConfig.textRenderer.getWidth(
playerX + " " + playerY + " " + playerZ);
dimensions.height = SaturnClientConfig.textRenderer.fontHeight;
}
public void render(DrawContext context) {
PlayerEntity player = MinecraftClient.getInstance().player;
int playerX = (int) player.getX();
int playerY = (int) player.getY();
int playerZ = (int) player.getZ();
context.drawText(
SaturnClientConfig.textRenderer,
playerX + " " + playerY + " " + playerZ,
0,
0,
fgColor.value,
false);
}
public String getName() {
return "Coords";
}
@Override
public Identifier getIconTexture() {
return Textures.getModIcon("coords");
}
public ModDimensions getDimensions() {
return dimensions;
}
public boolean isEnabled() {
return enabled.value;
}
public void setEnabled(boolean e) {
enabled.value = e;
}
@Override
public ConfigManager getConfig() {
return config;
}
}
@@ -1,44 +0,0 @@
package org.saturnclient.saturnmods.mods;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.Textures;
public class Crosshair implements SaturnMod {
public static ConfigManager config = new ConfigManager("Crosshair");
public static Property<Boolean> enabled = config.property(
"Enabled",
new Property<>(false));
public static Property<Boolean> range_indicator = config.property(
"Hit range indicator",
new Property<>(false));
@Override
public boolean isEnabled() {
return enabled.value;
}
@Override
public void setEnabled(boolean e) {
enabled.value = e;
}
@Override
public String getName() {
return "Crosshair";
}
@Override
public Identifier getIconTexture() {
return Textures.getModIcon("crosshair");
}
@Override
public ConfigManager getConfig() {
return config;
}
}
@@ -1,88 +0,0 @@
package org.saturnclient.saturnmods.mods;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.HudMod;
import org.saturnclient.saturnmods.ModDimensions;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.Textures;
public class FpsDisplay implements SaturnMod, HudMod {
public static ConfigManager config = new ConfigManager("Fps Display");
public static Property<Boolean> enabled = config.property(
"Enabled",
new Property<>(false));
public static ModDimensions dimensions = new ModDimensions(
config,
0,
0,
40,
8);
public static Property<Integer> fgColor = config.property(
"Foreground color",
new Property<>(SaturnClientConfig.WHITE, Property.PropertyType.HEX));
@Override
public ModDimensions getDimensions() {
return dimensions;
}
@Override
public void renderDummy(DrawContext context) {
int fps = 128;
context.drawText(
SaturnClientConfig.textRenderer,
String.valueOf(fps) + " FPS",
0,
0,
fgColor.value,
false);
}
@Override
public void render(DrawContext context) {
int fps = MinecraftClient.getInstance().getCurrentFps();
context.drawText(
SaturnClientConfig.textRenderer,
String.valueOf(fps) + " FPS",
0,
0,
fgColor.value,
false);
}
@Override
public boolean isEnabled() {
return enabled.value;
}
@Override
public void setEnabled(boolean e) {
enabled.value = e;
}
@Override
public String getName() {
return "Fps Display";
}
@Override
public Identifier getIconTexture() {
return Textures.getModIcon("fps");
}
@Override
public ConfigManager getConfig() {
return config;
}
}
@@ -1,46 +0,0 @@
package org.saturnclient.saturnmods.mods;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.Textures;
import net.minecraft.client.option.Perspective;
import net.minecraft.util.Identifier;
public class FreeLook implements SaturnMod {
public static boolean isFreeLooking = false;
public static Perspective lastPerspective = null;
private static ConfigManager config = new ConfigManager("Free Look");
public static Property<Boolean> enabled = config.property(
"Enabled",
new Property<>(false));
public static Property<Boolean> toggle = config.property(
"Toggle Free Look",
new Property<>(false));
public boolean isEnabled() {
return enabled.value;
}
public void setEnabled(boolean e) {
enabled.value = e;
}
@Override
public ConfigManager getConfig() {
return config;
}
@Override
public Identifier getIconTexture() {
return Textures.getModIcon("freelook");
}
@Override
public String getName() {
return "Free Look";
}
}
@@ -1,55 +0,0 @@
package org.saturnclient.saturnmods.mods;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.Textures;
public class Particles implements SaturnMod {
public static ConfigManager config = new ConfigManager("Particles");
public static Property<Boolean> enabled = config.property(
"Enabled",
new Property<>(false));
public static ConfigManager totem = new ConfigManager(config, "Totem particles");
public static Property<Boolean> totem_enabled = totem.property(
"Change totem color",
new Property<>(false));
public static Property<Integer> totem_1 = totem.property(
"Totem particle color 1",
new Property<>(SaturnClientConfig.color.value, Property.PropertyType.HEX));
public static Property<Integer> totem_2 = totem.property(
"Totem particle color 2",
new Property<>(SaturnClientConfig.color.value, Property.PropertyType.HEX));
@Override
public boolean isEnabled() {
return enabled.value;
}
@Override
public void setEnabled(boolean e) {
enabled.value = e;
}
@Override
public String getName() {
return "Particles";
}
@Override
public Identifier getIconTexture() {
return Textures.getModIcon("particles");
}
@Override
public ConfigManager getConfig() {
return config;
}
}
@@ -1,6 +1,6 @@
package org.saturnclient.ui.components; package org.saturnclient.ui.components;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -16,7 +16,7 @@ public class SaturnFloat extends SaturnWidget {
String text = ""; String text = "";
public Property<Float> prop; public Property<Float> prop;
public int cursorPosition = 0; public int cursorPosition = 0;
private TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; private TextRenderer textRenderer = SaturnClient.client.textRenderer;
public SaturnFloat(Property<Float> prop, int x, int y, int width) { public SaturnFloat(Property<Float> prop, int x, int y, int width) {
this.x = x; this.x = x;
@@ -1,6 +1,6 @@
package org.saturnclient.ui.components; package org.saturnclient.ui.components;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -16,7 +16,7 @@ public class SaturnHex extends SaturnWidget {
private String text = "#"; // Always starts with '#' private String text = "#"; // Always starts with '#'
public Property<Integer> prop; public Property<Integer> prop;
public int cursorPosition = 1; // After '#' public int cursorPosition = 1; // After '#'
private final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; private final TextRenderer textRenderer = SaturnClient.client.textRenderer;
public SaturnHex(Property<Integer> prop, int x, int y, int width) { public SaturnHex(Property<Integer> prop, int x, int y, int width) {
this.x = x; this.x = x;
@@ -1,9 +1,8 @@
package org.saturnclient.ui.components; package org.saturnclient.ui.components;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.config.ConfigManager; import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property; import org.saturnclient.saturnclient.config.Property;
@@ -16,7 +15,6 @@ public class SaturnInteger extends SaturnWidget {
String text = ""; String text = "";
public Property<Integer> prop; public Property<Integer> prop;
public int cursorPosition = 0; public int cursorPosition = 0;
private TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
public SaturnInteger(Property<Integer> prop, int x, int y, int width) { public SaturnInteger(Property<Integer> prop, int x, int y, int width) {
this.x = x; this.x = x;
@@ -24,7 +22,7 @@ public class SaturnInteger extends SaturnWidget {
this.width = width; this.width = width;
this.prop = prop; this.prop = prop;
this.text = String.valueOf(prop.value); this.text = String.valueOf(prop.value);
this.height = textRenderer.fontHeight + 4; this.height = SaturnClient.client.textRenderer.fontHeight + 4;
this.scale = 0.8f; this.scale = 0.8f;
} }
@@ -37,7 +35,7 @@ public class SaturnInteger extends SaturnWidget {
int textWidth = 0; int textWidth = 0;
for (int i = 0; i < visibleText.length(); i++) { for (int i = 0; i < visibleText.length(); i++) {
textWidth = textRenderer.getWidth(visibleText.substring(0, i + 1)); textWidth = SaturnClient.client.textRenderer.getWidth(visibleText.substring(0, i + 1));
if (textWidth > mouseX) { if (textWidth > mouseX) {
break; break;
@@ -119,7 +117,7 @@ public class SaturnInteger extends SaturnWidget {
int textColor = focused ? 0xFFFFFF : 0xAAAAAA; int textColor = focused ? 0xFFFFFF : 0xAAAAAA;
context.drawText( context.drawText(
textRenderer, SaturnClient.client.textRenderer,
SaturnUi.text(visibleText), SaturnUi.text(visibleText),
2, 2,
2, 2,
@@ -128,14 +126,14 @@ public class SaturnInteger extends SaturnWidget {
if (focused) { if (focused) {
int cursorX = 2 + int cursorX = 2 +
textRenderer.getWidth( SaturnClient.client.textRenderer.getWidth(
SaturnUi.text( SaturnUi.text(
visibleText.substring(0, cursorPosition - scrollOffset))); visibleText.substring(0, cursorPosition - scrollOffset)));
context.fill( context.fill(
cursorX, cursorX,
2, 2,
cursorX + 1, cursorX + 1,
textRenderer.fontHeight + 4, SaturnClient.client.textRenderer.fontHeight + 4,
0xFFFFFFFF); 0xFFFFFFFF);
} }
} }
@@ -155,7 +153,7 @@ public class SaturnInteger extends SaturnWidget {
int maxWidth = width - 4; // Available width for text int maxWidth = width - 4; // Available width for text
while (offset < cursorPosition) { // Ensure cursor remains visible while (offset < cursorPosition) { // Ensure cursor remains visible
String visibleText = text.substring(offset, cursorPosition); String visibleText = text.substring(offset, cursorPosition);
if (textRenderer.getWidth(SaturnUi.text(visibleText)) > maxWidth) { if (SaturnClient.client.textRenderer.getWidth(SaturnUi.text(visibleText)) > maxWidth) {
offset++; offset++;
} else { } else {
break; break;
@@ -169,7 +167,7 @@ public class SaturnInteger extends SaturnWidget {
// Ensure text does not overflow past the available width // Ensure text does not overflow past the available width
for (int i = 1; i <= visibleText.length(); i++) { for (int i = 1; i <= visibleText.length(); i++) {
if (textRenderer.getWidth( if (SaturnClient.client.textRenderer.getWidth(
SaturnUi.text(visibleText.substring(0, i))) > width - 4) { SaturnUi.text(visibleText.substring(0, i))) > width - 4) {
return visibleText.substring(0, i - 1); // Trim overflow return visibleText.substring(0, i - 1); // Trim overflow
} }
@@ -1,19 +1,20 @@
package org.saturnclient.ui.components; package org.saturnclient.ui.components;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import org.saturnclient.modules.Module;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.menus.ConfigEditor; import org.saturnclient.saturnclient.menus.ConfigEditor;
import org.saturnclient.saturnmods.SaturnMod;
import org.saturnclient.ui.SaturnUi; import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.SaturnWidget; import org.saturnclient.ui.SaturnWidget;
import org.saturnclient.ui.Textures; import org.saturnclient.ui.Textures;
public class SaturnModComp extends SaturnWidget { public class SaturnModComp extends SaturnWidget {
SaturnMod mod; Module mod;
public SaturnModComp(SaturnMod mod) { public SaturnModComp(Module mod) {
this.mod = mod; this.mod = mod;
} }
@@ -63,10 +64,10 @@ public class SaturnModComp extends SaturnWidget {
color); color);
context.drawText( context.drawText(
SaturnClientConfig.textRenderer, SaturnClient.client.textRenderer,
SaturnUi.text(mod.getName()), SaturnUi.text(mod.getName()),
20, 20,
(21 - SaturnClientConfig.textRenderer.fontHeight) / 2, (21 - SaturnClient.client.textRenderer.fontHeight) / 2,
color, color,
false); false);
@@ -85,7 +86,7 @@ public class SaturnModComp extends SaturnWidget {
@Override @Override
public void click(int mouseX, int mouseY) { public void click(int mouseX, int mouseY) {
if (settingsHovering(mouseX, mouseY)) { if (settingsHovering(mouseX, mouseY)) {
MinecraftClient.getInstance() SaturnClient.client
.setScreen(new ConfigEditor(mod.getConfig())); .setScreen(new ConfigEditor(mod.getConfig()));
} else { } else {
mod.setEnabled(!mod.isEnabled()); mod.setEnabled(!mod.isEnabled());
@@ -1,6 +1,6 @@
package org.saturnclient.ui.components; package org.saturnclient.ui.components;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -14,7 +14,7 @@ public class SaturnString extends SaturnWidget {
public Property<String> prop; public Property<String> prop;
public int cursorPosition = 0; public int cursorPosition = 0;
private TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; private TextRenderer textRenderer = SaturnClient.client.textRenderer;
public SaturnString(Property<String> prop, int x, int y, int width) { public SaturnString(Property<String> prop, int x, int y, int width) {
this.x = x; this.x = x;
@@ -4,7 +4,7 @@ import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.saturnclient.ui.SaturnWidget; import org.saturnclient.ui.SaturnWidget;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.DiffuseLighting; import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderDispatcher;
@@ -56,7 +56,7 @@ public class SkinPreview extends SaturnWidget {
context.getMatrices().multiply(quaternionf); context.getMatrices().multiply(quaternionf);
context.draw(); context.draw();
DiffuseLighting.method_34742(); DiffuseLighting.method_34742();
EntityRenderDispatcher entityRenderDispatcher = MinecraftClient.getInstance().getEntityRenderDispatcher(); EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
entityRenderDispatcher.setRenderShadows(false); entityRenderDispatcher.setRenderShadows(false);
context.draw((vertexConsumers) -> { context.draw((vertexConsumers) -> {
@@ -71,7 +71,7 @@ public class SkinPreview extends SaturnWidget {
@Override @Override
public void render(DrawContext context, boolean hovering, int mouseX, int mouseY) { public void render(DrawContext context, boolean hovering, int mouseX, int mouseY) {
LivingEntity entity = MinecraftClient.getInstance().player; LivingEntity entity = SaturnClient.client.player;
if (entity != null) { if (entity != null) {
drawEntity(context, 0, 0, 75, 78, 30, 0.0625F, mouseX, mouseY, entity, -30.0f, true); drawEntity(context, 0, 0, 75, 78, 30, 0.0625F, mouseX, mouseY, entity, -30.0f, true);
} }
@@ -2,7 +2,7 @@ package org.saturnclient.ui.widgets;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import java.util.function.Consumer; import java.util.function.Consumer;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@@ -10,6 +10,8 @@ import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.ui.SaturnUi; import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.SaturnWidget; import org.saturnclient.ui.SaturnWidget;
import org.saturnclient.ui.Textures; import org.saturnclient.ui.Textures;
import net.minecraft.client.MinecraftClient;
public class SaturnButton extends SaturnWidget { public class SaturnButton extends SaturnWidget {
@@ -37,7 +39,7 @@ public class SaturnButton extends SaturnWidget {
boolean hovering, boolean hovering,
int mouseX, int mouseX,
int mouseY) { int mouseY) {
MinecraftClient minecraftClient = MinecraftClient.getInstance(); MinecraftClient minecraftClient = SaturnClient.client;
if (background) { if (background) {
RenderSystem.setShaderTexture(0, Textures.BUTTON); RenderSystem.setShaderTexture(0, Textures.BUTTON);
@@ -1,7 +1,7 @@
package org.saturnclient.ui.widgets; package org.saturnclient.ui.widgets;
import org.saturnclient.ui.SaturnWidget; import org.saturnclient.ui.SaturnWidget;
import net.minecraft.client.MinecraftClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@@ -14,7 +14,7 @@ import org.saturnclient.ui.Textures;
public class SaturnInputBox extends SaturnWidget { public class SaturnInputBox extends SaturnWidget {
private TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; private TextRenderer textRenderer = SaturnClient.client.textRenderer;
private int tick = 0; private int tick = 0;
private boolean cursorVisible = true; private boolean cursorVisible = true;
@@ -1,6 +1,8 @@
package org.saturnclient.ui.widgets; package org.saturnclient.ui.widgets;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.ui.SaturnUi; import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.SaturnWidget; import org.saturnclient.ui.SaturnWidget;
@@ -11,8 +13,8 @@ public class SaturnText extends SaturnWidget {
public SaturnText(String text) { public SaturnText(String text) {
this.text = text; this.text = text;
this.width = SaturnClientConfig.textRenderer.getWidth(SaturnUi.text(text)); this.width = SaturnClient.client.textRenderer.getWidth(SaturnUi.text(text));
this.height = SaturnClientConfig.textRenderer.fontHeight; this.height = SaturnClient.client.textRenderer.fontHeight;
} }
public SaturnText(String text, int color) { public SaturnText(String text, int color) {
@@ -26,7 +28,7 @@ public class SaturnText extends SaturnWidget {
int mouseX, int mouseX,
int mouseY) { int mouseY) {
context.drawText( context.drawText(
SaturnClientConfig.textRenderer, SaturnClient.client.textRenderer,
SaturnUi.text(text), SaturnUi.text(text),
0, 0,
0, 0,
@@ -0,0 +1,73 @@
package org.saturnclient.ui2;
import java.util.function.Function;
import org.saturnclient.ui2.anim.Animation;
import org.saturnclient.ui2.anim.Curve;
public class Element {
public int x;
public int y;
public int width;
public int height;
public float opacity = 1.0f;
public boolean focused;
public Animation animation;
public float scale = 1.0f;
public Function<Double, Double> curve = Curve::easeInOutCubic;
public void render(RenderScope renderScope, RenderContext ctx) {
}
public void click(int mouseX, int mouseY) {
}
public final Element dimensions(int width, int height) {
this.width = width;
this.height = height;
return this;
}
public final Element position(int x, int y) {
this.x = x;
this.y = y;
return this;
}
public final Element centerHorizontal(int w, int h, int offsetX, int offsetY) {
this.x = (w - (int) (width * scale)) / 2 + offsetX;
this.y = offsetY;
return this;
}
public final Element center(int w, int h) {
this.centerOffset(w, h, 0, 0);
return this;
}
public final Element centerOffset(int w, int h, int offsetX, int offsetY) {
this.x = (w - (int) (width * scale)) / 2 + offsetX;
this.y = (h - (int) (height * scale)) / 2 + offsetY;
return this;
}
public final Element animation(Animation animation) {
this.animation = animation;
return this;
}
public final Element animation(Animation animation, Function<Double, Double> curve) {
this.animation = animation;
this.curve = curve;
return this;
}
public Element scale(float scale) {
this.scale = scale;
return this;
}
}
@@ -0,0 +1,22 @@
package org.saturnclient.ui2;
public class RenderContext {
public int mouseX, mouseY;
public int elementX, elementY;
public int elementWidth, elementHeight;
public float elementScale;
public RenderContext(int mouseX, int mouseY, Element e) {
this.mouseX = mouseX;
this.mouseY = mouseY;
this.elementX = e.x;
this.elementY = e.y;
this.elementWidth = e.width;
this.elementHeight = e.height;
this.elementScale = e.scale;
}
public boolean isHovering() {
return Utils.isHovering(mouseX - elementX, mouseY - elementY, elementWidth, elementHeight, elementScale);
}
}
@@ -0,0 +1,195 @@
package org.saturnclient.ui2;
import java.util.function.Function;
import org.joml.Matrix4f;
import org.saturnclient.ui2.resources.Fonts;
import com.mojang.blaze3d.systems.RenderSystem;
import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.font.TextRenderer.TextLayerType;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.RotationAxis;
public class RenderScope {
public MatrixStack matrices;
public VertexConsumerProvider.Immediate vertexConsumers;
private Function<Identifier, RenderLayer> renderLayers;
private int opacity = 255 << 24;
public RenderScope(MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers) {
this.matrices = matrices;
this.vertexConsumers = vertexConsumers;
}
public void setOpacity(float alpha) {
this.opacity = (int) (alpha * 255) << 24;
}
public int getColor(int color) {
int originalAlpha = (color >>> 24) & 0xFF;
int newAlpha = (opacity >>> 24) & 0xFF;
int mixedAlpha = (originalAlpha * newAlpha) / 255;
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
}
public void setRenderLayer(Function<Identifier, RenderLayer> renderLayers) {
this.renderLayers = renderLayers;
}
public void drawRect(int x, int y, int width, int height, int color) {
color = getColor(color);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
int i;
if (x1 < x2) {
i = x1;
x1 = x2;
x2 = i;
}
if (y1 < y2) {
i = y1;
y1 = y2;
y2 = i;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderLayer.getGui());
vertexConsumer.vertex(matrix4f, (float) x1, (float) y1, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x1, (float) y2, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y2, 0).color(color);
vertexConsumer.vertex(matrix4f, (float) x2, (float) y1, 0).color(color);
}
public void drawText(String text, int x, int y, boolean bold, int color) {
color = getColor(color);
Identifier font = bold ? Fonts.PANTON_BOLD : Fonts.PANTON;
matrices.push();
matrices.translate(x, y, 0);
matrices.scale(2.0f, 2.0f, 1.0f);
TextRenderer textRenderer = SaturnClient.client.textRenderer;
textRenderer.draw(Fonts.setFont(text, font), 0, 0, color, false, this.matrices.peek().getPositionMatrix(),
this.vertexConsumers, TextLayerType.NORMAL, 0, 15728880);
matrices.pop();
}
public void drawRoundedCorner(int width, int height, int radius, int color) {
int w = width * 20;
int h = height * 20;
for (int y = 0; y < h; y++) {
int startX = 0;
if (y < radius) {
double dy = radius - y - 0.5;
double dx = Math.sqrt(Math.max(0, radius * radius - dy * dy));
startX = radius - (int) dx;
}
this.drawRect(startX, y, w - startX, 1, color);
}
}
private void drawRoundedSide(int cornerWidth, int cornerHeight, int radius, int color) {
// Top
this.matrices.push();
this.matrices.scale(0.05f, 0.05f, 1.0f);
this.drawRoundedCorner(cornerWidth, cornerHeight, radius * 10, color);
this.matrices.pop();
// Bottom
this.matrices.push();
this.matrices.translate(cornerWidth, cornerHeight * 2, 0);
this.matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(90));
this.matrices.translate(0, -cornerWidth, 0);
this.matrices.scale(0.05f, 0.05f, 1.0f);
this.drawRoundedCorner(cornerHeight, cornerWidth, radius * 10, color);
this.matrices.pop();
}
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color) {
radius = Math.min(radius, Math.min(width, height));
int cornerWidth = width / 2;
int cornerHeight = height / 2;
this.matrices.push();
this.matrices.translate(x, y, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.translate(cornerWidth * 2, cornerHeight * 2, 0);
this.matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(180));
this.matrices.translate(0, 0, 0);
this.drawRoundedSide(cornerWidth, cornerHeight, radius, color);
this.matrices.pop();
}
public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getScaledWidth();
}
public int getScaledWindowHeight() {
return SaturnClient.client.getWindow().getScaledHeight();
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int color) {
this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height) {
this.drawTexture(sprite, x, y, u, v, width, height, width, height, width, height);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWith, int regionHeight, int textureWidth, int textureHeight) {
this.drawTexture(sprite, x, y, u, v, width, height, regionWith, regionHeight, textureWidth, textureHeight, -1);
}
public void drawTexture(Identifier sprite, int x, int y, float u, float v, int width, int height, int regionWidth, int regionHeight, int textureWidth, int textureHeight, int color) {
this.drawTexturedQuad(sprite, x, x + width, y, y + height, (u + 0.0F) / (float)textureWidth, (u + (float)regionWidth) / (float)textureWidth, (v + 0.0F) / (float)textureHeight, (v + (float)regionHeight) / (float)textureHeight, color);
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1, float v2, int color) {
x1 *= 4;
x2 *= 4;
y1 *= 4;
y2 *= 4;
color = getColor(color);
matrices.push();
matrices.scale(0.25f, 0.25f, 1.0f);
RenderSystem.setShaderTexture(0, sprite);
RenderLayer renderLayer = (RenderLayer)renderLayers.apply(sprite);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix();
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(renderLayer);
vertexConsumer.vertex(matrix4f, (float)x1, (float)y1, 0.0F).texture(u1, v1).color(color);
vertexConsumer.vertex(matrix4f, (float)x1, (float)y2, 0.0F).texture(u1, v2).color(color);
vertexConsumer.vertex(matrix4f, (float)x2, (float)y2, 0.0F).texture(u2, v2).color(color);
vertexConsumer.vertex(matrix4f, (float)x2, (float)y1, 0.0F).texture(u2, v1).color(color);
matrices.pop();
}
}
@@ -0,0 +1,128 @@
package org.saturnclient.ui2;
import java.util.ArrayList;
import java.util.List;
import org.saturnclient.saturnclient.config.ThemeManager;
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
import org.saturnclient.ui2.anim.Animation;
import net.minecraft.client.gl.PostEffectProcessor;
import net.minecraft.client.gui.CubeMapRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.RotatingCubeMapRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.render.DefaultFramebufferSet;
import net.minecraft.client.util.Pool;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public abstract class SaturnScreen extends Screen {
private final Pool pool = new Pool(3);
protected List<Element> elements = new ArrayList<>();
public int blurDuration = 700;
public float blurProgress = 0.0f;
public int backgroundBlur = 10;
protected static final CubeMapRenderer PANORAMA_RENDERER = new CubeMapRenderer(
Identifier.of("saturnclient", "textures/gui/title/background/panorama"));
public static final RotatingCubeMapRenderer ROTATING_PANORAMA_RENDERER;
static {
ROTATING_PANORAMA_RENDERER = new RotatingCubeMapRenderer(PANORAMA_RENDERER);
}
public SaturnScreen(String title) {
super(Text.literal(title));
}
public void draw(Element element) {
synchronized (elements) {
elements.add(element);
}
if (element.animation != null) {
element.animation.init(element);
Animation.execute((Float progress) -> {
element.animation.tick(progress, element);
}, element.animation.duration);
}
}
@Override
protected void init() {
width *= 2;
height *= 2;
ui(); // abstraction to render the saturn ui and also render extra stuff here
ThemeManager.load();
Animation.execute((Float progress) -> {
blurProgress = progress;
}, blurDuration);
}
public abstract void ui();
@SuppressWarnings("deprecation")
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
mouseX *= 2;
mouseY *= 2;
if (client.world == null && client.getCurrentServerEntry() == null) {
ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, 1.0F, delta);
}
PostEffectProcessor postEffectProcessor = this.client.getShaderLoader().loadPostEffect(
Identifier.ofVanilla("blur"),
DefaultFramebufferSet.MAIN_ONLY);
if (postEffectProcessor != null) {
postEffectProcessor.setUniforms("Radius", backgroundBlur * blurProgress);
postEffectProcessor.render(this.client.getFramebuffer(), this.pool);
}
// We are using a Abstracted RenderScope because older minecraft versions don't
// use DrawContext
RenderScope renderScope = new RenderScope(context.getMatrices(),
((DrawContextAccessor) context).getVertexConsumers());
renderScope.matrices.push();
renderScope.matrices.scale(0.5f, 0.5f, 0.5f);
for (Element element : elements) {
renderScope.matrices.push();
renderScope.setOpacity(element.opacity);
renderScope.matrices.translate(element.x, element.y, 0);
renderScope.matrices.scale(element.scale, element.scale, 1.0f);
element.render(renderScope, new RenderContext(mouseX, mouseY, element));
renderScope.matrices.pop();
renderScope.setRenderLayer(null);
}
renderScope.matrices.pop();
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouseX *= 2;
mouseY *= 2;
if (button == 0) {
for (Element element : new ArrayList<>(elements)) {
element.focused = false;
int adjustedMouseX = (int) mouseX - element.x;
int adjustedMouseY = (int) mouseY - element.y;
if (Utils.isHovering(adjustedMouseX, adjustedMouseY, element.width, element.height, element.scale)) {
element.focused = true;
element.click(adjustedMouseX, adjustedMouseY);
}
}
}
return false;
}
}
@@ -0,0 +1,10 @@
package org.saturnclient.ui2;
public class Utils {
public static boolean isHovering(int mouseX, int mouseY, int elementWidth, int elementHeight, float elementScale) {
return mouseX >= 0 &&
mouseX <= (elementWidth * elementScale) &&
mouseY >= 0 &&
mouseY <= (elementHeight * elementScale);
}
}
@@ -0,0 +1,53 @@
package org.saturnclient.ui2.anim;
import java.util.function.Consumer;
import java.util.function.Function;
import org.saturnclient.ui2.Element;
public abstract class Animation {
public int duration;
Animation(int duration) {
this.duration = duration;
}
public abstract void tick(float progress, Element element);
public abstract void init(Element element);
public static void execute(Consumer<Float> tick, int duration) {
new Thread(() -> {
long startTime = System.currentTimeMillis();
Function<Double, Double> curveFunction = Curve::easeInOutCubic;
float progress = 0.0f;
double incremental = (1000 - duration) / 10000.0;
System.out.println("Starting animation...");
for (int i = 0; i <= 100; i++) {
float newProgress = (float) (double) curveFunction.apply(i / 100.0);
while (Math.abs(newProgress - progress) > 1e-6) {
if (progress < newProgress) {
progress += incremental;
if (progress > newProgress) progress = newProgress;
} else {
progress -= incremental;
if (progress < newProgress) progress = newProgress;
}
tick.accept(newProgress);
try {
Thread.sleep(duration / 100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("Animation complete. " + (System.currentTimeMillis() - startTime) + "MS");
}).start();
}
}
@@ -0,0 +1,26 @@
package org.saturnclient.ui2.anim;
public class Curve {
public static double easeOutCubic(double x) {
return 1 - Math.pow(1 - x, 3);
}
public static double easeInOutCubic(double x) {
return (x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2);
}
public static double easeInOutCubicReverse(double x) {
return -(x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2);
}
public static double easeInOutBack(double x) {
double c1 = 1.70158;
double c2 = c1 * 1.525;
if (x < 0.5) {
return (Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2;
} else {
return (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (2 * x - 2) + c2) + 2) / 2;
}
}
}
@@ -0,0 +1,22 @@
package org.saturnclient.ui2.anim;
import org.saturnclient.ui2.Element;
public class Fade extends Animation {
float targetOpacity;
public Fade(int duration) {
super(duration);
}
@Override
public void tick(float progress, Element element) {
element.opacity = targetOpacity * progress;
}
@Override
public void init(Element element) {
targetOpacity = element.opacity;
element.opacity = 0;
}
}
@@ -0,0 +1,38 @@
package org.saturnclient.ui2.anim;
import org.saturnclient.ui2.Element;
public class SlideY extends Animation {
int offset = 20;
int maxOffset = 20;
int elementY;
public SlideY(int duration) {
super(duration);
}
public SlideY(int duration, int offset) {
super(duration);
this.offset = offset;
this.maxOffset = offset;
}
public SlideY(int duration, int offset, int maxOffset) {
super(duration);
this.offset = offset;
this.maxOffset = offset;
}
@Override
public void tick(float progress, Element element) {
element.y = elementY + (int) (offset * progress);
}
@Override
public void init(Element element) {
element.y -= offset;
elementY = element.y;
}
}
@@ -0,0 +1,52 @@
package org.saturnclient.ui2.elements;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnclient.config.ThemeManager;
import org.saturnclient.ui2.Element;
import org.saturnclient.ui2.RenderContext;
import org.saturnclient.ui2.RenderScope;
import org.saturnclient.ui2.resources.Fonts;
import net.minecraft.util.Identifier;
public class Button extends Element {
private static ThemeManager theme = new ThemeManager("Button", "hovering");
private static Property<Integer> bgColor = theme.property("bg-color", new Property<Integer>(0xFF000000));
private static Property<Integer> fgColor = theme.property("fg-color", new Property<Integer>(0xFFFFFFFF));
private static Property<Integer> cornerRadius = theme.property("corner-radius", new Property<Integer>(10));
private static Property<Boolean> bold = theme.property("fg-bold", new Property<Boolean>(false));
static {
theme.propertyStateDefault("hovering", "fg-color", 0xFFFF0000);
}
private String text;
private Identifier font;
private Runnable onClick;
public Button(String text, Runnable onClick) {
this.text = text;
this.font = Fonts.getFont(bold.value);
this.onClick = onClick;
this.dimensions(Fonts.getWidth(text, font) + 50, Fonts.getHeight() + 20);
}
@Override
public void render(RenderScope renderScope, RenderContext ctx) {
if (ctx.isHovering()) {
theme.setState("hovering");
} else {
theme.setState(null);
}
renderScope.drawRoundedRectangle(0, 0, width, height, cornerRadius.value, bgColor.value);
renderScope.drawText(text, (width - Fonts.getWidth(text, font)) / 2, (height - Fonts.getHeight()) / 2, bold.value, fgColor.value);
}
@Override
public void click(int mouseX, int mouseY) {
if (onClick != null) {
onClick.run();
}
}
}
@@ -0,0 +1,42 @@
package org.saturnclient.ui2.elements;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnclient.config.ThemeManager;
import org.saturnclient.ui2.Element;
import org.saturnclient.ui2.RenderContext;
import org.saturnclient.ui2.RenderScope;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier;
public class ClickableTexture extends Element {
private static ThemeManager theme = new ThemeManager("ClickableTexture", "hovering");
private static Property<Integer> fgColor = theme.property("fg-color", new Property<Integer>(0xFFFFFFFF));
Identifier sprite;
private Runnable onClick;
public ClickableTexture(Identifier sprite, Runnable onClick) {
this.sprite = sprite;
this.onClick = onClick;
}
@Override
public void render(RenderScope renderScope, RenderContext ctx) {
if (ctx.isHovering()) {
theme.setState("hovering");
} else {
theme.setState(null);
}
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
renderScope.drawTexture(sprite, 0, 0, 0, 0, width, height, fgColor.value);
}
@Override
public void click(int mouseX, int mouseY) {
if (onClick != null) {
onClick.run();
}
}
}
@@ -0,0 +1,22 @@
package org.saturnclient.ui2.elements;
import org.saturnclient.ui2.Element;
import org.saturnclient.ui2.RenderContext;
import org.saturnclient.ui2.RenderScope;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier;
public class ImageTexture extends Element {
Identifier sprite;
public ImageTexture(Identifier sprite) {
this.sprite = sprite;
}
@Override
public void render(RenderScope renderScope, RenderContext ctx) {
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
renderScope.drawTexture(sprite, 0, 0, 0, 0, width, height);
}
}
@@ -0,0 +1,23 @@
package org.saturnclient.ui2.elements;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnclient.config.ThemeManager;
import org.saturnclient.ui2.Element;
import org.saturnclient.ui2.RenderContext;
import org.saturnclient.ui2.RenderScope;
public class Text extends Element {
private static ThemeManager theme = new ThemeManager("Text");
private static Property<Integer> fgColor = theme.property("fg-color", new Property<Integer>(0xFFFFFFFF));
private String text;
public Text(String text) {
this.text = text;
}
@Override
public void render(RenderScope renderScope, RenderContext ctx) {
renderScope.drawText(this.text, this.x, this.y, false, fgColor.value);
}
}
@@ -0,0 +1,56 @@
package org.saturnclient.ui2.elements;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnclient.config.ThemeManager;
import org.saturnclient.ui2.Element;
import org.saturnclient.ui2.RenderContext;
import org.saturnclient.ui2.RenderScope;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier;
public class TextureButton extends Element {
private static ThemeManager theme = new ThemeManager("TextureButton", "hovering");
private static Property<Integer> bgColor = theme.property("bg-color", new Property<Integer>(0xFF000000));
private static Property<Integer> fgColor = theme.property("fg-color", new Property<Integer>(0xFFFFFFFF));
private static Property<Integer> padding = theme.property("padding", new Property<Integer>(14));
private static Property<Integer> cornerRadius = theme.property("corner-radius", new Property<Integer>(10));
static {
theme.propertyStateDefault("hovering", "fg-color", 0xFFFF0000);
}
Identifier sprite;
private Runnable onClick;
public TextureButton(Identifier sprite, Runnable onClick) {
this.sprite = sprite;
this.onClick = onClick;
}
@Override
public void render(RenderScope renderScope, RenderContext ctx) {
if (ctx.isHovering()) {
theme.setState("hovering");
} else {
theme.setState(null);
}
renderScope.drawRoundedRectangle(0, 0, width, height, cornerRadius.value, bgColor.value);
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
int texWidth = width - padding.value;
int texHeight = height - padding.value;
renderScope.drawTexture(sprite, padding.value / 2, padding.value / 2, 0, 0, texWidth, texHeight, fgColor.value);
}
@Override
public void click(int mouseX, int mouseY) {
if (onClick != null) {
onClick.run();
}
}
}
@@ -0,0 +1,42 @@
package org.saturnclient.ui2.resources;
import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class Fonts {
public static final Identifier PANTON = Identifier.of("saturnclient", "panton");
public static final Identifier PANTON_BOLD = Identifier.of("saturnclient", "panton_bold");
public static Identifier getFont(boolean bold) {
if (bold) {
return PANTON_BOLD;
} else {
return PANTON;
}
}
public static Text setFont(String text, Identifier font) {
return Text.literal(text).setStyle(
Style.EMPTY.withFont(font));
}
// public static int getWidth(String text, Identifier font) {
// return SaturnClient.client.textRenderer.getWidth(Text.literal(text).setStyle(
// Style.EMPTY.withFont(font)));
// }
// public static int getHeight() {
// return SaturnClient.client.textRenderer.fontHeight;
// }
public static int getWidth(String text, Identifier font) {
return SaturnClient.client.textRenderer.getWidth(Text.literal(text).setStyle(
Style.EMPTY.withFont(font))) * 2;
}
public static int getHeight() {
return SaturnClient.client.textRenderer.fontHeight * 2;
}
}
@@ -0,0 +1,7 @@
package org.saturnclient.ui2.resources;
import net.minecraft.util.Identifier;
public class Textures {
public static final Identifier CROSSHAIR_RANGE = Identifier.of("saturnclient", "textures/gui/hud/crosshair_range.png");
}
@@ -0,0 +1,41 @@
package org.saturnclient.ui2.screens;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.menus.CloaksMenu;
import org.saturnclient.saturnclient.menus.HudEditor;
import org.saturnclient.saturnclient.menus.ModMenu;
import org.saturnclient.ui.Textures;
import org.saturnclient.ui2.Element;
import org.saturnclient.ui2.SaturnScreen;
import org.saturnclient.ui2.elements.Button;
import org.saturnclient.ui2.elements.ImageTexture;
import org.saturnclient.ui2.elements.TextureButton;
import org.saturnclient.ui2.anim.Fade;
import org.saturnclient.ui2.anim.SlideY;
public class ShiftMenu extends SaturnScreen {
public ShiftMenu() {
super("Shift Menu");
}
@Override
public void ui() {
draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 16).centerOffset(width, height, 0, -36).animation(new Fade(700)));
draw(new ImageTexture(SaturnClientConfig.getLogo()).dimensions(98, 98).centerOffset(width, height, 0, -80).animation(new SlideY(700, -40)));
Element button = new Button("Settings", () -> {
SaturnClient.client.setScreen(new ModMenu());
}).center(width, height);
draw(button);
draw(new TextureButton(Textures.COSMETICS, () -> {
client.setScreen(new CloaksMenu());
}).dimensions(button.height, button.height).centerOffset(width, height, (button.width / 2) + (button.height / 2) + 4, 0));
draw(new TextureButton(Textures.HUD_ICON, () -> {
client.setScreen(new HudEditor());
}).dimensions(button.height, button.height).centerOffset(width, height, -((button.width / 2) + (button.height / 2) + 4), 0));
}
}
@@ -0,0 +1,63 @@
package org.saturnclient.ui2.screens;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.SaturnClientConfig;
import org.saturnclient.saturnclient.menus.CloaksMenu;
import org.saturnclient.saturnclient.menus.HudEditor;
import org.saturnclient.saturnclient.menus.ModMenu;
import org.saturnclient.ui.Textures;
import org.saturnclient.ui2.SaturnScreen;
import org.saturnclient.ui2.anim.Fade;
import org.saturnclient.ui2.anim.SlideY;
import org.saturnclient.ui2.elements.Button;
import org.saturnclient.ui2.elements.ImageTexture;
import org.saturnclient.ui2.elements.TextureButton;
import org.saturnclient.ui2.resources.Fonts;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.option.OptionsScreen;
import net.minecraft.client.gui.screen.world.SelectWorldScreen;
public class TitleMenu extends SaturnScreen {
public TitleMenu() {
super("Tile Menu");
}
@Override
public void ui() {
backgroundBlur = 0;
draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 16).centerOffset(width, height, 0, -40).animation(new Fade(700)));
draw(new ImageTexture(SaturnClientConfig.getLogo()).dimensions(98, 98).centerOffset(width, height, 0, -82).animation(new SlideY(700, -40)));
draw(new Button("SINGLEPLAYER", () -> {
client.setScreen(new SelectWorldScreen(new TitleMenu()));
}).scale(0.69f).dimensions(420, 52).centerOffset(width, height, 0, 0));
draw(new Button("MULTIPLAYER", () -> {
client.setScreen(new MultiplayerScreen(new TitleMenu()));
}).scale(0.69f).dimensions(420, 52).centerOffset(width, height, 0, 40));
draw(new Button("OPTIONS", () -> {
client.setScreen(new OptionsScreen(new TitleMenu(), SaturnClient.client.options));
}).scale(0.69f).dimensions(206, 52).centerOffset(width, height, -73, 80));
draw(new Button("QUIT", () -> {
client.scheduleStop();
}).scale(0.69f).dimensions(206, 52).centerOffset(width, height, 73, 80));
int s = Fonts.getHeight() + 20;
draw(new TextureButton(Textures.HUD_ICON, () -> {
client.setScreen(new HudEditor());
}).dimensions(s, s).centerHorizontal(width, height, -(s + 2), 8).animation(new SlideY(700, s + 8)));
draw(new TextureButton(Textures.SETTINGS, () -> {
SaturnClient.client.setScreen(new ModMenu());
}).dimensions(s, s).centerHorizontal(width, height, 0, 8).animation(new SlideY(700, s + 8)));
draw(new TextureButton(Textures.CLOAK, () -> {
client.setScreen(new CloaksMenu());
}).dimensions(s, s).centerHorizontal(width, height, s + 2, 8).animation(new SlideY(700, s + 8)));
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 KiB

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 19 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 19 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 16 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 16 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 KiB

After

Width:  |  Height:  |  Size: 21 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 18 MiB

+2 -5
View File
@@ -2,17 +2,14 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "org.saturnclient.saturnclient.mixin", "package": "org.saturnclient.saturnclient.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_21",
"client": [ "client": [
"TabListMixin", "TabListMixin",
"NameTagMixin", "NameTagMixin",
"PlayerEntityRendererMixin", "PlayerEntityRendererMixin",
"WhoAmI", "WhoAmI",
"SaturnReload", "SaturnReload",
"TotemParticleMixin", "DrawContextAccessor"
"Crosshair",
"EntityMixin",
"CameraMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1