Merge pull request #1 from saturnclientmc/working-common-system
Working common system
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
package org.saturnclient.client;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.saturnclient.client.player.SaturnPlayer;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnClientBindings;
|
||||
|
||||
import dev.selimaj.session.Session;
|
||||
|
||||
public class ServiceClient {
|
||||
private static Session session;
|
||||
public static UUID uuid;
|
||||
|
||||
public static final List<String> availableCloaks = new ArrayList<>();
|
||||
public static final List<String> availableHats = new ArrayList<>();
|
||||
|
||||
public static boolean connectTimeout() {
|
||||
try {
|
||||
session = Session.connect("wss://saturn-server.selimaj.dev", 10, TimeUnit.SECONDS);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean authenticate() {
|
||||
SaturnClientBindings.platform().onClientStopping(() -> {
|
||||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Unable to close Saturn session", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
String accessToken = SaturnClientBindings.platform().getAccessToken();
|
||||
uuid = SaturnClientBindings.platform().getUuid();
|
||||
String username = SaturnClientBindings.platform().getUsername();
|
||||
|
||||
if (accessToken == null || uuid == null || username == null) {
|
||||
SaturnClientBindings.platform().logError("No active Minecraft session found");
|
||||
return false;
|
||||
}
|
||||
|
||||
SaturnClientBindings.platform().logInfo("Authenticating with UUID: " + uuid);
|
||||
|
||||
if (!connectTimeout()) {
|
||||
SaturnClientBindings.platform().logError("Unable to authenticate: Session Server Timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
ServiceMethods.Types.Player response = session.request(ServiceMethods.Authenticate, accessToken)
|
||||
.get();
|
||||
|
||||
for (String availableCloak : response.cloaks()) {
|
||||
availableCloaks.add(availableCloak);
|
||||
}
|
||||
|
||||
for (String availableHat : response.hats()) {
|
||||
availableHats.add(availableHat);
|
||||
}
|
||||
|
||||
eventHandlers();
|
||||
|
||||
SaturnPlayer.set(new SaturnPlayer(uuid, username, response.cloak(), response.hat()));
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Authentication failed", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCloak(String itemId) {
|
||||
try {
|
||||
session.request(ServiceMethods.SetCloak, itemId).whenComplete((msg, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
} else {
|
||||
try {
|
||||
session.request(ServiceMethods.SendPlayer,
|
||||
new ServiceMethods.Types.SendPlayerRequest(SaturnPlayer.getExternalUUIDAsString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Failed to set cloak (service): ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setHat(String itemId) {
|
||||
try {
|
||||
session.request(ServiceMethods.SetHat, itemId).whenComplete((msg, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
} else {
|
||||
try {
|
||||
session.request(ServiceMethods.SendPlayer,
|
||||
new ServiceMethods.Types.SendPlayerRequest(SaturnPlayer.getExternalUUIDAsString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Failed to set hat (service): ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void buyCloak(String itemId) {
|
||||
try {
|
||||
session.request(ServiceMethods.BuyCloak, itemId).whenComplete((msg, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
} else {
|
||||
availableCloaks.add(itemId);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Failed to buy cloak (service): ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void buyHat(String itemId) {
|
||||
try {
|
||||
session.request(ServiceMethods.BuyHat, itemId).whenComplete((msg, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
} else {
|
||||
availableHats.add(itemId);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Failed to buy hat (service): ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void emote(String emote) {
|
||||
try {
|
||||
session.request(ServiceMethods.Emote,
|
||||
new ServiceMethods.Types.EmoteRequest(emote, SaturnPlayer.getExternalUUIDAsString()))
|
||||
.whenComplete((msg, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Failed to emote (service): ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void eventHandlers() {
|
||||
session.onNotification(ServiceMethods.EmoteEvent, (data) -> {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
UUID from;
|
||||
try {
|
||||
from = UUID.fromString(data.from());
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.emote() != null && !data.emote().isEmpty()) {
|
||||
SaturnClientBindings.emotes().setEmote(from, data.emote());
|
||||
} else {
|
||||
SaturnClientBindings.emotes().setEmote(from, null);
|
||||
}
|
||||
});
|
||||
|
||||
session.onNotification(ServiceMethods.Player, (player) -> {
|
||||
System.out.println(player);
|
||||
SaturnPlayer.set(player.toSaturnPlayer());
|
||||
});
|
||||
}
|
||||
|
||||
public static void player(UUID uuid, String name) {
|
||||
try {
|
||||
session.request(ServiceMethods.GetPlayer, uuid.toString())
|
||||
.whenComplete((user, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
} else if (user != null) {
|
||||
SaturnPlayer.set(user.toSaturnPlayer(uuid, name));
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
SaturnClientBindings.platform().logError("Failed to get player", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package org.saturnclient.client;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.saturnclient.client.ServiceMethods.Types.SendPlayerRequest;
|
||||
import org.saturnclient.client.player.SaturnPlayer;
|
||||
|
||||
import dev.selimaj.session.types.Method;
|
||||
|
||||
public class ServiceMethods {
|
||||
|
||||
// =========================
|
||||
// Types (Rust structs)
|
||||
// =========================
|
||||
public static class Types {
|
||||
|
||||
public record EmoteRequest(String emote, String[] targets) {
|
||||
}
|
||||
|
||||
public record EmoteEvent(String emote, String from) {
|
||||
}
|
||||
|
||||
public record Player(
|
||||
String cloak,
|
||||
String hat,
|
||||
String[] cloaks,
|
||||
String[] hats) {
|
||||
public SaturnPlayer toSaturnPlayer(UUID uuid, String name) {
|
||||
return new SaturnPlayer(uuid, name, cloak, hat);
|
||||
}
|
||||
}
|
||||
|
||||
public record PlayerStream(Player player, String name, String uuid) {
|
||||
public SaturnPlayer toSaturnPlayer() {
|
||||
return new SaturnPlayer(UUID.fromString(uuid), name, this.player.cloak, this.player.hat);
|
||||
}
|
||||
}
|
||||
|
||||
public record SendPlayerRequest(String[] targets) {
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// AUTH
|
||||
// =========================
|
||||
public static final Method<String, Types.Player, String> Authenticate = new Method<>("auth",
|
||||
String.class,
|
||||
Types.Player.class,
|
||||
String.class);
|
||||
|
||||
// =========================
|
||||
// EQUIP
|
||||
// =========================
|
||||
public static final Method<String, String, String> SetCloak = new Method<>("set_cloak",
|
||||
String.class,
|
||||
String.class,
|
||||
String.class);
|
||||
|
||||
public static final Method<String, String, String> SetHat = new Method<>("set_hat",
|
||||
String.class,
|
||||
String.class,
|
||||
String.class);
|
||||
|
||||
// =========================
|
||||
// BUY
|
||||
// =========================
|
||||
public static final Method<String, String, String> BuyCloak = new Method<>("buy_cloak",
|
||||
String.class,
|
||||
String.class,
|
||||
String.class);
|
||||
|
||||
public static final Method<String, String, String> BuyHat = new Method<>("buy_hat",
|
||||
String.class,
|
||||
String.class,
|
||||
String.class);
|
||||
|
||||
// =========================
|
||||
// EMOTE
|
||||
// =========================
|
||||
public static final Method<Types.EmoteRequest, Void, String> Emote = new Method<>("emote",
|
||||
Types.EmoteRequest.class,
|
||||
Void.class,
|
||||
String.class);
|
||||
|
||||
public static final Method<Types.EmoteEvent, Void, Void> EmoteEvent = new Method<>("emote_event",
|
||||
Types.EmoteEvent.class,
|
||||
Void.class,
|
||||
Void.class);
|
||||
|
||||
// =========================
|
||||
// GET PLAYER
|
||||
// =========================
|
||||
public static final Method<String, Types.Player, String> GetPlayer = new Method<>("get_player",
|
||||
String.class,
|
||||
Types.Player.class,
|
||||
String.class);
|
||||
|
||||
// =========================
|
||||
// PLAYER (Server Notification)
|
||||
// =========================
|
||||
public static final Method<Types.PlayerStream, Void, Void> Player = new Method<>("player",
|
||||
Types.PlayerStream.class,
|
||||
Void.class,
|
||||
Void.class);
|
||||
|
||||
// =========================
|
||||
// SEND PLAYER
|
||||
// =========================
|
||||
public static final Method<SendPlayerRequest, Void, String> SendPlayer = new Method<>("send_player",
|
||||
SendPlayerRequest.class,
|
||||
Void.class,
|
||||
String.class);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.saturnclient.client.player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.saturnclient.config.Config;
|
||||
|
||||
public class Roles {
|
||||
static enum Role {
|
||||
OWNER,
|
||||
ADMIN,
|
||||
PARTNER,
|
||||
CONTRIBUTOR
|
||||
}
|
||||
|
||||
private static final Map<UUID, Role> ROLES = Map.of(
|
||||
UUID.fromString("d362a042-28bd-49e1-a807-ae74dbe8aba9"),
|
||||
Role.OWNER,
|
||||
UUID.fromString("d8dc7023-179b-4460-bcf6-493fbf1289a6"),
|
||||
Role.CONTRIBUTOR);
|
||||
|
||||
/*
|
||||
* 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 int getIconColor(UUID uuid) {
|
||||
Role role = ROLES.get(uuid);
|
||||
|
||||
if (role == null) {
|
||||
return 0xFFFFFF;
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case OWNER:
|
||||
return 0xAA0000;
|
||||
|
||||
case ADMIN:
|
||||
return 0xFF5555;
|
||||
|
||||
case PARTNER:
|
||||
return 0xFFAA00;
|
||||
|
||||
case CONTRIBUTOR:
|
||||
return 0x55FFFF;
|
||||
|
||||
default:
|
||||
return 0xFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSaturnIndicator() {
|
||||
return Config.realisticLogo.value ? "\uE003" : "\uE002";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.saturnclient.client.player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnClientBindings;
|
||||
|
||||
public class SaturnPlayer {
|
||||
private static Map<UUID, SaturnPlayer> PLAYERS = new HashMap<>();
|
||||
private static Map<String, UUID> PLAYER_NAMES = new HashMap<>();
|
||||
|
||||
public String cloak = "";
|
||||
public String hat = "";
|
||||
public final UUID uuid;
|
||||
public final String name;
|
||||
|
||||
public SaturnPlayer(UUID uuid, String name, String cloak, String hat) {
|
||||
this.cloak = cloak;
|
||||
this.hat = hat;
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static SaturnPlayer get() {
|
||||
UUID self = SaturnClientBindings.platform().getUuid();
|
||||
if (self == null) {
|
||||
return null;
|
||||
}
|
||||
return PLAYERS.get(self);
|
||||
}
|
||||
|
||||
public static SaturnPlayer get(UUID uuid) {
|
||||
return PLAYERS.get(uuid);
|
||||
}
|
||||
|
||||
public static SaturnPlayer get(String name) {
|
||||
UUID uuid = PLAYER_NAMES.get(name);
|
||||
if (uuid == null)
|
||||
return null;
|
||||
return PLAYERS.get(uuid);
|
||||
}
|
||||
|
||||
public static void set(SaturnPlayer player) {
|
||||
PLAYER_NAMES.put(player.name, player.uuid);
|
||||
PLAYERS.put(player.uuid, player);
|
||||
}
|
||||
|
||||
public static String[] getExternalUUIDAsString() {
|
||||
UUID self = SaturnClientBindings.platform().getUuid();
|
||||
return PLAYERS.keySet().stream().filter(id -> self == null || !id.equals(self)).map(UUID::toString)
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.saturnclient.common;
|
||||
|
||||
public class Common {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.saturnclient.common.minecraft;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.common.minecraft.render.IWindow;
|
||||
|
||||
public interface IMinecraftClient {
|
||||
|
||||
public File getRunDirectory();
|
||||
|
||||
public InputStream getResource(SaturnIdentifier identifier);
|
||||
|
||||
public IWindow getWindow();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.saturnclient.common.minecraft;
|
||||
|
||||
public class MinecraftBinding {
|
||||
public Object inner;
|
||||
|
||||
public MinecraftBinding(Object binding) {
|
||||
this.inner = binding;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get() {
|
||||
try {
|
||||
return (T) inner;
|
||||
} catch (ClassCastException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.saturnclient.common.minecraft;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.ui.SaturnScreen;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public abstract class MinecraftProvider {
|
||||
public static MinecraftProvider PROVIDER;
|
||||
|
||||
public static enum MinecraftScreen {
|
||||
SelectWorld,
|
||||
Multiplayer,
|
||||
Options
|
||||
}
|
||||
|
||||
public abstract IMinecraftClient getClient();
|
||||
|
||||
public abstract void setScreen(SaturnScreen screen);
|
||||
|
||||
public abstract void setScreen(MinecraftScreen screen);
|
||||
|
||||
public abstract Object createIdentifier(String namespace, String path);
|
||||
|
||||
public abstract boolean isKeyPressed(int key);
|
||||
|
||||
public abstract int getWidth(String text, int font);
|
||||
|
||||
public abstract void registerBufferedImageTexture(SaturnIdentifier i, BufferedImage bi);
|
||||
|
||||
public abstract String getKeyName(int key);
|
||||
|
||||
public abstract void stop();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
public final class SaturnClientBindings {
|
||||
private static SaturnPlatformBindings platform;
|
||||
private static SaturnEmoteBindings emotes;
|
||||
|
||||
private SaturnClientBindings() {
|
||||
}
|
||||
|
||||
public static void setPlatform(SaturnPlatformBindings bindings) {
|
||||
platform = bindings;
|
||||
}
|
||||
|
||||
public static SaturnPlatformBindings platform() {
|
||||
if (platform == null) {
|
||||
throw new IllegalStateException("SaturnPlatformBindings not initialized");
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
public static void setEmotes(SaturnEmoteBindings bindings) {
|
||||
emotes = bindings;
|
||||
}
|
||||
|
||||
public static SaturnEmoteBindings emotes() {
|
||||
if (emotes == null) {
|
||||
throw new IllegalStateException("SaturnEmoteBindings not initialized");
|
||||
}
|
||||
return emotes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface SaturnEmoteBindings {
|
||||
void setEmote(UUID fromPlayerUuid, String emoteIdOrNull);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftBinding;
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
|
||||
public class SaturnIdentifier extends MinecraftBinding {
|
||||
public SaturnIdentifier(String namespace, String path) {
|
||||
super(MinecraftProvider.PROVIDER.createIdentifier(namespace, path));
|
||||
}
|
||||
|
||||
public SaturnIdentifier(Object o) {
|
||||
super(o);
|
||||
}
|
||||
|
||||
public static SaturnIdentifier of(String namespace, String path) {
|
||||
return new SaturnIdentifier(namespace, path);
|
||||
}
|
||||
|
||||
public static SaturnIdentifier of(String fullPath) {
|
||||
String[] p = fullPath.split(":", 2);
|
||||
|
||||
return new SaturnIdentifier(p[0], p[1]);
|
||||
}
|
||||
|
||||
public static SaturnIdentifier ofVanilla(String path) {
|
||||
return new SaturnIdentifier("minecraft", path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.inner.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftBinding;
|
||||
|
||||
public class SaturnItemStack extends MinecraftBinding {
|
||||
public SaturnItemStack(Object binding) {
|
||||
super(binding);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface SaturnPlatformBindings {
|
||||
String getAccessToken();
|
||||
|
||||
UUID getUuid();
|
||||
|
||||
String getUsername();
|
||||
|
||||
void onClientStopping(Runnable handler);
|
||||
|
||||
void logInfo(String message);
|
||||
|
||||
void logError(String message);
|
||||
|
||||
void logError(String message, Throwable throwable);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftBinding;
|
||||
|
||||
public class SaturnQuaternionf extends MinecraftBinding {
|
||||
public SaturnQuaternionf(Object o) {
|
||||
super(o);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.saturnclient.common.minecraft.bindings;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftBinding;
|
||||
|
||||
public class SaturnSprite extends MinecraftBinding {
|
||||
public SaturnSprite(Object binding) {
|
||||
super(binding);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.saturnclient.common.minecraft.render;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnQuaternionf;
|
||||
|
||||
public interface IMatrixStack {
|
||||
public void translate(double x, double y, double z);
|
||||
|
||||
public void translate(float x, float y, float z);
|
||||
|
||||
public void scale(float x, float y, float z);
|
||||
|
||||
public void multiply(SaturnQuaternionf quaternion);
|
||||
|
||||
public void multiply(SaturnQuaternionf quaternion, float originX, float originY, float originZ);
|
||||
|
||||
public void push();
|
||||
|
||||
public void pop();
|
||||
|
||||
public Object peek();
|
||||
|
||||
public boolean isEmpty();
|
||||
|
||||
public void loadIdentity();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.saturnclient.common.minecraft.render;
|
||||
|
||||
public interface IWindow {
|
||||
public int getWidth();
|
||||
|
||||
public int getHeight();
|
||||
|
||||
public int getFramebufferWidth();
|
||||
|
||||
public int getFramebufferHeight();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.saturnclient.config;
|
||||
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class AnimationConfig {
|
||||
public static ConfigManager config;
|
||||
|
||||
// Logo
|
||||
public static final AnimationConfig logo = new AnimationConfig(true, 700, 0);
|
||||
|
||||
// Main menu
|
||||
public static final AnimationConfig mainMenu = new AnimationConfig(true, 700, 120);
|
||||
|
||||
// Mod menu
|
||||
public static final AnimationConfig modMenu = new AnimationConfig(true, 700, 20);
|
||||
|
||||
// Shift menu
|
||||
public static final AnimationConfig shiftMenu = new AnimationConfig(true, 700, 100);
|
||||
|
||||
// Cosmetics menu
|
||||
public static final AnimationConfig cosmeticsMenu = new AnimationConfig(true, 700, 40);
|
||||
|
||||
// Emote wheel
|
||||
public static final AnimationConfig emoteWheel = new AnimationConfig(true, 700, 40);
|
||||
|
||||
public static void init(ConfigManager parent) {
|
||||
config = new ConfigManager(parent, "Animations");
|
||||
|
||||
logo.init("Logo");
|
||||
mainMenu.init("Main Menu");
|
||||
modMenu.init("Mod Menu");
|
||||
shiftMenu.init("Shift Menu");
|
||||
cosmeticsMenu.init("Cosmetics Menu");
|
||||
emoteWheel.init("Emote Wheel");
|
||||
}
|
||||
|
||||
// Animation properties
|
||||
public final Property<Integer> duration;
|
||||
public final Property<Integer> stagger;
|
||||
public final Property<Integer> curve;
|
||||
|
||||
public AnimationConfig(boolean enabled, int delay, int stagger) {
|
||||
this.duration = Property.integer(delay);
|
||||
this.stagger = Property.integer(stagger);
|
||||
this.curve = Property.select(1, "Ease In Out Cubic", "Ease Out Cubic", "Ease In Out Back");
|
||||
}
|
||||
|
||||
public void init(String name) {
|
||||
// config.property("Enable " + name + " Animations", this.enabled);
|
||||
config.property(name + " Duration", this.duration);
|
||||
config.property(name + " Stagger", this.stagger);
|
||||
config.property(name + " Curve", this.curve);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.saturnclient.config;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Key;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
public class Config {
|
||||
public static ConfigManager config;
|
||||
|
||||
public static Property<Boolean> realisticLogo = Property.bool(false);
|
||||
public static Property<Boolean> saturnTitleScreen = Property.bool(true);
|
||||
public static Property<Boolean> cloakPhysics = Property.bool(true);
|
||||
public static Property<Integer> openEmoteWheel = Property.keybinding(Key.GLFW_KEY_B);
|
||||
public static Property<Boolean> stagger = Property.bool(true);
|
||||
|
||||
public static SaturnIdentifier getLogo() {
|
||||
return realisticLogo.value ? Textures.REALISTIC_LOGO : Textures.LOGO;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
File configFile = new File(MinecraftProvider.PROVIDER.getClient().getRunDirectory(), "saturn.json");
|
||||
config = new ConfigManager(configFile, "Saturn Client");
|
||||
|
||||
config.property("Realistic logo", realisticLogo);
|
||||
config.property("Saturn client title screen", saturnTitleScreen);
|
||||
config.property("Open Emote Wheel", openEmoteWheel);
|
||||
config.property("Cloak Physics", cloakPhysics);
|
||||
config.property("Stagger Animations", stagger);
|
||||
|
||||
// Initialize a sub namespace for theme
|
||||
Theme.init(config);
|
||||
|
||||
// Initialize a sub namespace for animations
|
||||
AnimationConfig.init(config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package org.saturnclient.config;
|
||||
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class Theme {
|
||||
// Main UI background (slightly warm dark to match Saturn tone)
|
||||
public static final Property<Integer> BACKGROUND = Property.color(0xFF12100D);
|
||||
|
||||
// Default text color
|
||||
public static final Property<Integer> FOREGROUND = Property.color(0xFFF2E6D2);
|
||||
|
||||
// Widget default background (normal state)
|
||||
public static final Property<Integer> PRIMARY = Property.color(0xFF1C1915);
|
||||
|
||||
// Widget text color
|
||||
public static final Property<Integer> PRIMARY_FG = Property.color(0xFFEAD9B8);
|
||||
|
||||
// Saturn brand color (hovered / enabled / selected)
|
||||
public static final Property<Integer> ACCENT = Property.color(0xFFE2BF7D);
|
||||
|
||||
// Text/icons shown on accent background
|
||||
public static final Property<Integer> ACCENT_FG = Property.color(0xFF1A140A);
|
||||
|
||||
// Misc colors
|
||||
public static final Property<Integer> SCROLL = Property.color(0xFFE2BF7D);
|
||||
|
||||
// UI metrics
|
||||
public static final Property<Integer> BG_RADIUS = Property.integer(12);
|
||||
public static final Property<Integer> WIDGET_RADIUS = Property.integer(10);
|
||||
|
||||
// Font
|
||||
public static final Property<Integer> FONT = Property.font(2);
|
||||
|
||||
public static void init(ConfigManager parent) {
|
||||
ConfigManager config = new ConfigManager(parent, "UI Style");
|
||||
config.property("Background", BACKGROUND);
|
||||
config.property("Foreground", FOREGROUND);
|
||||
config.property("Primary", PRIMARY);
|
||||
config.property("Primary Foreground", PRIMARY_FG);
|
||||
config.property("Accent", ACCENT);
|
||||
config.property("Accent Foreground", ACCENT_FG);
|
||||
config.property("Scrollbar Color", SCROLL);
|
||||
|
||||
config.property("Background Radius", BG_RADIUS);
|
||||
config.property("Widget Radius", WIDGET_RADIUS);
|
||||
|
||||
config.property("Font", FONT);
|
||||
}
|
||||
|
||||
/**
|
||||
* primary by default, accent if true
|
||||
*/
|
||||
public static int getBg(boolean hover) {
|
||||
return hover ? ACCENT.value : PRIMARY.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Foreground) primary by default, accent if true
|
||||
*/
|
||||
public static int getFg(boolean hover) {
|
||||
return hover ? ACCENT_FG.value : PRIMARY_FG.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies existing alpha with 0–255 alpha.
|
||||
*/
|
||||
public static int withAlpha(int alpha, int color) {
|
||||
alpha = Math.max(0, Math.min(255, alpha));
|
||||
|
||||
int originalAlpha = (color >>> 24) & 0xFF;
|
||||
|
||||
// Merge (multiply) alphas
|
||||
int merged = (originalAlpha * alpha) / 255;
|
||||
|
||||
return (color & 0x00FFFFFF) | (merged << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies existing alpha with 0.0–1.0 alpha.
|
||||
*/
|
||||
public static int withAlpha(float alpha, int color) {
|
||||
alpha = Math.max(0f, Math.min(1f, alpha));
|
||||
|
||||
int originalAlpha = (color >>> 24) & 0xFF;
|
||||
|
||||
int merged = (int) (originalAlpha * alpha);
|
||||
|
||||
return (color & 0x00FFFFFF) | (merged << 24);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package org.saturnclient.config.manager;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
private static File configFile;
|
||||
|
||||
// SINGLE ROOT TREE
|
||||
private static final Map<String, Property<?>> ROOT = new LinkedHashMap<>();
|
||||
|
||||
private static JsonNode cachedJson = null;
|
||||
|
||||
private final Map<String, Property<?>> currentMap;
|
||||
|
||||
private final String[] path;
|
||||
|
||||
/**
|
||||
* Creates a root namespace
|
||||
*/
|
||||
public ConfigManager(File configFile, String namespace) {
|
||||
ConfigManager.configFile = configFile;
|
||||
this.currentMap = new LinkedHashMap<>();
|
||||
this.path = new String[] { namespace };
|
||||
|
||||
ROOT.put(namespace, Property.namespace(currentMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a root namespace
|
||||
*/
|
||||
public ConfigManager(String namespace) {
|
||||
this.currentMap = new LinkedHashMap<>();
|
||||
this.path = new String[] { namespace };
|
||||
|
||||
ROOT.put(namespace, Property.namespace(currentMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-namespace inside a parent
|
||||
*/
|
||||
public ConfigManager(ConfigManager parent, String namespace) {
|
||||
this.currentMap = new LinkedHashMap<>();
|
||||
|
||||
this.path = new String[parent.path.length + 1];
|
||||
System.arraycopy(parent.path, 0, this.path, 0, parent.path.length);
|
||||
this.path[this.path.length - 1] = namespace;
|
||||
|
||||
parent.property(namespace, Property.namespace(currentMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a property
|
||||
*/
|
||||
public <T> Property<T> property(String name, Property<T> value) {
|
||||
currentMap.put(name, value);
|
||||
loadSingleProperty(name, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add empty namespace
|
||||
*/
|
||||
public ConfigManager sub(String name) {
|
||||
return new ConfigManager(this, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load entire config
|
||||
*/
|
||||
public void load() {
|
||||
JsonNode json = loadAndCache();
|
||||
if (json == null || !json.isObject())
|
||||
return;
|
||||
|
||||
loadRecursive((ObjectNode) json, ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save entire config
|
||||
*/
|
||||
public static void save() {
|
||||
|
||||
ObjectNode rootJson = MAPPER.createObjectNode();
|
||||
saveRecursive(rootJson, ROOT);
|
||||
|
||||
try {
|
||||
MAPPER.writerWithDefaultPrettyPrinter().writeValue(configFile, rootJson);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive save
|
||||
*/
|
||||
private static void saveRecursive(ObjectNode json, Map<String, Property<?>> map) {
|
||||
map.forEach((name, prop) -> {
|
||||
if (prop.isNamespace()) {
|
||||
|
||||
ObjectNode child = json.objectNode();
|
||||
saveRecursive(child, prop.getNamespaceMap());
|
||||
|
||||
json.set(name, child);
|
||||
|
||||
} else {
|
||||
|
||||
json.set(name, prop.toJson());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive load
|
||||
*/
|
||||
private static void loadRecursive(ObjectNode json, Map<String, Property<?>> map) {
|
||||
|
||||
map.forEach((name, prop) -> {
|
||||
|
||||
JsonNode element = json.get(name);
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
if (prop.isNamespace() && element.isObject()) {
|
||||
|
||||
loadRecursive((ObjectNode) element, prop.getNamespaceMap());
|
||||
|
||||
} else {
|
||||
|
||||
prop.loadFromJson(element);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load only a single property immediately after creation
|
||||
*/
|
||||
private void loadSingleProperty(String name, Property<?> prop) {
|
||||
|
||||
JsonNode source = cachedJson != null ? cachedJson : loadAndCache();
|
||||
if (source == null || !source.isObject())
|
||||
return;
|
||||
|
||||
JsonNode currentScope = source;
|
||||
|
||||
for (String segment : path) {
|
||||
|
||||
JsonNode next = currentScope.get(segment);
|
||||
|
||||
if (next != null && next.isObject()) {
|
||||
currentScope = next;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JsonNode element = currentScope.get(name);
|
||||
|
||||
if (element != null) {
|
||||
prop.loadFromJson(element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads file and caches json
|
||||
*/
|
||||
private JsonNode loadAndCache() {
|
||||
|
||||
try {
|
||||
|
||||
if (!configFile.exists()) {
|
||||
|
||||
Files.writeString(configFile.toPath(), "{}");
|
||||
cachedJson = MAPPER.createObjectNode();
|
||||
return cachedJson;
|
||||
|
||||
}
|
||||
|
||||
cachedJson = MAPPER.readTree(configFile);
|
||||
return cachedJson;
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Map<String, Property<?>> getProperties() {
|
||||
return currentMap;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package org.saturnclient.config.manager;
|
||||
|
||||
public class Key {
|
||||
/** Printable keys. */
|
||||
public static final int GLFW_KEY_SPACE = 32,
|
||||
GLFW_KEY_APOSTROPHE = 39,
|
||||
GLFW_KEY_COMMA = 44,
|
||||
GLFW_KEY_MINUS = 45,
|
||||
GLFW_KEY_PERIOD = 46,
|
||||
GLFW_KEY_SLASH = 47,
|
||||
GLFW_KEY_0 = 48,
|
||||
GLFW_KEY_1 = 49,
|
||||
GLFW_KEY_2 = 50,
|
||||
GLFW_KEY_3 = 51,
|
||||
GLFW_KEY_4 = 52,
|
||||
GLFW_KEY_5 = 53,
|
||||
GLFW_KEY_6 = 54,
|
||||
GLFW_KEY_7 = 55,
|
||||
GLFW_KEY_8 = 56,
|
||||
GLFW_KEY_9 = 57,
|
||||
GLFW_KEY_SEMICOLON = 59,
|
||||
GLFW_KEY_EQUAL = 61,
|
||||
GLFW_KEY_A = 65,
|
||||
GLFW_KEY_B = 66,
|
||||
GLFW_KEY_C = 67,
|
||||
GLFW_KEY_D = 68,
|
||||
GLFW_KEY_E = 69,
|
||||
GLFW_KEY_F = 70,
|
||||
GLFW_KEY_G = 71,
|
||||
GLFW_KEY_H = 72,
|
||||
GLFW_KEY_I = 73,
|
||||
GLFW_KEY_J = 74,
|
||||
GLFW_KEY_K = 75,
|
||||
GLFW_KEY_L = 76,
|
||||
GLFW_KEY_M = 77,
|
||||
GLFW_KEY_N = 78,
|
||||
GLFW_KEY_O = 79,
|
||||
GLFW_KEY_P = 80,
|
||||
GLFW_KEY_Q = 81,
|
||||
GLFW_KEY_R = 82,
|
||||
GLFW_KEY_S = 83,
|
||||
GLFW_KEY_T = 84,
|
||||
GLFW_KEY_U = 85,
|
||||
GLFW_KEY_V = 86,
|
||||
GLFW_KEY_W = 87,
|
||||
GLFW_KEY_X = 88,
|
||||
GLFW_KEY_Y = 89,
|
||||
GLFW_KEY_Z = 90,
|
||||
GLFW_KEY_LEFT_BRACKET = 91,
|
||||
GLFW_KEY_BACKSLASH = 92,
|
||||
GLFW_KEY_RIGHT_BRACKET = 93,
|
||||
GLFW_KEY_GRAVE_ACCENT = 96,
|
||||
GLFW_KEY_WORLD_1 = 161,
|
||||
GLFW_KEY_WORLD_2 = 162;
|
||||
|
||||
/** Function keys. */
|
||||
public static final int GLFW_KEY_ESCAPE = 256,
|
||||
GLFW_KEY_ENTER = 257,
|
||||
GLFW_KEY_TAB = 258,
|
||||
GLFW_KEY_BACKSPACE = 259,
|
||||
GLFW_KEY_INSERT = 260,
|
||||
GLFW_KEY_DELETE = 261,
|
||||
GLFW_KEY_RIGHT = 262,
|
||||
GLFW_KEY_LEFT = 263,
|
||||
GLFW_KEY_DOWN = 264,
|
||||
GLFW_KEY_UP = 265,
|
||||
GLFW_KEY_PAGE_UP = 266,
|
||||
GLFW_KEY_PAGE_DOWN = 267,
|
||||
GLFW_KEY_HOME = 268,
|
||||
GLFW_KEY_END = 269,
|
||||
GLFW_KEY_CAPS_LOCK = 280,
|
||||
GLFW_KEY_SCROLL_LOCK = 281,
|
||||
GLFW_KEY_NUM_LOCK = 282,
|
||||
GLFW_KEY_PRINT_SCREEN = 283,
|
||||
GLFW_KEY_PAUSE = 284,
|
||||
GLFW_KEY_F1 = 290,
|
||||
GLFW_KEY_F2 = 291,
|
||||
GLFW_KEY_F3 = 292,
|
||||
GLFW_KEY_F4 = 293,
|
||||
GLFW_KEY_F5 = 294,
|
||||
GLFW_KEY_F6 = 295,
|
||||
GLFW_KEY_F7 = 296,
|
||||
GLFW_KEY_F8 = 297,
|
||||
GLFW_KEY_F9 = 298,
|
||||
GLFW_KEY_F10 = 299,
|
||||
GLFW_KEY_F11 = 300,
|
||||
GLFW_KEY_F12 = 301,
|
||||
GLFW_KEY_F13 = 302,
|
||||
GLFW_KEY_F14 = 303,
|
||||
GLFW_KEY_F15 = 304,
|
||||
GLFW_KEY_F16 = 305,
|
||||
GLFW_KEY_F17 = 306,
|
||||
GLFW_KEY_F18 = 307,
|
||||
GLFW_KEY_F19 = 308,
|
||||
GLFW_KEY_F20 = 309,
|
||||
GLFW_KEY_F21 = 310,
|
||||
GLFW_KEY_F22 = 311,
|
||||
GLFW_KEY_F23 = 312,
|
||||
GLFW_KEY_F24 = 313,
|
||||
GLFW_KEY_F25 = 314,
|
||||
GLFW_KEY_KP_0 = 320,
|
||||
GLFW_KEY_KP_1 = 321,
|
||||
GLFW_KEY_KP_2 = 322,
|
||||
GLFW_KEY_KP_3 = 323,
|
||||
GLFW_KEY_KP_4 = 324,
|
||||
GLFW_KEY_KP_5 = 325,
|
||||
GLFW_KEY_KP_6 = 326,
|
||||
GLFW_KEY_KP_7 = 327,
|
||||
GLFW_KEY_KP_8 = 328,
|
||||
GLFW_KEY_KP_9 = 329,
|
||||
GLFW_KEY_KP_DECIMAL = 330,
|
||||
GLFW_KEY_KP_DIVIDE = 331,
|
||||
GLFW_KEY_KP_MULTIPLY = 332,
|
||||
GLFW_KEY_KP_SUBTRACT = 333,
|
||||
GLFW_KEY_KP_ADD = 334,
|
||||
GLFW_KEY_KP_ENTER = 335,
|
||||
GLFW_KEY_KP_EQUAL = 336,
|
||||
GLFW_KEY_LEFT_SHIFT = 340,
|
||||
GLFW_KEY_LEFT_CONTROL = 341,
|
||||
GLFW_KEY_LEFT_ALT = 342,
|
||||
GLFW_KEY_LEFT_SUPER = 343,
|
||||
GLFW_KEY_RIGHT_SHIFT = 344,
|
||||
GLFW_KEY_RIGHT_CONTROL = 345,
|
||||
GLFW_KEY_RIGHT_ALT = 346,
|
||||
GLFW_KEY_RIGHT_SUPER = 347,
|
||||
GLFW_KEY_MENU = 348,
|
||||
GLFW_KEY_LAST = GLFW_KEY_MENU;
|
||||
|
||||
/** If this bit is set one or more Shift keys were held down. */
|
||||
public static final int GLFW_MOD_SHIFT = 0x1;
|
||||
|
||||
/** If this bit is set one or more Control keys were held down. */
|
||||
public static final int GLFW_MOD_CONTROL = 0x2;
|
||||
|
||||
/** If this bit is set one or more Alt keys were held down. */
|
||||
public static final int GLFW_MOD_ALT = 0x4;
|
||||
|
||||
/** If this bit is set one or more Super keys were held down. */
|
||||
public static final int GLFW_MOD_SUPER = 0x8;
|
||||
|
||||
/**
|
||||
* If this bit is set the Caps Lock key is enabled and the
|
||||
* {@link #GLFW_LOCK_KEY_MODS LOCK_KEY_MODS} input mode is set.
|
||||
*/
|
||||
public static final int GLFW_MOD_CAPS_LOCK = 0x10;
|
||||
|
||||
/**
|
||||
* If this bit is set the Num Lock key is enabled and the
|
||||
* {@link #GLFW_LOCK_KEY_MODS LOCK_KEY_MODS} input mode is set.
|
||||
*/
|
||||
public static final int GLFW_MOD_NUM_LOCK = 0x20;
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
package org.saturnclient.config.manager;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Property<T> {
|
||||
|
||||
public static class NamedProperty<T> {
|
||||
public String name;
|
||||
public Property<T> prop;
|
||||
|
||||
public NamedProperty(String name, Property<T> value) {
|
||||
this.name = name;
|
||||
this.prop = value;
|
||||
}
|
||||
}
|
||||
|
||||
public enum PropertyType {
|
||||
BOOLEAN,
|
||||
INTEGER,
|
||||
FLOAT,
|
||||
STRING,
|
||||
HEX,
|
||||
NAMESPACE,
|
||||
SELECT,
|
||||
KEYBINDING,
|
||||
}
|
||||
|
||||
public T value;
|
||||
public boolean isReset = false;
|
||||
private T defaultValue;
|
||||
private String[] availableValues;
|
||||
private final PropertyType type;
|
||||
private boolean wasPressedLastTick = false;
|
||||
|
||||
private Property(T value, PropertyType type) {
|
||||
this.value = value;
|
||||
this.defaultValue = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
// ---------- Factory Methods ----------
|
||||
|
||||
public static <T> Property<T> from(T value) {
|
||||
if (value instanceof Boolean)
|
||||
return new Property<>(value, PropertyType.BOOLEAN);
|
||||
if (value instanceof Integer)
|
||||
return new Property<>(value, PropertyType.INTEGER);
|
||||
if (value instanceof Float)
|
||||
return new Property<>(value, PropertyType.FLOAT);
|
||||
if (value instanceof String)
|
||||
return new Property<>(value, PropertyType.STRING);
|
||||
if (valueIsNamespace(value))
|
||||
return new Property<>(value, PropertyType.NAMESPACE);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Property<Integer> font(int value) {
|
||||
return select(value, "Default", "Inter", "Inter bold");
|
||||
}
|
||||
|
||||
public static Property<Integer> select(Integer value, String... availableValues) {
|
||||
Property<Integer> property = new Property<>(value, PropertyType.SELECT);
|
||||
property.availableValues = availableValues;
|
||||
return property;
|
||||
}
|
||||
|
||||
public static Property<Map<String, Property<?>>> namespace(Map<String, Property<?>> value) {
|
||||
return new Property<>(value, PropertyType.NAMESPACE);
|
||||
}
|
||||
|
||||
public static Property<Boolean> bool(boolean value) {
|
||||
return new Property<>(value, PropertyType.BOOLEAN);
|
||||
}
|
||||
|
||||
public static Property<Integer> integer(int value) {
|
||||
return new Property<>(value, PropertyType.INTEGER);
|
||||
}
|
||||
|
||||
public static Property<Float> floatProp(float value) {
|
||||
return new Property<>(value, PropertyType.FLOAT);
|
||||
}
|
||||
|
||||
public static Property<String> string(String value) {
|
||||
return new Property<>(value, PropertyType.STRING);
|
||||
}
|
||||
|
||||
public static Property<Integer> color(int value) {
|
||||
return new Property<>(value, PropertyType.HEX);
|
||||
}
|
||||
|
||||
public static Property<Integer> keybinding(int value) {
|
||||
return new Property<>(value, PropertyType.KEYBINDING);
|
||||
}
|
||||
|
||||
// ---------- Select Helpers ----------
|
||||
|
||||
public void next() {
|
||||
if (type == PropertyType.SELECT) {
|
||||
int i = (Integer) value;
|
||||
setValue((i < availableValues.length - 1) ? i + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void prev() {
|
||||
if (type == PropertyType.SELECT) {
|
||||
int i = (Integer) value;
|
||||
setValue((i > 0) ? i - 1 : availableValues.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelection(int selection) {
|
||||
if (type == PropertyType.SELECT && selection >= 0 && selection < availableValues.length) {
|
||||
setValue(selection);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelection() {
|
||||
return (type == PropertyType.SELECT) ? availableValues[(Integer) value] : null;
|
||||
}
|
||||
|
||||
// ---------- Lifecycle ----------
|
||||
|
||||
public void reset() {
|
||||
value = defaultValue;
|
||||
isReset = true;
|
||||
}
|
||||
|
||||
public PropertyType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Property<?>> getNamespaceValue() {
|
||||
if (type == PropertyType.NAMESPACE && value instanceof Map) {
|
||||
return (Map<String, Property<?>>) value;
|
||||
}
|
||||
throw new IllegalStateException("Property is not a namespace");
|
||||
}
|
||||
|
||||
// ---------- JSON Serialization ----------
|
||||
|
||||
public JsonNode toJson() {
|
||||
|
||||
switch (type) {
|
||||
|
||||
case BOOLEAN:
|
||||
return JsonNodeFactory.instance.booleanNode((Boolean) value);
|
||||
|
||||
case INTEGER:
|
||||
return JsonNodeFactory.instance.numberNode((Integer) value);
|
||||
|
||||
case FLOAT:
|
||||
return JsonNodeFactory.instance.numberNode((Float) value);
|
||||
|
||||
case STRING:
|
||||
return JsonNodeFactory.instance.textNode((String) value);
|
||||
|
||||
case HEX:
|
||||
return JsonNodeFactory.instance.textNode(
|
||||
String.format("#%08X", (Integer) value));
|
||||
|
||||
case KEYBINDING:
|
||||
case SELECT:
|
||||
return JsonNodeFactory.instance.numberNode((Integer) value);
|
||||
|
||||
case NAMESPACE:
|
||||
|
||||
ObjectNode nested = JsonNodeFactory.instance.objectNode();
|
||||
|
||||
getNamespaceValue().forEach((k, v) -> {
|
||||
nested.set(k, v.toJson());
|
||||
});
|
||||
|
||||
return nested;
|
||||
|
||||
default:
|
||||
return JsonNodeFactory.instance.textNode(String.valueOf(value));
|
||||
}
|
||||
}
|
||||
|
||||
public void loadFromJson(JsonNode element) {
|
||||
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
|
||||
case BOOLEAN:
|
||||
if (element.isBoolean())
|
||||
setValue(element.booleanValue());
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
if (element.isInt())
|
||||
setValue(element.intValue());
|
||||
else if (element.isTextual())
|
||||
setValue(parseHexToInt(element.textValue()));
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
if (element.isNumber())
|
||||
setValue(element.floatValue());
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
if (element.isTextual())
|
||||
setValue(element.textValue());
|
||||
break;
|
||||
|
||||
case HEX:
|
||||
if (element.isTextual())
|
||||
setValue(parseHexToInt(element.textValue()));
|
||||
break;
|
||||
|
||||
case NAMESPACE:
|
||||
|
||||
if (element.isObject()) {
|
||||
|
||||
ObjectNode obj = (ObjectNode) element;
|
||||
|
||||
getNamespaceValue().forEach((k, v) -> {
|
||||
v.loadFromJson(obj.get(k));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SELECT:
|
||||
if (element.isInt())
|
||||
setSelection(element.intValue());
|
||||
break;
|
||||
|
||||
case KEYBINDING:
|
||||
if (element.isInt())
|
||||
setValue(element.intValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Utility ----------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
public static boolean valueIsNamespace(Object obj) {
|
||||
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);
|
||||
}
|
||||
|
||||
// ---------- Keybindings (no SaturnClient) ----------
|
||||
|
||||
public boolean isKeyPressed() {
|
||||
|
||||
return (Integer) value != -1 &&
|
||||
MinecraftProvider.PROVIDER.isKeyPressed((Integer) value);
|
||||
}
|
||||
|
||||
public boolean wasKeyPressed() {
|
||||
boolean pressed = isKeyPressed();
|
||||
|
||||
boolean result = pressed && !wasPressedLastTick;
|
||||
|
||||
wasPressedLastTick = pressed;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------- HEX ----------
|
||||
|
||||
public static int parseHexToInt(String hex) {
|
||||
|
||||
hex = hex.replace("#", "");
|
||||
|
||||
if (hex.length() == 6)
|
||||
hex = "FF" + hex;
|
||||
|
||||
if (hex.length() != 8)
|
||||
throw new IllegalArgumentException(
|
||||
"Hex must be 6 or 8 chars long, got '" + hex + "'");
|
||||
|
||||
return (int) Long.parseLong(hex, 16);
|
||||
}
|
||||
|
||||
// ---------- Misc ----------
|
||||
|
||||
public Property<T> copy() {
|
||||
return new Property<>(this.value, this.type);
|
||||
}
|
||||
|
||||
public boolean isNamespace() {
|
||||
return type == PropertyType.NAMESPACE;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Property<?>> getNamespaceMap() {
|
||||
return isNamespace() ? (Map<String, Property<?>>) value : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.saturnclient.cosmetics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Emotes {
|
||||
public static List<String> availableEmotes = new ArrayList<>();
|
||||
|
||||
public static void initialize() {
|
||||
availableEmotes.add("tpose");
|
||||
availableEmotes.add("back_flip");
|
||||
availableEmotes.add("facepalm");
|
||||
availableEmotes.add("cry");
|
||||
availableEmotes.add("giga_chad");
|
||||
availableEmotes.add("front_flip");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.saturnclient.cosmetics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.saturnclient.client.ServiceClient;
|
||||
import org.saturnclient.client.player.SaturnPlayer;
|
||||
|
||||
public class Hats {
|
||||
public static final String[] ALL_HATS = { "horns_black", "horns_white", "halo", "halo_black" };
|
||||
public static List<String> availableHats = new ArrayList<>();
|
||||
|
||||
public static void initialize() {
|
||||
availableHats.add(0, "");
|
||||
}
|
||||
|
||||
public static void setHat(String hatName) {
|
||||
if (availableHats.contains(hatName)) {
|
||||
setHat(ServiceClient.uuid, hatName);
|
||||
ServiceClient.setHat(hatName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setHat(UUID uuid, String hatName) {
|
||||
SaturnPlayer player = SaturnPlayer.get(uuid);
|
||||
if (player != null) {
|
||||
player.hat = hatName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.saturnclient.modules;
|
||||
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public interface HudMod {
|
||||
public ModDimensions getDimensions();
|
||||
|
||||
public void renderDummy(RenderScope scope);
|
||||
|
||||
public void renderHud(RenderScope scope);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.saturnclient.modules;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.config.manager.Property.NamedProperty;
|
||||
|
||||
public class ModDimensions {
|
||||
public Property<Integer> x = Property.integer(0);
|
||||
public Property<Integer> y = Property.integer(0);
|
||||
public Property<Float> scale = Property.floatProp(1.0f);
|
||||
public Property<Integer> bgColor = Property.color(0x00000000);
|
||||
public Property<Integer> fgColor = Property.color(0xFFffffff);
|
||||
public Property<Integer> radius = Property.integer(0);
|
||||
public Property<Integer> font = Property.font(0);
|
||||
public boolean renderBackground = true;
|
||||
|
||||
public int width = 0;
|
||||
public int height = 0;
|
||||
|
||||
public NamedProperty<Map<String, Property<?>>> prop() {
|
||||
return Property.namespace(Map.of(
|
||||
"X", x,
|
||||
"Y", y,
|
||||
"Scale", scale,
|
||||
"Background Color", bgColor,
|
||||
"Foreground Color", fgColor,
|
||||
"Corner Radius", radius,
|
||||
"Font", font)).named("In-Game Display");
|
||||
}
|
||||
|
||||
public ModDimensions() {
|
||||
}
|
||||
|
||||
public ModDimensions(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public ModDimensions(int x, int y, int width, int height) {
|
||||
this.x.value = x;
|
||||
this.y.value = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public ModDimensions(int x, int y, int width, int height, float scale) {
|
||||
this.x.value = x;
|
||||
this.y.value = y;
|
||||
this.scale.value = scale;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.saturnclient.modules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ModManager {
|
||||
public static List<Module> ENABLED_MODS = new ArrayList<>();
|
||||
public static Module[] MODS = {};
|
||||
|
||||
public static void init(ModuleProvider provider) {
|
||||
MODS = provider.getMods();
|
||||
updateEnabledModules();
|
||||
}
|
||||
|
||||
public static synchronized void updateEnabledModules() {
|
||||
ENABLED_MODS.clear();
|
||||
for (Module m : MODS) {
|
||||
if (m.isEnabled()) {
|
||||
ENABLED_MODS.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Module[] getAllMods() {
|
||||
return MODS;
|
||||
}
|
||||
|
||||
public interface ModuleProvider {
|
||||
Module[] getMods();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.saturnclient.modules;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Property.NamedProperty;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
public abstract class Module {
|
||||
private final ModuleDetails details;
|
||||
private final ConfigManager configManager;
|
||||
|
||||
public Module(ModuleDetails details, NamedProperty<?>... props) {
|
||||
this.details = details;
|
||||
configManager = new ConfigManager(details.name);
|
||||
for (NamedProperty<?> prop : props) {
|
||||
configManager.property(prop.name, prop.prop);
|
||||
}
|
||||
}
|
||||
|
||||
public void render(RenderScope scope) {
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
}
|
||||
|
||||
public abstract boolean isEnabled();
|
||||
|
||||
public final void setEnabled(boolean e) {
|
||||
onEnabled(e);
|
||||
ModManager.updateEnabledModules();
|
||||
}
|
||||
|
||||
public abstract void onEnabled(boolean e);
|
||||
|
||||
public final String getName() {
|
||||
return details.name;
|
||||
}
|
||||
|
||||
public SaturnIdentifier getIconTexture() {
|
||||
return Textures.getModIcon(details.namespace);
|
||||
}
|
||||
|
||||
public ConfigManager getConfig() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return details.description;
|
||||
}
|
||||
|
||||
public String[] getTags() {
|
||||
return details.tags;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return details.version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.saturnclient.modules;
|
||||
|
||||
public class ModuleDetails {
|
||||
public String name;
|
||||
public String namespace;
|
||||
public String description;
|
||||
public String version;
|
||||
public String[] tags = {};
|
||||
|
||||
public ModuleDetails(String name, String namespace) {
|
||||
this.name = name;
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public ModuleDetails name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModuleDetails namespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModuleDetails description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModuleDetails version(String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModuleDetails tags(String... tags) {
|
||||
this.tags = tags;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnItemStack;
|
||||
|
||||
public interface ArmorDisplayInterface {
|
||||
|
||||
SaturnItemStack getMainHand();
|
||||
|
||||
SaturnItemStack getHelmet();
|
||||
|
||||
SaturnItemStack getChestplate();
|
||||
|
||||
SaturnItemStack getLeggings();
|
||||
|
||||
SaturnItemStack getBoots();
|
||||
|
||||
SaturnItemStack getDummyMainHand();
|
||||
|
||||
SaturnItemStack getDummyHelmet();
|
||||
|
||||
SaturnItemStack getDummyChestplate();
|
||||
|
||||
SaturnItemStack getDummyLeggings();
|
||||
|
||||
SaturnItemStack getDummyBoots();
|
||||
|
||||
boolean isEmpty(SaturnItemStack stack);
|
||||
|
||||
int getMaxDamage(SaturnItemStack stack);
|
||||
|
||||
int getDamage(SaturnItemStack stack);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface AutoSprintInterface {
|
||||
|
||||
boolean hasPlayer();
|
||||
|
||||
boolean hasNetwork();
|
||||
|
||||
boolean isForwardPressed();
|
||||
|
||||
boolean isBackPressed();
|
||||
|
||||
boolean isSneaking();
|
||||
|
||||
boolean hasHorizontalCollision();
|
||||
|
||||
boolean isUsingItem();
|
||||
|
||||
void setSprinting(boolean sprinting);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface CoordinatesInterface {
|
||||
|
||||
int getPlayerX();
|
||||
|
||||
int getPlayerY();
|
||||
|
||||
int getPlayerZ();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface CrosshairInterface {
|
||||
|
||||
boolean isTargetingLivingEntity();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface DayCounterInterface {
|
||||
|
||||
long getDay();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface FpsInterface {
|
||||
|
||||
int getFps();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface FreelookInterface {
|
||||
|
||||
boolean isFirstPerson();
|
||||
|
||||
void setFirstPerson();
|
||||
|
||||
void setThirdPersonBack();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface HealthDisplayInterface {
|
||||
|
||||
float getPlayerHealth();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface KeystrokesInterface {
|
||||
|
||||
boolean isForwardPressed();
|
||||
boolean isBackPressed();
|
||||
boolean isLeftPressed();
|
||||
boolean isRightPressed();
|
||||
boolean isJumpPressed();
|
||||
boolean isAttackPressed();
|
||||
boolean isUsePressed();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface NametagsInterface {
|
||||
|
||||
public static interface EntityState {
|
||||
|
||||
String getCustomName();
|
||||
|
||||
float getHealth();
|
||||
|
||||
float getMaxHealth();
|
||||
|
||||
EntityType getEntityType();
|
||||
}
|
||||
|
||||
public static enum EntityType {
|
||||
PLAYER,
|
||||
PASSIVE,
|
||||
HOSTILE,
|
||||
OTHER
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface PingInterface {
|
||||
|
||||
/** Returns current player ping in milliseconds */
|
||||
int getPing();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
public interface SpeedometerInterface {
|
||||
|
||||
/** Returns the current player or vehicle velocity in blocks per tick */
|
||||
Velocity getVelocity();
|
||||
|
||||
/** Returns true if player or vehicle is on ground */
|
||||
boolean isOnGround();
|
||||
|
||||
class Velocity {
|
||||
public final double x, y, z;
|
||||
|
||||
public Velocity(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.saturnclient.modules.interfaces;
|
||||
|
||||
import java.util.List;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnSprite;
|
||||
|
||||
public interface StatusEffectsInterface {
|
||||
|
||||
/** Returns a list of currently active effects */
|
||||
List<Effect> getActiveEffects();
|
||||
|
||||
/** Returns a dummy list of effects for dummy rendering */
|
||||
List<Effect> getDummyEffects();
|
||||
|
||||
/** Represents a single effect for rendering purposes */
|
||||
class Effect {
|
||||
private final SaturnSprite icon;
|
||||
private final int durationSeconds;
|
||||
private final boolean infinite;
|
||||
private final boolean showIcon;
|
||||
private final String infiniteText;
|
||||
|
||||
public Effect(SaturnSprite icon, int durationSeconds, boolean infinite, boolean showIcon, String infiniteText) {
|
||||
this.icon = icon;
|
||||
this.durationSeconds = durationSeconds;
|
||||
this.infinite = infinite;
|
||||
this.showIcon = showIcon;
|
||||
this.infiniteText = infiniteText;
|
||||
}
|
||||
|
||||
public SaturnSprite getIcon() { return icon; }
|
||||
public int getDurationSeconds() { return durationSeconds; }
|
||||
public boolean isInfinite() { return infinite; }
|
||||
public boolean shouldShowIcon() { return showIcon; }
|
||||
public String getInfiniteText() { return infiniteText; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.ArmorDisplayInterface;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnItemStack;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class ArmorDisplay extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(40, 75);
|
||||
private static Property<Boolean> useMainHand = Property.bool(true);
|
||||
|
||||
private final ArmorDisplayInterface minecraft;
|
||||
|
||||
public ArmorDisplay(ArmorDisplayInterface minecraft) {
|
||||
super(new ModuleDetails("Armor Display", "armor")
|
||||
.description("Displays armor durability")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
useMainHand.named("Use Main Hand"),
|
||||
dimensions.prop());
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
public void renderArmor(RenderScope scope,
|
||||
SaturnItemStack mainHand,
|
||||
SaturnItemStack helmet,
|
||||
SaturnItemStack chestplate,
|
||||
SaturnItemStack leggings,
|
||||
SaturnItemStack boots) {
|
||||
|
||||
int row = 0;
|
||||
|
||||
if (useMainHand.value && !minecraft.isEmpty(mainHand)) {
|
||||
scope.drawItem(mainHand, 0, 15 * row);
|
||||
renderHealth(scope, row, minecraft.getMaxDamage(mainHand), minecraft.getDamage(mainHand));
|
||||
row++;
|
||||
}
|
||||
|
||||
if (!minecraft.isEmpty(helmet)) {
|
||||
scope.drawItem(helmet, 0, 15 * row);
|
||||
renderHealth(scope, row, minecraft.getMaxDamage(helmet), minecraft.getDamage(helmet));
|
||||
row++;
|
||||
}
|
||||
|
||||
if (!minecraft.isEmpty(chestplate)) {
|
||||
scope.drawItem(chestplate, 0, 15 * row);
|
||||
renderHealth(scope, row, minecraft.getMaxDamage(chestplate), minecraft.getDamage(chestplate));
|
||||
row++;
|
||||
}
|
||||
|
||||
if (!minecraft.isEmpty(leggings)) {
|
||||
scope.drawItem(leggings, 0, 15 * row);
|
||||
renderHealth(scope, row, minecraft.getMaxDamage(leggings), minecraft.getDamage(leggings));
|
||||
row++;
|
||||
}
|
||||
|
||||
if (!minecraft.isEmpty(boots)) {
|
||||
scope.drawItem(boots, 0, 15 * row);
|
||||
renderHealth(scope, row, minecraft.getMaxDamage(boots), minecraft.getDamage(boots));
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
public void renderHealth(RenderScope scope, int i, int maxDamage, int damage) {
|
||||
if (maxDamage > 0) {
|
||||
scope.drawText(
|
||||
0.5f,
|
||||
"" + (maxDamage - damage),
|
||||
17,
|
||||
(15 * i) + 3,
|
||||
dimensions.font.value,
|
||||
dimensions.fgColor.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
renderArmor(scope,
|
||||
minecraft.getMainHand(),
|
||||
minecraft.getHelmet(),
|
||||
minecraft.getChestplate(),
|
||||
minecraft.getLeggings(),
|
||||
minecraft.getBoots());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderArmor(scope,
|
||||
minecraft.getDummyMainHand(),
|
||||
minecraft.getDummyHelmet(),
|
||||
minecraft.getDummyChestplate(),
|
||||
minecraft.getDummyLeggings(),
|
||||
minecraft.getDummyBoots());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.AutoSprintInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class AutoSprint extends Module {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
|
||||
private final AutoSprintInterface minecraft;
|
||||
|
||||
public AutoSprint(AutoSprintInterface minecraft) {
|
||||
super(
|
||||
new ModuleDetails("Auto Sprint", "sprint")
|
||||
.description("Makes the player always sprint")
|
||||
.tags("Movement")
|
||||
.version("v0.1.0"),
|
||||
enabled.named("Enabled"));
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (!minecraft.hasPlayer() || !minecraft.hasNetwork()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (minecraft.isForwardPressed()
|
||||
&& !minecraft.isBackPressed()
|
||||
&& !minecraft.isSneaking()
|
||||
&& !minecraft.hasHorizontalCollision()
|
||||
&& !minecraft.isUsingItem()) {
|
||||
|
||||
minecraft.setSprinting(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.LocalTime;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Clock extends Module implements HudMod {
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Integer> format = Property.select(0, "24 hour", "12 hour");
|
||||
private static Property<Boolean> seconds = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight());
|
||||
|
||||
public Clock() {
|
||||
super(new ModuleDetails("Clock", "clock")
|
||||
.description("Displays the current real-world time")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
format.named("Format"),
|
||||
seconds.named("Show seconds"),
|
||||
dimensions.prop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderClock(scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
renderClock(scope);
|
||||
}
|
||||
|
||||
public void renderClock(RenderScope scope) {
|
||||
String text = "";
|
||||
LocalTime currentTime = LocalTime.now();
|
||||
|
||||
switch (format.value) {
|
||||
case 0:
|
||||
if (seconds.value) {
|
||||
text = currentTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
|
||||
} else {
|
||||
text = currentTime.format(DateTimeFormatter.ofPattern("HH:mm"));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (seconds.value) {
|
||||
text = currentTime.format(DateTimeFormatter.ofPattern("hh:mm:ss a"));
|
||||
} else {
|
||||
text = currentTime.format(DateTimeFormatter.ofPattern("hh:mm a"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
scope.drawText(text,
|
||||
0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
dimensions.height = 18 * text.split("\n").length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.CoordinatesInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Coordinates extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
|
||||
private static Property<Integer> displayMethod = Property.select(
|
||||
0,
|
||||
"Flat",
|
||||
"Flat annotated",
|
||||
"Newline",
|
||||
"Newline annotated");
|
||||
|
||||
private static ModDimensions dimensions = new ModDimensions(40, 18);
|
||||
|
||||
private final CoordinatesInterface minecraft;
|
||||
|
||||
public Coordinates(CoordinatesInterface minecraft) {
|
||||
super(new ModuleDetails("Coordinates", "coords")
|
||||
.description("Displays your current coordinates")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
displayMethod.named("Display Method"),
|
||||
dimensions.prop());
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderCoords(532, 69, 253, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
int x = minecraft.getPlayerX();
|
||||
int y = minecraft.getPlayerY();
|
||||
int z = minecraft.getPlayerZ();
|
||||
|
||||
renderCoords(x, y, z, scope);
|
||||
}
|
||||
|
||||
public void renderCoords(int x, int y, int z, RenderScope scope) {
|
||||
|
||||
String f = "%d %d %d";
|
||||
|
||||
switch (displayMethod.value) {
|
||||
case 1:
|
||||
f = "X: %d Y: %d Z: %d";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
f = "%d\n%d\n%d";
|
||||
break;
|
||||
|
||||
case 3:
|
||||
f = "X: %d\nY: %d\nZ: %d";
|
||||
break;
|
||||
}
|
||||
|
||||
String text = String.format(f, x, y, z);
|
||||
|
||||
scope.drawText(
|
||||
text,
|
||||
0,
|
||||
0,
|
||||
dimensions.font.value,
|
||||
dimensions.fgColor.value);
|
||||
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
dimensions.height = 18 * text.split("\n").length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.CrosshairInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
public class Crosshair extends Module {
|
||||
|
||||
public static Property<Boolean> enabled = Property.bool(false);
|
||||
|
||||
private final CrosshairInterface minecraft;
|
||||
|
||||
public Crosshair(CrosshairInterface minecraft) {
|
||||
super(
|
||||
new ModuleDetails("Crosshair", "crosshair")
|
||||
.description("Changes the crosshair if you're aiming at a entity")
|
||||
.tags("Visuals", "Utility")
|
||||
.version("v0.1.0"),
|
||||
enabled.named("Enabled"));
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope scope) {
|
||||
|
||||
if (enabled.value && minecraft.isTargetingLivingEntity()) {
|
||||
|
||||
int scaledWidth = 15;
|
||||
int scaledHeight = 15;
|
||||
|
||||
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 onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.DayCounterInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class DayCounter extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(40, 18);
|
||||
|
||||
private final DayCounterInterface minecraft;
|
||||
|
||||
long day = 0;
|
||||
|
||||
public DayCounter(DayCounterInterface minecraft) {
|
||||
super(new ModuleDetails("DayCounter", "day")
|
||||
.description("Displays the number of days that have passed")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
dimensions.prop());
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderDay(271, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
day = minecraft.getDay();
|
||||
renderDay(day, scope);
|
||||
}
|
||||
|
||||
public void renderDay(long day, RenderScope scope) {
|
||||
String text = "Day: " + day;
|
||||
|
||||
scope.drawText(
|
||||
text,
|
||||
0,
|
||||
0,
|
||||
dimensions.font.value,
|
||||
dimensions.fgColor.value);
|
||||
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
dimensions.height = 18 * text.split("\n").length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.FpsInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Fps extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight());
|
||||
|
||||
private final FpsInterface minecraft;
|
||||
|
||||
public Fps(FpsInterface minecraft) {
|
||||
super(new ModuleDetails("FPS Display", "fps")
|
||||
.description("Displays current FPS")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
dimensions.prop());
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
int fps = minecraft.getFps();
|
||||
|
||||
String text = fps + " FPS";
|
||||
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
String text = "369 FPS";
|
||||
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.FreelookInterface;
|
||||
import org.saturnclient.config.manager.Key;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class Freelook extends Module {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Boolean> toggle = Property.bool(true);
|
||||
|
||||
public static Property<Integer> freelookKey = Property.keybinding(Key.GLFW_KEY_H);
|
||||
|
||||
public static boolean isFreeLooking = false;
|
||||
private static boolean was1stPerson = false;
|
||||
|
||||
private final FreelookInterface minecraft;
|
||||
|
||||
public Freelook(FreelookInterface minecraft) {
|
||||
super(
|
||||
new ModuleDetails("Freelook", "freelook")
|
||||
.description("Allows you to look around freely without moving your character")
|
||||
.tags("Movement", "Camera")
|
||||
.version("0.1.0"),
|
||||
enabled.named("Enabled"),
|
||||
toggle.named("Toggle freelook"),
|
||||
freelookKey.named("Freelook Keybinding"));
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
|
||||
if (toggle.value) {
|
||||
|
||||
if (freelookKey.wasKeyPressed()) {
|
||||
|
||||
if (isFreeLooking) {
|
||||
stopFreelook();
|
||||
} else {
|
||||
startFreelook();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (freelookKey.isKeyPressed()) {
|
||||
|
||||
if (!isFreeLooking) {
|
||||
startFreelook();
|
||||
}
|
||||
|
||||
} else if (isFreeLooking) {
|
||||
|
||||
stopFreelook();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void startFreelook() {
|
||||
isFreeLooking = true;
|
||||
|
||||
was1stPerson = minecraft.isFirstPerson();
|
||||
|
||||
minecraft.setThirdPersonBack();
|
||||
}
|
||||
|
||||
private void stopFreelook() {
|
||||
|
||||
if (was1stPerson) {
|
||||
minecraft.setFirstPerson();
|
||||
}
|
||||
|
||||
isFreeLooking = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class Fullbright extends Module {
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Integer> brightness = Property.integer(100);
|
||||
|
||||
public Fullbright() {
|
||||
super(
|
||||
new ModuleDetails("Fullbright", "fullbright")
|
||||
.description("Allows you to see in the dark")
|
||||
.tags("Camera")
|
||||
.version("v0.1.0"),
|
||||
enabled.named("Enabled"),
|
||||
brightness.named("Brightness %"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
public static boolean shouldOverrideBrightness() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
public static float getBrightnessValue() {
|
||||
return brightness.value / 10;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.HealthDisplayInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class HealthDisplay extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Integer> displayMode = Property.select(0, "Health", "Hearts");
|
||||
private static Property<Integer> decimals = Property.select(0, "0", "1", "2");
|
||||
|
||||
private static ModDimensions dimensions = new ModDimensions(40, 18);
|
||||
|
||||
private final HealthDisplayInterface minecraft;
|
||||
|
||||
public HealthDisplay(HealthDisplayInterface minecraft) {
|
||||
super(new ModuleDetails("Health display", "health")
|
||||
.description("Displays your current health")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
displayMode.named("Display mode"),
|
||||
decimals.named("Decimals"),
|
||||
dimensions.prop());
|
||||
|
||||
this.minecraft = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderHealth(10, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
float health = minecraft.getPlayerHealth();
|
||||
|
||||
switch (displayMode.value) {
|
||||
case 1:
|
||||
health = health / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
renderHealth(health, scope);
|
||||
}
|
||||
|
||||
public void renderHealth(float health, RenderScope scope) {
|
||||
|
||||
String text = "";
|
||||
|
||||
switch (decimals.value) {
|
||||
case 0:
|
||||
text = String.format("%.0f ", health);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
text = String.format("%.1f ", health);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
text = String.format("%.2f ", health);
|
||||
break;
|
||||
}
|
||||
|
||||
scope.drawText(
|
||||
text,
|
||||
0,
|
||||
0,
|
||||
dimensions.font.value,
|
||||
dimensions.fgColor.value
|
||||
);
|
||||
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
dimensions.height = 18 * text.split("\n").length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.KeystrokesInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class Keystrokes extends Module implements HudMod {
|
||||
|
||||
private static final Property<Boolean> enabled = Property.bool(false);
|
||||
private static final Property<Boolean> showMouse = Property.bool(true);
|
||||
private static final Property<Boolean> showSpace = Property.bool(false);
|
||||
|
||||
private static final Property<Integer> clickBg = Property.color(0xFFCCCCCC);
|
||||
private static final Property<Integer> clickFg = Property.color(0xFFFFFFFF);
|
||||
|
||||
private static final ModDimensions dimensions = new ModDimensions(78, 54);
|
||||
|
||||
private final KeystrokesInterface minecraft;
|
||||
|
||||
// Key states
|
||||
private boolean w, a, s, d, lmb, rmb, space;
|
||||
|
||||
// Layout constants
|
||||
private static final int KEY_SIZE = 24;
|
||||
private static final int KEY_SPACING = 3;
|
||||
private static final int MOUSE_WIDTH = 38;
|
||||
private static final int MOUSE_HEIGHT = 24;
|
||||
private static final int SPACE_HEIGHT = 19;
|
||||
|
||||
public Keystrokes(KeystrokesInterface minecraft) {
|
||||
super(new ModuleDetails("Keystrokes", "keystrokes")
|
||||
.description("Displays movement keystrokes")
|
||||
.version("v0.2.0")
|
||||
.tags("Utility"),
|
||||
|
||||
enabled.named("Enabled"),
|
||||
showMouse.named("Show mouse clicks"),
|
||||
showSpace.named("Show space"),
|
||||
dimensions.prop(),
|
||||
clickFg.named("Clicked fg"),
|
||||
clickBg.named("Clicked bg"));
|
||||
|
||||
this.minecraft = minecraft;
|
||||
|
||||
dimensions.renderBackground = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
w = minecraft.isForwardPressed();
|
||||
a = minecraft.isLeftPressed();
|
||||
s = minecraft.isBackPressed();
|
||||
d = minecraft.isRightPressed();
|
||||
lmb = minecraft.isAttackPressed();
|
||||
rmb = minecraft.isUsePressed();
|
||||
space = minecraft.isJumpPressed();
|
||||
|
||||
updateHeight();
|
||||
}
|
||||
|
||||
private void updateHeight() {
|
||||
int height = KEY_SIZE * 2 + KEY_SPACING;
|
||||
|
||||
if (showSpace.value)
|
||||
height += SPACE_HEIGHT + KEY_SPACING;
|
||||
|
||||
if (showMouse.value)
|
||||
height += MOUSE_HEIGHT + KEY_SPACING;
|
||||
|
||||
dimensions.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
render(scope, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
render(scope, true);
|
||||
}
|
||||
|
||||
private void render(RenderScope scope, boolean live) {
|
||||
|
||||
int yOffset = 0;
|
||||
|
||||
// --- W ---
|
||||
renderKey(scope, live && w, 'W', KEY_SIZE + KEY_SPACING, yOffset);
|
||||
|
||||
// --- A S D ---
|
||||
yOffset += KEY_SIZE + KEY_SPACING;
|
||||
|
||||
renderKey(scope, live && a, 'A', 0, yOffset);
|
||||
renderKey(scope, live && s, 'S', KEY_SIZE + KEY_SPACING, yOffset);
|
||||
renderKey(scope, live && d, 'D', (KEY_SIZE + KEY_SPACING) * 2, yOffset);
|
||||
|
||||
yOffset += KEY_SIZE + KEY_SPACING;
|
||||
|
||||
// --- SPACE ---
|
||||
if (showSpace.value) {
|
||||
renderKeySpace(scope, live && space, 0, yOffset);
|
||||
yOffset += SPACE_HEIGHT + KEY_SPACING;
|
||||
}
|
||||
|
||||
// --- MOUSE ---
|
||||
if (showMouse.value) {
|
||||
renderKeyMouse(scope, live && lmb, "LMB", 0, yOffset);
|
||||
renderKeyMouse(scope, live && rmb, "RMB", MOUSE_WIDTH + KEY_SPACING, yOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderKey(RenderScope scope, boolean pressed, char c, int x, int y) {
|
||||
int bg = pressed ? clickBg.value : dimensions.bgColor.value;
|
||||
int fg = pressed ? clickFg.value : dimensions.fgColor.value;
|
||||
|
||||
scope.drawRoundedRectangle(x, y, KEY_SIZE, KEY_SIZE, dimensions.radius.value, bg);
|
||||
scope.drawText(0.6f, String.valueOf(c), x + 9, y + 7, dimensions.font.value, fg);
|
||||
}
|
||||
|
||||
private void renderKeyMouse(RenderScope scope, boolean pressed, String text, int x, int y) {
|
||||
int bg = pressed ? clickBg.value : dimensions.bgColor.value;
|
||||
int fg = pressed ? clickFg.value : dimensions.fgColor.value;
|
||||
|
||||
scope.drawRoundedRectangle(x, y, MOUSE_WIDTH, MOUSE_HEIGHT, dimensions.radius.value, bg);
|
||||
scope.drawText(0.6f, text, x + 9, y + 7, dimensions.font.value, fg);
|
||||
}
|
||||
|
||||
private void renderKeySpace(RenderScope scope, boolean pressed, int x, int y) {
|
||||
int bg = pressed ? clickBg.value : dimensions.bgColor.value;
|
||||
int fg = pressed ? clickFg.value : dimensions.fgColor.value;
|
||||
|
||||
scope.drawRoundedRectangle(x, y, dimensions.width, SPACE_HEIGHT, dimensions.radius.value, bg);
|
||||
|
||||
int lineY = y + SPACE_HEIGHT / 2;
|
||||
scope.drawRect(x + (dimensions.width - 30) / 2, lineY, 30, 1, fg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.modules.interfaces.NametagsInterface;
|
||||
|
||||
public class Nametags extends Module {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Boolean> healthDisplay = Property.bool(false);
|
||||
private static Property<Boolean> players = Property.bool(true);
|
||||
private static Property<Boolean> hostile = Property.bool(false);
|
||||
private static Property<Boolean> passive = Property.bool(false);
|
||||
private static Property<Boolean> heartEmoji = Property.bool(true);
|
||||
private static Property<Boolean> obfuscate = Property.bool(false);
|
||||
private static Property<Integer> unit = Property.select(0, "Health", "Hearts");
|
||||
private static Property<Integer> format = Property.select(0, "Value", "Value / Total", "%");
|
||||
private static Property<Integer> nameColor = Property.select(15,
|
||||
"Black","Dark Blue","Dark Green","Dark Aqua","Dark Red","Dark Purple","Gold","Gray",
|
||||
"Dark Gray","Blue","Green","Aqua","Red","Light Purple","Yellow","White");
|
||||
private static Property<Integer> healthColor = Property.select(12,
|
||||
"Black","Dark Blue","Dark Green","Dark Aqua","Dark Red","Dark Purple","Gold","Gray",
|
||||
"Dark Gray","Blue","Green","Aqua","Red","Light Purple","Yellow","White");
|
||||
|
||||
private static final String[] COLOR_CODES = {
|
||||
"§0", "§1", "§2", "§3", "§4", "§5", "§6", "§7",
|
||||
"§8", "§9", "§a", "§b", "§c", "§d", "§e", "§f"
|
||||
};
|
||||
|
||||
public Nametags(NametagsInterface minecraft) {
|
||||
super(new ModuleDetails("Nametags", "nametags")
|
||||
.description("Allows you to modify entity nametags")
|
||||
.tags("Camera", "Utility")
|
||||
.version("0.1.0"),
|
||||
enabled.named("Enabled"),
|
||||
healthDisplay.named("Display health"),
|
||||
players.named("Players"),
|
||||
hostile.named("Hostile"),
|
||||
passive.named("Passive"),
|
||||
heartEmoji.named("Heart emoji"),
|
||||
obfuscate.named("Obfuscate enemy names"),
|
||||
unit.named("Unit"),
|
||||
format.named("Format"),
|
||||
nameColor.named("Name color"),
|
||||
healthColor.named("Health color"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
// Currently unused
|
||||
}
|
||||
|
||||
public static String getHealthString(NametagsInterface.EntityState state, float health, float maxHealth) {
|
||||
String ret = "";
|
||||
|
||||
switch (format.value) {
|
||||
case 0: // value
|
||||
ret = String.format("%.1f", health / (unit.value + 1));
|
||||
break;
|
||||
|
||||
case 1: // value / total
|
||||
ret = String.format("%.1f", health / (unit.value + 1)) + " / "
|
||||
+ String.format("%.1f", maxHealth / (unit.value + 1));
|
||||
break;
|
||||
|
||||
case 2: // %
|
||||
ret = String.format("%.0f%%", (health / maxHealth) * 100);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static String getNametagString(NametagsInterface.EntityState state) {
|
||||
if (state.getCustomName() == null)
|
||||
return null;
|
||||
|
||||
if (!healthDisplay.value)
|
||||
return state.getCustomName(); // name only
|
||||
|
||||
float health = state.getHealth();
|
||||
float maxHealth = state.getMaxHealth();
|
||||
NametagsInterface.EntityType type = state.getEntityType();
|
||||
|
||||
if (type == NametagsInterface.EntityType.PASSIVE && !passive.value)
|
||||
return null;
|
||||
if (type == NametagsInterface.EntityType.HOSTILE && !hostile.value)
|
||||
return null;
|
||||
if (type == NametagsInterface.EntityType.PLAYER && !players.value)
|
||||
return null;
|
||||
if (type == NametagsInterface.EntityType.OTHER)
|
||||
return null;
|
||||
|
||||
if (health < 0f || maxHealth < 0f || health > maxHealth)
|
||||
return null;
|
||||
|
||||
String hpColor = COLOR_CODES[healthColor.value];
|
||||
String color = COLOR_CODES[nameColor.value];
|
||||
String heart = heartEmoji.value ? " ❤" : "";
|
||||
String obf = obfuscate.value ? "§k" : "";
|
||||
String reset = "§r";
|
||||
|
||||
return color + obf + state.getCustomName() + reset + " " + hpColor
|
||||
+ getHealthString(state, health, maxHealth) + heart;
|
||||
}
|
||||
|
||||
public static boolean shouldReplaceName() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class NoFog extends Module {
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Boolean> liquids = Property.bool(false);
|
||||
|
||||
public NoFog() {
|
||||
super(
|
||||
new ModuleDetails("No Fog", "nofog")
|
||||
.description("Stops fog from rendering")
|
||||
.tags("Camera")
|
||||
.version("v0.1.0"),
|
||||
enabled.named("Enabled"),
|
||||
liquids.named("See through liquids"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
// static for the mixin
|
||||
public static boolean isActive() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
public static boolean liquids() {
|
||||
return liquids.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.modules.interfaces.PingInterface;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Ping extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight());
|
||||
|
||||
private final PingInterface pingProvider;
|
||||
|
||||
public Ping(PingInterface pingProvider) {
|
||||
super(new ModuleDetails("Ping Display", "ping")
|
||||
.description("Displays ping")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
dimensions.prop());
|
||||
|
||||
this.pingProvider = pingProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
int ping = pingProvider.getPing();
|
||||
String text = ping + " ms";
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
String text = "10 ms";
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.modules.interfaces.SpeedometerInterface;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Speedometer extends Module implements HudMod {
|
||||
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Integer> axis = Property.select(1, "Absolute", "X axis", "Y axis");
|
||||
private static Property<Integer> unitText = Property.select(0, "None", "Blocks/s", "blocks/s", "b/s");
|
||||
private static Property<Boolean> speedText = Property.bool(true);
|
||||
private static ModDimensions dimensions = new ModDimensions(40, 18);
|
||||
|
||||
private final SpeedometerInterface provider;
|
||||
private double speed = 0.;
|
||||
|
||||
public Speedometer(SpeedometerInterface provider) {
|
||||
super(new ModuleDetails("Speedometer", "speed")
|
||||
.description("Displays your current speed")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
axis.named("Speed type"),
|
||||
unitText.named("Unit text"),
|
||||
speedText.named("Show speed text"),
|
||||
dimensions.prop());
|
||||
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderSpeed(2.71, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
SpeedometerInterface.Velocity velocity = provider.getVelocity();
|
||||
boolean onGround = provider.isOnGround();
|
||||
|
||||
double y = onGround ? 0.0 : velocity.y;
|
||||
|
||||
switch (axis.value) {
|
||||
case 0: // Absolute
|
||||
speed = Math.sqrt(Math.pow(velocity.x, 2) + Math.pow(y, 2) + Math.pow(velocity.z, 2));
|
||||
break;
|
||||
case 1: // X axis
|
||||
speed = Math.sqrt(Math.pow(velocity.x, 2) + Math.pow(velocity.z, 2));
|
||||
break;
|
||||
case 2: // Y axis
|
||||
speed = Math.abs(y);
|
||||
break;
|
||||
}
|
||||
|
||||
renderSpeed(speed * 20, scope); // blocks/tick to blocks/s
|
||||
}
|
||||
|
||||
public void renderSpeed(double speed, RenderScope scope) {
|
||||
String text = String.format("%.2f ", speed);
|
||||
|
||||
switch (unitText.value) {
|
||||
case 1 -> text += "Blocks/s";
|
||||
case 2 -> text += "blocks/s";
|
||||
case 3 -> text += "b/s";
|
||||
}
|
||||
|
||||
if (speedText.value) {
|
||||
text = "Speed: " + text;
|
||||
}
|
||||
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
dimensions.height = 18 * text.split("\n").length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.modules.interfaces.StatusEffectsInterface;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class StatusEffects extends Module implements HudMod {
|
||||
|
||||
public static Property<Boolean> enabled = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(60, 0);
|
||||
|
||||
private final StatusEffectsInterface provider;
|
||||
|
||||
public StatusEffects(StatusEffectsInterface provider) {
|
||||
super(new ModuleDetails("Status effects", "effect")
|
||||
.description("Displays status effects")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
dimensions.prop());
|
||||
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
private void renderEffects(RenderScope scope, List<StatusEffectsInterface.Effect> effects) {
|
||||
int row = 0;
|
||||
|
||||
for (StatusEffectsInterface.Effect effect : effects) {
|
||||
if (!effect.shouldShowIcon()) continue;
|
||||
|
||||
scope.drawSpriteStretched(effect.getIcon(), 0, 18 * row, 16, 16);
|
||||
scope.drawText(0.5f, getDurationAsString(effect), 18, 18 * row + 3, dimensions.font.value, -1);
|
||||
row++;
|
||||
}
|
||||
|
||||
dimensions.height = 18 * row;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
renderEffects(scope, provider.getActiveEffects());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderEffects(scope, provider.getDummyEffects());
|
||||
}
|
||||
|
||||
private String getDurationAsString(StatusEffectsInterface.Effect effect) {
|
||||
if (effect.isInfinite()) {
|
||||
return effect.getInfiniteText();
|
||||
}
|
||||
|
||||
int totalSeconds = effect.getDurationSeconds();
|
||||
if (totalSeconds >= 3600) {
|
||||
return totalSeconds / 3600 + "h";
|
||||
} else if (totalSeconds >= 60) {
|
||||
int minutes = totalSeconds / 60;
|
||||
int seconds = totalSeconds % 60;
|
||||
return String.format("%d:%02d", minutes, seconds);
|
||||
} else {
|
||||
return totalSeconds + "s";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.HudMod;
|
||||
import org.saturnclient.modules.ModDimensions;
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Tps extends Module implements HudMod {
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static ModDimensions dimensions = new ModDimensions(60, Fonts.getHeight());
|
||||
|
||||
private static long lastWorldAge = -1;
|
||||
private static long lastRealTime = -1;
|
||||
private static double currentTps = 20.0;
|
||||
|
||||
private static final int SAMPLE_COUNT = 2;
|
||||
private static final double[] samples = new double[SAMPLE_COUNT];
|
||||
static {
|
||||
java.util.Arrays.fill(samples, 20.0);
|
||||
}
|
||||
private static int sampleIndex = 0;
|
||||
private static int samplesFilled = 0;
|
||||
|
||||
public Tps() {
|
||||
super(new ModuleDetails("TPS Display", "tps")
|
||||
.description("Displays the TPS")
|
||||
.version("v0.1.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
dimensions.prop());
|
||||
}
|
||||
|
||||
public static void onTimePacket(long worldAge) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (lastWorldAge != -1 && lastRealTime != -1) {
|
||||
long tickDelta = worldAge - lastWorldAge;
|
||||
long timeDelta = now - lastRealTime;
|
||||
|
||||
if (timeDelta > 0 && tickDelta > 0) {
|
||||
double sample = (tickDelta / (double) timeDelta) * 1000.0;
|
||||
sample = Math.min(sample, 20.0);
|
||||
|
||||
samples[sampleIndex % SAMPLE_COUNT] = sample;
|
||||
sampleIndex++;
|
||||
samplesFilled = Math.min(samplesFilled + 1, SAMPLE_COUNT);
|
||||
|
||||
double sum = 0;
|
||||
for (int i = 0; i < samplesFilled; i++)
|
||||
sum += samples[i];
|
||||
currentTps = sum / samplesFilled;
|
||||
}
|
||||
}
|
||||
|
||||
lastWorldAge = worldAge;
|
||||
lastRealTime = now;
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
lastWorldAge = -1;
|
||||
lastRealTime = -1;
|
||||
currentTps = 20.0;
|
||||
sampleIndex = 0;
|
||||
samplesFilled = SAMPLE_COUNT;
|
||||
for (int i = 0; i < SAMPLE_COUNT; i++)
|
||||
samples[i] = 20.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
String text = String.format("%.1f TPS", currentTps);
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
String text = "20.0 TPS";
|
||||
scope.drawText(text, 0, 0, dimensions.font.value, dimensions.fgColor.value);
|
||||
dimensions.width = Fonts.getWidth(text, dimensions.font.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModDimensions getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.saturnclient.modules.mods;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.modules.ModuleDetails;
|
||||
import org.saturnclient.config.manager.Key;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
|
||||
public class Zoom extends Module {
|
||||
private static Property<Boolean> enabled = Property.bool(false);
|
||||
private static Property<Boolean> toggle = Property.bool(false);
|
||||
public static Property<Integer> zoomKey = Property.keybinding(Key.GLFW_KEY_C);
|
||||
public static Property<Float> zoomLevel = Property.floatProp(3.0f);
|
||||
|
||||
public static boolean isZooming = false;
|
||||
|
||||
public Zoom() {
|
||||
super(
|
||||
new ModuleDetails("Zoom", "zoom")
|
||||
.description("Allows you to zoom in for a closer view")
|
||||
.tags("Camera", "Utility")
|
||||
.version("0.1.0"),
|
||||
enabled.named("Enabled"),
|
||||
toggle.named("Toggle zoom"),
|
||||
zoomKey.named("Zoom Keybinding"),
|
||||
zoomLevel.named("Zoom Level"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (toggle.value) {
|
||||
if (zoomKey.wasKeyPressed()) {
|
||||
isZooming = !isZooming;
|
||||
}
|
||||
} else {
|
||||
isZooming = zoomKey.isKeyPressed();
|
||||
}
|
||||
}
|
||||
|
||||
public static float getZoomLevel() {
|
||||
return zoomLevel.value;
|
||||
}
|
||||
|
||||
public static boolean shouldZoom() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
if (!e) {
|
||||
isZooming = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.saturnclient.ui;
|
||||
|
||||
import org.saturnclient.ui.anim.Animation;
|
||||
|
||||
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 Integer duration = null; // Element duration, will fade out if not null
|
||||
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
}
|
||||
|
||||
public void click(int mouseX, int mouseY) {
|
||||
}
|
||||
|
||||
public void scroll(int mouseX, int mouseY, double horizontalAmount, double verticalAmount) {
|
||||
}
|
||||
|
||||
public void keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
}
|
||||
|
||||
public void charTyped(char typedChar) {
|
||||
}
|
||||
|
||||
public void mouseClicked(double mouseX, double mouseY, int button) {
|
||||
}
|
||||
|
||||
public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
}
|
||||
|
||||
public void mouseReleased(double mouseX, double mouseY, int button) {
|
||||
}
|
||||
|
||||
public void playAnimationFrame(long elapsed) {
|
||||
if (this.animation != null && elapsed >= this.animation.delay) {
|
||||
this.animation.tick(this.animation.curve
|
||||
.apply(Math.min(1.0, (double) (elapsed - this.animation.delay) / this.animation.duration)), this);
|
||||
}
|
||||
}
|
||||
|
||||
public Element dimensions(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Element position(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Element centerHorizontal(int w, int h, int offsetX, int offsetY) {
|
||||
this.x = (w - (int) (width * scale)) / 2 + offsetX;
|
||||
this.y = offsetY;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Element center(int w, int h) {
|
||||
this.centerOffset(w, h, 0, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public 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 Element animation(Animation animation) {
|
||||
this.animation = animation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Element scale(float scale) {
|
||||
this.scale = scale;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.saturnclient.ui;
|
||||
|
||||
public class ElementContext {
|
||||
public int mouseX, mouseY;
|
||||
public int elementWidth, elementHeight;
|
||||
public float elementScale;
|
||||
public long elapsed;
|
||||
|
||||
public ElementContext(long elapsed, int mouseX, int mouseY, Element e) {
|
||||
this.mouseX = mouseX - e.x;
|
||||
this.mouseY = mouseY - e.y;
|
||||
this.elementWidth = e.width;
|
||||
this.elementHeight = e.height;
|
||||
this.elementScale = e.scale;
|
||||
this.elapsed = elapsed;
|
||||
}
|
||||
|
||||
public boolean isHovering() {
|
||||
return Utils.isHovering(mouseX, mouseY, elementWidth, elementHeight, elementScale);
|
||||
}
|
||||
|
||||
public boolean isHovering(int x, int y, int width, int height) {
|
||||
return Utils.isHovering(mouseX - x, mouseY - y, width, height, elementScale);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.saturnclient.ui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ElementRenderer {
|
||||
public static ElementRenderer INSTANCE;
|
||||
|
||||
public abstract void draw(List<Element> elements, Element element);
|
||||
|
||||
public abstract void render(List<Element> elements, long elapsed, RenderScope renderScope, int mouseX, int mouseY);
|
||||
|
||||
public abstract void mouseClicked(List<Element> elements, double mouseX, double mouseY, int button);
|
||||
|
||||
public abstract void mouseScrolled(
|
||||
List<Element> elements,
|
||||
double mouseX,
|
||||
double mouseY,
|
||||
double horizontalAmount,
|
||||
double verticalAmount);
|
||||
|
||||
public abstract void keyPressed(List<Element> elements, int keyCode, int scanCode, int modifiers);
|
||||
|
||||
public abstract void mouseDragged(List<Element> elements, double mouseX, double mouseY, int button, double deltaX,
|
||||
double deltaY);
|
||||
|
||||
public abstract void mouseReleased(List<Element> elements, double mouseX, double mouseY, int button);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.saturnclient.ui;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnItemStack;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnSprite;
|
||||
import org.saturnclient.common.minecraft.render.IMatrixStack;
|
||||
|
||||
public interface RenderScope {
|
||||
public IMatrixStack getMatrixStack();
|
||||
|
||||
public void setOpacity(float alpha);
|
||||
|
||||
public int getColor(int color);
|
||||
|
||||
public void drawRect(int x, int y, int width, int height, int color);
|
||||
|
||||
public void drawText(String text, int x, int y, int font, int color);
|
||||
|
||||
public void drawText(float scale, String text, int x, int y, int font, int color);
|
||||
|
||||
public void drawRoundedRectangle(int x, int y, int width, int height, int radius, int color);
|
||||
|
||||
public int getScaledWindowWidth();
|
||||
|
||||
public int getScaledWindowHeight();
|
||||
|
||||
/* Saturn common sprites */
|
||||
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height, int color);
|
||||
|
||||
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height);
|
||||
|
||||
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height,
|
||||
int regionWith,
|
||||
int regionHeight, int textureWidth, int textureHeight);
|
||||
|
||||
public void drawTexture(SaturnIdentifier sprite, int x, int y, float u, float v, int width, int height,
|
||||
int regionWidth,
|
||||
int regionHeight, int textureWidth, int textureHeight, int color);
|
||||
|
||||
public void enableScissor(int x1, int y1, int x2, int y2);
|
||||
|
||||
public void disableScissor();
|
||||
|
||||
public boolean scissorContains(int x, int y);
|
||||
|
||||
public void draw();
|
||||
|
||||
public void drawItem(SaturnItemStack item, int x, int y);
|
||||
|
||||
public void drawItem(SaturnItemStack stack, int x, int y, int seed);
|
||||
|
||||
public void drawItem(SaturnItemStack stack, int x, int y, int seed, int z);
|
||||
|
||||
public void drawItemWithoutEntity(SaturnItemStack stack, int x, int y);
|
||||
|
||||
public void drawItemWithoutEntity(SaturnItemStack stack, int x, int y, int seed);
|
||||
|
||||
public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height);
|
||||
|
||||
public void drawSpriteStretched(SaturnSprite sprite, int x, int y, int width, int height, int color);
|
||||
|
||||
public void fill(int x1, int y1, int x2, int y2, int color);
|
||||
|
||||
public void fill(int x1, int y1, int x2, int y2, int z, int color);
|
||||
|
||||
public void drawBorder(int x, int y, int width, int height, int color);
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.saturnclient.ui;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class SaturnScreen {
|
||||
public static interface ScreenProvider {
|
||||
public void close();
|
||||
|
||||
public int getWidth();
|
||||
|
||||
public int getHeight();
|
||||
}
|
||||
|
||||
// General
|
||||
public int width;
|
||||
public int height;
|
||||
public String title;
|
||||
|
||||
// Saturn Screen
|
||||
public List<Element> elements = new ArrayList<>();
|
||||
public float backgroundOpacity = 1.0f;
|
||||
protected Instant start = null;
|
||||
public int backgroundBlur = 10;
|
||||
|
||||
// Provider
|
||||
public ScreenProvider provider;
|
||||
|
||||
public SaturnScreen(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
elements.clear();
|
||||
width = provider.getWidth();
|
||||
height = provider.getHeight();
|
||||
ui(); // abstraction to render the saturn ui and also render extra stuff here
|
||||
}
|
||||
|
||||
public abstract void ui();
|
||||
|
||||
public void draw(Element element) {
|
||||
ElementRenderer.INSTANCE.draw(elements, element);
|
||||
}
|
||||
|
||||
// --------------
|
||||
// Rendering
|
||||
// --------------
|
||||
|
||||
public void render(RenderScope renderScope, int mouseX, int mouseY, float delta, long elapsed) {
|
||||
renderScope.getMatrixStack().push();
|
||||
|
||||
renderScope.getMatrixStack().scale(0.5f, 0.5f, 0.5f);
|
||||
|
||||
ElementRenderer.INSTANCE.render(new ArrayList<>(elements), elapsed, renderScope, mouseX, mouseY);
|
||||
|
||||
renderScope.getMatrixStack().pop();
|
||||
}
|
||||
|
||||
// --------------
|
||||
// Events
|
||||
// --------------
|
||||
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
mouseX *= 2;
|
||||
mouseY *= 2;
|
||||
|
||||
ElementRenderer.INSTANCE.mouseClicked(elements, mouseX, mouseY, button);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
mouseX *= 2;
|
||||
mouseY *= 2;
|
||||
|
||||
ElementRenderer.INSTANCE.mouseDragged(elements, mouseX, mouseY, button, deltaX, deltaY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
mouseX *= 2;
|
||||
mouseY *= 2;
|
||||
|
||||
ElementRenderer.INSTANCE.mouseReleased(elements, mouseX, mouseY, button);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean mouseScrolled(
|
||||
double mouseX,
|
||||
double mouseY,
|
||||
double horizontalAmount,
|
||||
double verticalAmount) {
|
||||
mouseX *= 2;
|
||||
mouseY *= 2;
|
||||
|
||||
ElementRenderer.INSTANCE.mouseScrolled(elements, mouseX, mouseY, horizontalAmount, verticalAmount);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resize(int width, int height) {
|
||||
init();
|
||||
}
|
||||
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
ElementRenderer.INSTANCE.keyPressed(elements, keyCode, scanCode, modifiers);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldPause() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onClose() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.saturnclient.ui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.saturnclient.config.manager.Key;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static char getCharFromKey(int keyCode, int modifiers) {
|
||||
boolean shift = (modifiers & Key.GLFW_MOD_SHIFT) != 0;
|
||||
|
||||
// A-Z
|
||||
if (keyCode >= Key.GLFW_KEY_A && keyCode <= Key.GLFW_KEY_Z) {
|
||||
return (char) (shift
|
||||
? 'A' + (keyCode - Key.GLFW_KEY_A)
|
||||
: 'a' + (keyCode - Key.GLFW_KEY_A));
|
||||
}
|
||||
|
||||
// 0-9
|
||||
if (keyCode >= Key.GLFW_KEY_0 && keyCode <= Key.GLFW_KEY_9) {
|
||||
return shift
|
||||
? ")!@#$%^&*(".charAt(keyCode - Key.GLFW_KEY_0)
|
||||
: (char) ('0' + (keyCode - Key.GLFW_KEY_0));
|
||||
}
|
||||
|
||||
// Special characters
|
||||
return switch (keyCode) {
|
||||
case Key.GLFW_KEY_SPACE -> ' ';
|
||||
case Key.GLFW_KEY_PERIOD -> shift ? '>' : '.';
|
||||
case Key.GLFW_KEY_COMMA -> shift ? '<' : ',';
|
||||
case Key.GLFW_KEY_MINUS -> shift ? '_' : '-';
|
||||
case Key.GLFW_KEY_EQUAL -> shift ? '+' : '=';
|
||||
case Key.GLFW_KEY_SEMICOLON -> shift ? ':' : ';';
|
||||
case Key.GLFW_KEY_APOSTROPHE -> shift ? '"' : '\'';
|
||||
case Key.GLFW_KEY_SLASH -> shift ? '?' : '/';
|
||||
case Key.GLFW_KEY_BACKSLASH -> shift ? '|' : '\\';
|
||||
case Key.GLFW_KEY_LEFT_BRACKET -> shift ? '{' : '[';
|
||||
case Key.GLFW_KEY_RIGHT_BRACKET -> shift ? '}' : ']';
|
||||
case Key.GLFW_KEY_GRAVE_ACCENT -> shift ? '~' : '`';
|
||||
default -> '\0';
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> T getOrNull(List<T> list, int index) {
|
||||
return (index >= 0 && index < list.size()) ? list.get(index) : null;
|
||||
}
|
||||
|
||||
// public static void notify(NotificationKind kind, String title, String toast) {
|
||||
// if (SaturnClient.client.currentScreen instanceof SaturnScreen) {
|
||||
// ((SaturnScreen) SaturnClient.client.currentScreen)
|
||||
// .draw(new Notification(SaturnClient.client.currentScreen.width,
|
||||
// SaturnClient.client.currentScreen.height, kind,
|
||||
// title, toast));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.saturnclient.ui.anim;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.ui.Element;
|
||||
|
||||
public abstract class Animation {
|
||||
public int duration;
|
||||
public int delay = 0;
|
||||
public Function<Double, Double> curve = Curve::easeInOutCubic;
|
||||
|
||||
Animation(AnimationConfig config) {
|
||||
this.duration = config.duration.value;
|
||||
switch (config.curve.value) {
|
||||
case 0:
|
||||
this.curve = Curve::easeInOutCubic;
|
||||
break;
|
||||
case 1:
|
||||
this.curve = Curve::easeOutCubic;
|
||||
break;
|
||||
case 2:
|
||||
this.curve = Curve::easeInOutBack;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Animation(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public abstract void tick(double progress, Element element);
|
||||
|
||||
public abstract void init(Element element);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.saturnclient.ui.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 easeInOutBack(double x) {
|
||||
double c1 = 2.5;
|
||||
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,27 @@
|
||||
package org.saturnclient.ui.anim;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.ui.Element;
|
||||
|
||||
public class Fade extends Animation {
|
||||
float targetOpacity;
|
||||
|
||||
public Fade(int duration) {
|
||||
super(duration);
|
||||
}
|
||||
|
||||
public Fade(AnimationConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(double progress, Element element) {
|
||||
element.opacity = Math.max(0.1f, targetOpacity * (float) progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Element element) {
|
||||
targetOpacity = element.opacity;
|
||||
element.opacity = 0.1f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.saturnclient.ui.anim;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.ui.Element;
|
||||
|
||||
public class FadeOut extends Animation {
|
||||
float targetOpacity;
|
||||
|
||||
public FadeOut(int duration) {
|
||||
super(duration);
|
||||
}
|
||||
|
||||
public FadeOut(AnimationConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(double progress, Element element) {
|
||||
element.opacity = targetOpacity - (float) progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Element element) {
|
||||
targetOpacity = element.opacity;
|
||||
// element.opacity = 1.0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.saturnclient.ui.anim;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.ui.Element;
|
||||
|
||||
public class SlideFade extends Animation {
|
||||
public Fade fade;
|
||||
public SlideY slideY;
|
||||
|
||||
public SlideFade(int duration, int offset) {
|
||||
super(duration);
|
||||
this.fade = new Fade(duration);
|
||||
this.slideY = new SlideY(duration, offset);
|
||||
}
|
||||
|
||||
public SlideFade(AnimationConfig config, int offset) {
|
||||
super(config);
|
||||
this.fade = new Fade(duration);
|
||||
this.slideY = new SlideY(duration, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(double progress, Element element) {
|
||||
fade.delay = this.delay;
|
||||
fade.duration = this.duration;
|
||||
|
||||
slideY.delay = this.delay;
|
||||
slideY.duration = this.duration;
|
||||
|
||||
fade.tick(progress, element);
|
||||
slideY.tick(progress, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Element element) {
|
||||
fade.init(element);
|
||||
slideY.init(element);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.saturnclient.ui.anim;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.ui.Element;
|
||||
|
||||
public class SlideX extends Animation {
|
||||
int offset = 20;
|
||||
double startX;
|
||||
|
||||
public SlideX(AnimationConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
public SlideX(AnimationConfig config, int offset) {
|
||||
super(config);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public SlideX(int duration) {
|
||||
super(duration);
|
||||
}
|
||||
|
||||
public SlideX(int duration, int offset) {
|
||||
super(duration);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Element element) {
|
||||
startX = element.x - offset;
|
||||
element.x = (int) startX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(double progress, Element element) {
|
||||
double currentX = startX + offset * progress;
|
||||
element.x = (int) currentX;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.saturnclient.ui.anim;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.ui.Element;
|
||||
|
||||
public class SlideY extends Animation {
|
||||
int offset = 20;
|
||||
double startY;
|
||||
|
||||
public SlideY(AnimationConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
public SlideY(AnimationConfig config, int offset) {
|
||||
super(config);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public SlideY(int duration) {
|
||||
super(duration);
|
||||
}
|
||||
|
||||
public SlideY(int duration, int offset) {
|
||||
super(duration);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Element element) {
|
||||
startY = element.y - offset;
|
||||
element.y = (int) startY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(double progress, Element element) {
|
||||
double currentY = startY + offset * progress;
|
||||
element.y = (int) currentY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class CosmeticPreview extends Element {
|
||||
static int padding = 14;
|
||||
|
||||
SaturnIdentifier sprite;
|
||||
private Runnable onClick;
|
||||
private boolean isSelected;
|
||||
|
||||
public CosmeticPreview(boolean isSelected, SaturnIdentifier sprite, Runnable onClick) {
|
||||
this.sprite = sprite;
|
||||
this.onClick = onClick;
|
||||
this.isSelected = isSelected;
|
||||
|
||||
this.width = 50;
|
||||
this.height = 111;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value,
|
||||
isSelected ? Theme.ACCENT.value : Theme.PRIMARY.value);
|
||||
|
||||
int texWidth = width - padding;
|
||||
int texHeight = height - padding;
|
||||
|
||||
renderScope.drawTexture(sprite, padding / 2, padding / 2, 0, 0, texWidth, texHeight,
|
||||
Theme.FOREGROUND.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
if (onClick != null) {
|
||||
onClick.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.ElementRenderer;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.Utils;
|
||||
|
||||
public class ElementRendererImpl extends ElementRenderer {
|
||||
public void draw(List<Element> elements, Element element) {
|
||||
synchronized (elements) {
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
if (element.animation != null) {
|
||||
element.animation.init(element);
|
||||
}
|
||||
}
|
||||
|
||||
public void render(List<Element> elements, long elapsed, RenderScope renderScope, int mouseX, int mouseY) {
|
||||
for (Element element : elements) {
|
||||
element.playAnimationFrame(elapsed);
|
||||
|
||||
renderScope.getMatrixStack().push();
|
||||
renderScope.setOpacity(element.opacity);
|
||||
renderScope.getMatrixStack().translate(element.x, element.y, 0);
|
||||
renderScope.getMatrixStack().scale(element.scale, element.scale, 1.0f);
|
||||
element.render(renderScope, new ElementContext(elapsed, mouseX, mouseY, element));
|
||||
renderScope.getMatrixStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseClicked(List<Element> elements, double mouseX, double mouseY, int button) {
|
||||
if (button == 0) {
|
||||
for (Element element : new ArrayList<>(elements)) {
|
||||
element.focused = false;
|
||||
|
||||
int adjustedMouseX = (int) mouseX - element.x;
|
||||
int adjustedMouseY = (int) mouseY - element.y;
|
||||
|
||||
element.mouseClicked(adjustedMouseX * element.scale, adjustedMouseY * element.scale, button);
|
||||
|
||||
if (element.opacity > 0 && Utils.isHovering(adjustedMouseX, adjustedMouseY, element.width,
|
||||
element.height, element.scale)) {
|
||||
element.focused = true;
|
||||
element.click((int) (adjustedMouseX * element.scale), (int) (adjustedMouseY * element.scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseScrolled(
|
||||
List<Element> elements,
|
||||
double mouseX,
|
||||
double mouseY,
|
||||
double horizontalAmount,
|
||||
double verticalAmount) {
|
||||
for (Element element : new ArrayList<>(elements)) {
|
||||
if (Utils.isHovering((int) mouseX - element.x, (int) mouseY - element.y, element.width, element.height,
|
||||
element.scale)) {
|
||||
element.scroll(
|
||||
(int) mouseX - element.x,
|
||||
(int) mouseY - element.y,
|
||||
horizontalAmount,
|
||||
verticalAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void keyPressed(List<Element> elements, int keyCode, int scanCode, int modifiers) {
|
||||
for (Element element : new ArrayList<>(elements)) {
|
||||
if (element.focused && element.opacity > 0) {
|
||||
element.keyPressed(keyCode, scanCode, modifiers);
|
||||
|
||||
char typedChar = Utils.getCharFromKey(keyCode, modifiers);
|
||||
if (typedChar != '\0') {
|
||||
element.charTyped(typedChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseDragged(List<Element> elements, double mouseX, double mouseY, int button, double deltaX,
|
||||
double deltaY) {
|
||||
for (Element element : new ArrayList<>(elements)) {
|
||||
element.mouseDragged(mouseX - element.x, mouseY - element.y, button, deltaX, deltaY);
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseReleased(List<Element> elements, double mouseX, double mouseY, int button) {
|
||||
for (Element element : new ArrayList<>(elements)) {
|
||||
element.mouseReleased(mouseX - element.x, mouseY - element.y, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import org.saturnclient.modules.Module;
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.Utils;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
import org.saturnclient.ui.screens.ConfigEditor;
|
||||
|
||||
public class SaturnModule extends Element {
|
||||
|
||||
private final Module mod;
|
||||
|
||||
static int p = 10; // padding
|
||||
static int s = 14; // settings icon size
|
||||
static int expand = 5; // settings icon click area
|
||||
|
||||
public SaturnModule(Module mod) {
|
||||
this.mod = mod;
|
||||
this.width = 160;
|
||||
this.height = 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
boolean hovered = ctx.isHovering();
|
||||
boolean enabled = mod.isEnabled();
|
||||
|
||||
int iconX = width - s - p;
|
||||
int iconY = height - s - p;
|
||||
|
||||
boolean settingsHover = ctx.isHovering(
|
||||
getSettingsX(),
|
||||
getSettingsY(),
|
||||
getSettingsHitBox(),
|
||||
getSettingsHitBox());
|
||||
|
||||
// Resolve theme colors
|
||||
int bgColor = Theme.PRIMARY.value;
|
||||
int fgColor = hovered && !settingsHover ? Theme.ACCENT.value : Theme.PRIMARY_FG.value;
|
||||
|
||||
int iconBg = enabled ? Theme.ACCENT.value : Theme.PRIMARY.value;
|
||||
int iconFg = enabled ? Theme.ACCENT_FG.value : fgColor;
|
||||
|
||||
int settingsColor = settingsHover
|
||||
? Theme.ACCENT.value
|
||||
: Theme.withAlpha(160, fgColor);
|
||||
|
||||
int h = height - (p * 2);
|
||||
|
||||
// Main background
|
||||
renderScope.drawRoundedRectangle(
|
||||
0, 0,
|
||||
width, height,
|
||||
Theme.WIDGET_RADIUS.value,
|
||||
bgColor);
|
||||
|
||||
// Icon background
|
||||
renderScope.drawRoundedRectangle(
|
||||
p, p,
|
||||
h, h,
|
||||
Theme.WIDGET_RADIUS.value,
|
||||
iconBg);
|
||||
|
||||
// Icon
|
||||
renderScope.drawTexture(
|
||||
mod.getIconTexture(),
|
||||
p + (p / 2),
|
||||
p + (p / 2),
|
||||
0, 0,
|
||||
h - p,
|
||||
h - p,
|
||||
iconFg);
|
||||
|
||||
// Module name
|
||||
renderScope.drawText(
|
||||
0.6f,
|
||||
mod.getName(),
|
||||
p + h + 4,
|
||||
p + 1,
|
||||
Theme.FONT.value,
|
||||
fgColor);
|
||||
|
||||
// Version (right aligned)
|
||||
String version = mod.getVersion();
|
||||
int versionWidth = (int) (Fonts.getWidth(version, Theme.FONT.value) * 0.35f);
|
||||
|
||||
renderScope.drawText(
|
||||
0.35f,
|
||||
version,
|
||||
width - p - versionWidth,
|
||||
p + 1,
|
||||
Theme.FONT.value,
|
||||
fgColor);
|
||||
|
||||
// Tags
|
||||
int xt = p + h + 4;
|
||||
for (String tag : mod.getTags()) {
|
||||
int tagWidth = (int) (Fonts.getWidth(tag, Theme.FONT.value) * 0.4f);
|
||||
|
||||
renderScope.drawRoundedRectangle(
|
||||
xt,
|
||||
p + (h / 2),
|
||||
tagWidth + 6,
|
||||
12,
|
||||
5,
|
||||
Theme.ACCENT.value);
|
||||
|
||||
renderScope.drawText(
|
||||
0.4f,
|
||||
tag,
|
||||
xt + 2,
|
||||
p + (h / 2) + 3,
|
||||
Theme.FONT.value,
|
||||
Theme.ACCENT_FG.value);
|
||||
|
||||
xt += tagWidth + 9;
|
||||
}
|
||||
|
||||
// Settings icon
|
||||
renderScope.drawTexture(
|
||||
Textures.SETTINGS,
|
||||
iconX,
|
||||
iconY,
|
||||
0, 0,
|
||||
s, s,
|
||||
settingsColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
boolean settingsHover = Utils.isHovering(
|
||||
mouseX - getSettingsX(),
|
||||
mouseY - getSettingsY(),
|
||||
getSettingsHitBox(),
|
||||
getSettingsHitBox(),
|
||||
1.0f);
|
||||
|
||||
if (settingsHover) {
|
||||
MinecraftProvider.PROVIDER.setScreen(new ConfigEditor(mod.getConfig()));
|
||||
} else {
|
||||
mod.setEnabled(!mod.isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
private int getSettingsX() {
|
||||
return width - s - p - expand;
|
||||
}
|
||||
|
||||
private int getSettingsY() {
|
||||
return height - s - p - expand;
|
||||
}
|
||||
|
||||
private int getSettingsHitBox() {
|
||||
return s + expand * 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.Config;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.Utils;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
import org.saturnclient.ui.screens.ConfigEditor;
|
||||
import org.saturnclient.ui.screens.ModMenu;
|
||||
import org.saturnclient.ui.screens.cosmetics.CloakMenu;
|
||||
import org.saturnclient.ui.screens.store.CloakStore;
|
||||
|
||||
public class Sidebar extends Element {
|
||||
public static class SidebarComponent {
|
||||
Runnable onClick;
|
||||
boolean end;
|
||||
SaturnIdentifier sprite;
|
||||
|
||||
public SidebarComponent(SaturnIdentifier sprite, Runnable onClick, boolean end) {
|
||||
this.onClick = onClick;
|
||||
this.end = end;
|
||||
this.sprite = sprite;
|
||||
}
|
||||
}
|
||||
|
||||
Runnable onClose;
|
||||
SidebarComponent[] components = {
|
||||
new Sidebar.SidebarComponent(Textures.MODS_TAB, () -> {
|
||||
MinecraftProvider.PROVIDER.setScreen(new ModMenu());
|
||||
}, false),
|
||||
new Sidebar.SidebarComponent(Textures.SETTINGS, () -> {
|
||||
MinecraftProvider.PROVIDER.setScreen(new ConfigEditor(Config.config));
|
||||
}, false),
|
||||
|
||||
new Sidebar.SidebarComponent(Textures.SHIRT, () -> {
|
||||
MinecraftProvider.PROVIDER.setScreen(new CloakMenu());
|
||||
}, false),
|
||||
|
||||
new Sidebar.SidebarComponent(Textures.CLOSE, () -> {
|
||||
onClose.run();
|
||||
}, true),
|
||||
|
||||
new Sidebar.SidebarComponent(Textures.STORE, () -> {
|
||||
MinecraftProvider.PROVIDER.setScreen(new CloakStore());
|
||||
}, true),
|
||||
};
|
||||
int active = 0;
|
||||
|
||||
public Sidebar(int active, Runnable onClose) {
|
||||
this.width = 30;
|
||||
this.height = 350;
|
||||
this.active = active;
|
||||
this.onClose = onClose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
int topRow = 0;
|
||||
int bottomRow = 0;
|
||||
|
||||
int gap = 5; // 5px gap between icons
|
||||
int padding = 10;
|
||||
int sp = 30 - padding + gap;
|
||||
int s = 30 - (padding * 2);
|
||||
int s2 = s + padding;
|
||||
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.BG_RADIUS.value, Theme.BACKGROUND.value);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (SidebarComponent component : components) {
|
||||
int y = component.end ? ((height - (sp * bottomRow)) - (s * 2)) : (padding + (sp * topRow));
|
||||
boolean selected = ctx.isHovering(0, y - (padding / 2), s2, s2) || active == i;
|
||||
|
||||
renderScope.drawRoundedRectangle(padding / 2, y - (padding / 2), s + padding,
|
||||
s + padding, Theme.WIDGET_RADIUS.value, Theme.getBg(selected));
|
||||
|
||||
renderScope.drawTexture(component.sprite, padding, y, 0, 0, s, s, Theme.getFg(selected));
|
||||
|
||||
if (component.end) {
|
||||
bottomRow += 1;
|
||||
} else {
|
||||
topRow += 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
int topRow = 0;
|
||||
int bottomRow = 0;
|
||||
|
||||
int gap = 5;
|
||||
int padding = 10;
|
||||
int sp = 30 - padding + gap;
|
||||
int s = 30 - (padding * 2);
|
||||
int s2 = s + padding;
|
||||
|
||||
for (SidebarComponent component : components) {
|
||||
int y = component.end ? ((height - (sp * bottomRow)) - (s * 2)) : (padding + (sp * topRow));
|
||||
boolean hovering = Utils.isHovering(mouseX - (padding / 2), mouseY - (y - (padding / 2)), s2, s2, scale);
|
||||
|
||||
if (hovering) {
|
||||
component.onClick.run();
|
||||
break;
|
||||
}
|
||||
|
||||
if (component.end) {
|
||||
bottomRow += 1;
|
||||
} else {
|
||||
topRow += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class SkinPreview extends Element {
|
||||
public static EntityDrawer DRAWER;
|
||||
private boolean negativeAngle = false;
|
||||
private float angle = 0.0f;
|
||||
|
||||
public SkinPreview(float angle, boolean negativeAngle) {
|
||||
this.angle = angle;
|
||||
this.negativeAngle = negativeAngle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
DRAWER.render(renderScope, negativeAngle, angle, scale, ctx);
|
||||
}
|
||||
|
||||
public static interface EntityDrawer {
|
||||
public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale,
|
||||
ElementContext ctx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class FloatInput extends Input {
|
||||
public Property<Float> prop;
|
||||
|
||||
public FloatInput(Property<Float> prop) {
|
||||
this.width = 120;
|
||||
this.height = Fonts.getHeight();
|
||||
this.prop = prop;
|
||||
this.text = String.valueOf(prop.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void charTyped(char chr) {
|
||||
if ((Character.isDigit(chr) || chr == '.' || (chr == '-' && cursorPosition == 0)) && text.length() < 10) {
|
||||
if (text.equals("0") && cursorPosition == 1) {
|
||||
text = "" + chr;
|
||||
} else {
|
||||
text = text.substring(0, cursorPosition) +
|
||||
chr +
|
||||
text.substring(cursorPosition);
|
||||
|
||||
try {
|
||||
prop.value = text.isEmpty() ? 0 : Float.parseFloat(text);
|
||||
cursorPosition++;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void backspace() {
|
||||
try {
|
||||
if (text.length() == 0) {
|
||||
text = "0";
|
||||
cursorPosition = 1;
|
||||
}
|
||||
prop.value = Float.parseFloat(text);
|
||||
ConfigManager.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkReset() {
|
||||
if (prop.isReset) {
|
||||
this.text = String.valueOf(prop.value);
|
||||
this.cursorPosition = 0;
|
||||
prop.isReset = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class HexInput extends Element {
|
||||
public Property<Integer> prop;
|
||||
|
||||
// Picker state
|
||||
private boolean open = false;
|
||||
private float hue = 0f;
|
||||
private float opacity = 1f;
|
||||
private int selectedX = 0;
|
||||
private int selectedY = 0;
|
||||
|
||||
private boolean draggingOpacity = false;
|
||||
|
||||
// Dimensions
|
||||
private static final int PICKER_WIDTH = 100;
|
||||
private static final int PICKER_HEIGHT = 100;
|
||||
private static final int SLIDER_WIDTH = 100;
|
||||
private static final int SLIDER_HEIGHT = 10;
|
||||
private static final int HUE_SLIDER_HEIGHT = 10;
|
||||
|
||||
public HexInput(Property<Integer> prop) {
|
||||
this.prop = prop;
|
||||
this.width = 58;
|
||||
this.height = 20;
|
||||
syncFromColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
open = !open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (open) {
|
||||
handlePickerClick(mouseX - width - 8, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
if (open) {
|
||||
handlePickerDrag(mouseX - width - 8, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(double mouseX, double mouseY, int button) {
|
||||
draggingOpacity = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
// Draw the main color rectangle
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, 6, prop.value);
|
||||
|
||||
if (!open)
|
||||
return;
|
||||
|
||||
// Draw the picker relative to (width + 8, 0)
|
||||
int pickerX = width + 8;
|
||||
int pickerY = 0;
|
||||
|
||||
renderColorSquare(renderScope, pickerX, pickerY);
|
||||
renderOpacitySlider(renderScope, pickerX, pickerY - SLIDER_HEIGHT - 10);
|
||||
renderHueSlider(renderScope, pickerX, pickerY + PICKER_HEIGHT + 10);
|
||||
}
|
||||
|
||||
private void renderColorSquare(RenderScope renderScope, int xStart, int yStart) {
|
||||
for (int x = 0; x < PICKER_WIDTH; x++) {
|
||||
for (int y = 0; y < PICKER_HEIGHT; y++) {
|
||||
float saturation = x / (float) PICKER_WIDTH;
|
||||
float value = 1f - y / (float) PICKER_HEIGHT;
|
||||
int color = Color.HSBtoRGB(hue, saturation, value);
|
||||
int alpha = (int) (opacity * 255) & 0xFF;
|
||||
color = (alpha << 24) | (color & 0xFFFFFF);
|
||||
renderScope.fill(xStart + x, yStart + y, xStart + x + 1, yStart + y + 1, color);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw selection square
|
||||
int selX = xStart + selectedX - 4;
|
||||
int selY = yStart + selectedY - 4;
|
||||
renderScope.fill(selX, selY, selX + 8, selY + 8, 0xFF000000 | prop.value);
|
||||
renderScope.drawBorder(selX, selY, 8, 8, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
private void renderOpacitySlider(RenderScope renderScope, int xStart, int yStart) {
|
||||
for (int x = 0; x < SLIDER_WIDTH; x++) {
|
||||
float localOpacity = x / (float) SLIDER_WIDTH;
|
||||
int alpha = (int) (localOpacity * 255) & 0xFF;
|
||||
int color = (alpha << 24) | (prop.value & 0xFFFFFF);
|
||||
renderScope.fill(xStart + x, yStart, xStart + x + 1, yStart + SLIDER_HEIGHT, color);
|
||||
}
|
||||
|
||||
int knobX = xStart + (int) (opacity * SLIDER_WIDTH);
|
||||
renderScope.fill(knobX - 1, yStart - 2, knobX + 1, yStart + SLIDER_HEIGHT + 2, 0xFF000000);
|
||||
}
|
||||
|
||||
private void renderHueSlider(RenderScope renderScope, int xStart, int yStart) {
|
||||
for (int x = 0; x < SLIDER_WIDTH; x++) {
|
||||
float localHue = x / (float) SLIDER_WIDTH;
|
||||
int color = Color.HSBtoRGB(localHue, 1f, 1f);
|
||||
renderScope.fill(xStart + x, yStart, xStart + x + 1, yStart + HUE_SLIDER_HEIGHT, 0xFF000000 | color);
|
||||
}
|
||||
|
||||
int knobX = xStart + (int) (hue * SLIDER_WIDTH);
|
||||
renderScope.fill(knobX - 1, yStart - 2, knobX + 1, yStart + HUE_SLIDER_HEIGHT + 2, 0xFF000000);
|
||||
}
|
||||
|
||||
private void handlePickerClick(double mouseX, double mouseY) {
|
||||
// Color square
|
||||
if (mouseX >= 0 && mouseX < PICKER_WIDTH && mouseY >= 0 && mouseY < PICKER_HEIGHT) {
|
||||
selectedX = (int) mouseX;
|
||||
selectedY = (int) mouseY;
|
||||
updateColorFromSelection();
|
||||
}
|
||||
|
||||
// Opacity slider
|
||||
int opY = -SLIDER_HEIGHT - 10;
|
||||
if (mouseX >= 0 && mouseX < SLIDER_WIDTH && mouseY >= opY && mouseY <= opY + SLIDER_HEIGHT) {
|
||||
updateOpacity(mouseX);
|
||||
draggingOpacity = true;
|
||||
}
|
||||
|
||||
// Hue slider
|
||||
int hueY = PICKER_HEIGHT + 10;
|
||||
if (mouseX >= 0 && mouseX < SLIDER_WIDTH && mouseY >= hueY && mouseY <= hueY + HUE_SLIDER_HEIGHT) {
|
||||
updateHue(mouseX);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePickerDrag(double mouseX, double mouseY) {
|
||||
// Opacity
|
||||
if (draggingOpacity)
|
||||
updateOpacity(mouseX);
|
||||
|
||||
// Color square
|
||||
if (mouseX >= 0 && mouseX < PICKER_WIDTH && mouseY >= 0 && mouseY < PICKER_HEIGHT) {
|
||||
selectedX = (int) mouseX;
|
||||
selectedY = (int) mouseY;
|
||||
updateColorFromSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColorFromSelection() {
|
||||
float saturation = selectedX / (float) PICKER_WIDTH;
|
||||
float value = 1f - selectedY / (float) PICKER_HEIGHT;
|
||||
int color = Color.HSBtoRGB(hue, saturation, value);
|
||||
int alpha = (int) (opacity * 255) & 0xFF;
|
||||
prop.value = (alpha << 24) | (color & 0xFFFFFF);
|
||||
}
|
||||
|
||||
private void updateHue(double mouseX) {
|
||||
hue = (float) Math.max(0, Math.min(1, mouseX / SLIDER_WIDTH));
|
||||
updateColorFromSelection();
|
||||
}
|
||||
|
||||
private void updateOpacity(double mouseX) {
|
||||
opacity = (float) Math.max(0, Math.min(1, mouseX / SLIDER_WIDTH));
|
||||
updateColorFromSelection();
|
||||
}
|
||||
|
||||
private void syncFromColor() {
|
||||
int rgb = prop.value & 0xFFFFFF;
|
||||
float[] hsb = Color.RGBtoHSB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF, null);
|
||||
hue = hsb[0];
|
||||
selectedX = (int) (hsb[1] * PICKER_WIDTH);
|
||||
selectedY = (int) ((1f - hsb[2]) * PICKER_HEIGHT);
|
||||
int alpha = (prop.value >> 24) & 0xFF;
|
||||
if (alpha == 0)
|
||||
alpha = 255;
|
||||
opacity = alpha / 255f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.Key;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public abstract class Input extends Element {
|
||||
String text = "";
|
||||
public int cursorPosition = 0;
|
||||
|
||||
public abstract void checkReset();
|
||||
|
||||
public abstract void backspace();
|
||||
|
||||
public boolean validateBackspace() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (keyCode == Key.GLFW_KEY_BACKSPACE) {
|
||||
if (cursorPosition > 0 && validateBackspace()) {
|
||||
text = text.substring(0, cursorPosition - 1) +
|
||||
text.substring(cursorPosition);
|
||||
cursorPosition--;
|
||||
backspace();
|
||||
}
|
||||
} else if (keyCode == Key.GLFW_KEY_LEFT) {
|
||||
if (cursorPosition > 0) {
|
||||
cursorPosition--;
|
||||
}
|
||||
} else if (keyCode == Key.GLFW_KEY_RIGHT) {
|
||||
if (cursorPosition < text.length()) {
|
||||
cursorPosition++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
int scrollOffset = getScrollOffset();
|
||||
String visibleText = text.substring(scrollOffset);
|
||||
|
||||
int newCursorPos = scrollOffset;
|
||||
float textWidth = 0;
|
||||
|
||||
for (int i = 0; i < visibleText.length(); i++) {
|
||||
textWidth = Fonts.getWidth(visibleText.substring(0, i + 1), Theme.FONT.value) * 0.6f;
|
||||
|
||||
if (textWidth > mouseX) {
|
||||
break;
|
||||
}
|
||||
|
||||
newCursorPos++;
|
||||
}
|
||||
|
||||
cursorPosition = newCursorPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
checkReset();
|
||||
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, 10, 0xFF000000);
|
||||
|
||||
int scrollOffset = getScrollOffset();
|
||||
String visibleText = getVisibleText(scrollOffset);
|
||||
int textColor = focused ? 0xFFFFFF : 0xAAAAAA;
|
||||
renderScope.drawText(0.6f, visibleText, 4, 4, Theme.FONT.value, textColor);
|
||||
|
||||
if (focused) {
|
||||
int cursorX = 4 +
|
||||
(int) (Fonts.getWidth(visibleText.substring(0, cursorPosition - scrollOffset), Theme.FONT.value)
|
||||
* 0.6f);
|
||||
|
||||
renderScope.drawRect(cursorX, 2, 1, height - 4, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getScrollOffset() {
|
||||
if (text.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
int maxWidth = width - 4; // Available width for text
|
||||
while (offset < cursorPosition) { // Ensure cursor remains visible
|
||||
String visibleText = text.substring(offset, cursorPosition);
|
||||
if (Fonts.getWidth(visibleText, Theme.FONT.value) > maxWidth) {
|
||||
offset++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
protected String getVisibleText(int scrollOffset) {
|
||||
String visibleText = text.substring(scrollOffset);
|
||||
|
||||
// Ensure text does not overflow past the available width
|
||||
for (int i = 1; i <= visibleText.length(); i++) {
|
||||
if (Fonts.getWidth(visibleText.substring(0, i), Theme.FONT.value) > width - 4) {
|
||||
return visibleText.substring(0, i - 1); // Trim overflow
|
||||
}
|
||||
}
|
||||
return visibleText;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class IntInput extends Input {
|
||||
public Property<Integer> prop;
|
||||
|
||||
public IntInput(Property<Integer> prop) {
|
||||
this.width = 120;
|
||||
this.height = Fonts.getHeight();
|
||||
this.prop = prop;
|
||||
this.text = String.valueOf(prop.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void charTyped(char chr) {
|
||||
if ((Character.isDigit(chr) || chr == '.' || (chr == '-' && cursorPosition == 0)) && text.length() < 10) {
|
||||
if (text.equals("0") && cursorPosition == 1) {
|
||||
text = "" + chr;
|
||||
} else {
|
||||
text = text.substring(0, cursorPosition) +
|
||||
chr +
|
||||
text.substring(cursorPosition);
|
||||
|
||||
try {
|
||||
prop.value = text.isEmpty() ? 0 : Integer.parseInt(text);
|
||||
cursorPosition++;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void backspace() {
|
||||
try {
|
||||
if (text.length() == 0) {
|
||||
text = "0";
|
||||
cursorPosition = 1;
|
||||
}
|
||||
prop.value = Integer.parseInt(text);
|
||||
ConfigManager.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkReset() {
|
||||
if (prop.isReset) {
|
||||
this.text = String.valueOf(prop.value);
|
||||
this.cursorPosition = 0;
|
||||
prop.isReset = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.Key;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class KeybindingSelector extends Element {
|
||||
Property<Integer> prop;
|
||||
|
||||
public KeybindingSelector(Property<Integer> prop) {
|
||||
this.prop = prop;
|
||||
this.width = 120;
|
||||
this.height = Fonts.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
int textColor = focused ? 0xFFFFFF : 0xAAAAAA;
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, 10, 0xFF000000);
|
||||
String name = MinecraftProvider.PROVIDER.getKeyName(prop.value);
|
||||
|
||||
renderScope.drawText(0.6f,
|
||||
prop.value == -1 ? "<NONE>"
|
||||
: name != null ? name.toUpperCase() : "<Invalid-Key>",
|
||||
4, 4, Theme.FONT.value, textColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (keyCode == Key.GLFW_KEY_BACKSPACE) {
|
||||
prop.value = -1;
|
||||
} else {
|
||||
prop.value = keyCode;
|
||||
}
|
||||
focused = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.Utils;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Select extends Element {
|
||||
private Property<Integer> prop;
|
||||
|
||||
public Select(Property<Integer> prop) {
|
||||
this.prop = prop;
|
||||
this.width = 150;
|
||||
this.height = 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawText(0.8f, "<", 0, 0, Theme.FONT.value, Theme.FOREGROUND.value);
|
||||
|
||||
String text = prop.getSelection();
|
||||
|
||||
renderScope.drawText(0.6f, text, (int) (width - ((float) Fonts.getWidth(text, Theme.FONT.value) * 0.6f)) / 2, 1,
|
||||
Theme.FONT.value, Theme.FOREGROUND.value);
|
||||
|
||||
renderScope.drawText(0.8f, ">", width - 10, 0, Theme.FONT.value, Theme.FOREGROUND.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
if (Utils.isHovering(mouseX - (width - 10), mouseY, 10, height, 1.0f)) {
|
||||
prop.next();
|
||||
} else if (Utils.isHovering(mouseX, mouseY, 10, height, 1.0f)) {
|
||||
prop.prev();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.saturnclient.ui.components.inputs;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class Toggle extends Element {
|
||||
private Property<Boolean> prop;
|
||||
|
||||
public Toggle(Property<Boolean> prop) {
|
||||
this.prop = prop;
|
||||
this.width = 60;
|
||||
this.height = 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, height,
|
||||
Theme.withAlpha(0.5f, prop.value ? Theme.ACCENT.value : Theme.PRIMARY.value));
|
||||
renderScope.drawRoundedRectangle(prop.value ? 30 : 0, 0, 30, 30, 30,
|
||||
prop.value ? Theme.ACCENT.value : Theme.PRIMARY.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
prop.value = !prop.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.config.Config;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.ElementRenderer;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class AnimationStagger extends Element {
|
||||
protected List<Element> children = new ArrayList<>();
|
||||
public int delay;
|
||||
|
||||
public AnimationStagger(int delay) {
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public AnimationStagger(AnimationConfig config) {
|
||||
this.delay = config.stagger.value;
|
||||
}
|
||||
|
||||
public void draw(Element element) {
|
||||
if (!Config.stagger.value) {
|
||||
element.animation = null;
|
||||
}
|
||||
|
||||
if (element.animation != null) {
|
||||
element.animation.delay = delay * children.size();
|
||||
}
|
||||
|
||||
ElementRenderer.INSTANCE.draw(children, element);
|
||||
|
||||
this.height = Math.max(this.height, element.y + element.height);
|
||||
this.width = Math.max(this.width, element.x + element.width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
ElementRenderer.INSTANCE.render(children, ctx.elapsed, renderScope,
|
||||
ctx.mouseX,
|
||||
ctx.mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(double mouseX, double mouseY, int button) {
|
||||
ElementRenderer.INSTANCE.mouseClicked(children, mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
ElementRenderer.INSTANCE.keyPressed(children, keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
ElementRenderer.INSTANCE.mouseDragged(children, mouseX, mouseY, button, deltaX, deltaY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(double mouseX, double mouseY, int button) {
|
||||
ElementRenderer.INSTANCE.mouseReleased(children, mouseX, mouseY, button);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Button extends Element {
|
||||
private String text;
|
||||
private Runnable onClick;
|
||||
|
||||
public Button(String text, Runnable onClick) {
|
||||
this.text = text;
|
||||
this.onClick = onClick;
|
||||
this.dimensions(Fonts.getWidth(text, Theme.FONT.value) + 50, 38);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value,
|
||||
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
|
||||
|
||||
renderScope.drawText(text, Fonts.centerX(width, text, Theme.FONT.value), Fonts.centerY(height),
|
||||
Theme.FONT.value,
|
||||
ctx.isHovering() ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
if (onClick != null) {
|
||||
onClick.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class ClickableTexture extends Element {
|
||||
SaturnIdentifier sprite;
|
||||
private Runnable onClick;
|
||||
|
||||
public ClickableTexture(SaturnIdentifier sprite, Runnable onClick) {
|
||||
this.sprite = sprite;
|
||||
this.onClick = onClick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawTexture(sprite, 0, 0, 0, 0, width, height,
|
||||
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
if (onClick != null) {
|
||||
onClick.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.common.minecraft.IMinecraftClient;
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.SvgTexture;
|
||||
|
||||
public class ImageTexture extends Element {
|
||||
SaturnIdentifier sprite;
|
||||
|
||||
public ImageTexture(SaturnIdentifier sprite) {
|
||||
this.sprite = sprite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
if (sprite.toString().endsWith(".svg")) {
|
||||
IMinecraftClient client = MinecraftProvider.PROVIDER.getClient();
|
||||
|
||||
int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWidth());
|
||||
int renderHeight = (int) (height * client.getWindow().getFramebufferHeight()
|
||||
/ client.getWindow().getHeight());
|
||||
|
||||
SaturnIdentifier pngId = SvgTexture.getSvg(client, sprite, renderWidth * 2, renderHeight * 2);
|
||||
|
||||
this.sprite = pngId;
|
||||
if (pngId == null) {
|
||||
System.err.println("Failed to render SVG: " + sprite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
renderScope.drawTexture(this.sprite, 0, 0, 0, 0, width, height);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.anim.SlideX;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
public class Notification extends Element {
|
||||
private static Property<Integer> error = Property.color(0xFFbf212f);
|
||||
private static Property<Integer> info = Property.color(0xFF264b96);
|
||||
private static Property<Integer> success = Property.color(0xFF27b376);
|
||||
|
||||
public static enum NotificationKind {
|
||||
Error,
|
||||
Info,
|
||||
Success,
|
||||
}
|
||||
|
||||
NotificationKind kind;
|
||||
String text;
|
||||
String title;
|
||||
|
||||
public Notification(int width, int height, NotificationKind kind, String title, String text) {
|
||||
this.kind = kind;
|
||||
this.text = text;
|
||||
this.title = title;
|
||||
this.width = (int) Math.max(Fonts.getWidth(text, 1) * 0.6f, Fonts.getWidth(title, 1)) + 20;
|
||||
this.height = 50;
|
||||
this.x = width - this.width - 15;
|
||||
this.y = height - this.height - 15;
|
||||
this.animation = new SlideX(700, -width);
|
||||
this.duration = 3000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, 10, Theme.PRIMARY.value);
|
||||
switch (kind) {
|
||||
case Error:
|
||||
renderScope.drawTexture(Textures.CIRCLE_X, 9, 9, 0, 0, 15, 15, error.value);
|
||||
break;
|
||||
|
||||
case Info:
|
||||
renderScope.drawTexture(Textures.INFO, 9, 9, 0, 0, 15, 15, info.value);
|
||||
break;
|
||||
|
||||
case Success:
|
||||
renderScope.drawTexture(Textures.CHECK, 9, 9, 0, 0, 15, 15, success.value);
|
||||
break;
|
||||
}
|
||||
renderScope.drawText(0.7f, title, 32, 10, 1, -1);
|
||||
renderScope.drawText(0.5f, text, 32, 28, 1, -1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.ElementRenderer;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class Scroll extends Element {
|
||||
private static Property<Integer> scrollBarRadius = Property.integer(10);
|
||||
private static Property<Integer> scrollBarWidth = Property.integer(5);
|
||||
private static Property<Integer> scrollBarPadding = Property.integer(5);
|
||||
|
||||
int padding = 0;
|
||||
|
||||
protected List<Element> children = new ArrayList<>();
|
||||
int scroll = 0;
|
||||
int maxScroll = 0;
|
||||
|
||||
public Scroll(int padding) {
|
||||
this.padding = padding;
|
||||
}
|
||||
|
||||
public void draw(Element element) {
|
||||
ElementRenderer.INSTANCE.draw(children, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
calculateMaxScroll();
|
||||
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height,
|
||||
Theme.BG_RADIUS.value, Theme.BACKGROUND.value);
|
||||
|
||||
renderScope.enableScissor(padding, padding, width - padding, height - padding);
|
||||
renderScope.getMatrixStack().push();
|
||||
renderScope.getMatrixStack().translate(padding, -scroll + padding, 0);
|
||||
|
||||
ElementRenderer.INSTANCE.render(children, ctx.elapsed, renderScope,
|
||||
ctx.mouseX - padding,
|
||||
ctx.mouseY - padding + scroll);
|
||||
|
||||
renderScope.getMatrixStack().pop();
|
||||
renderScope.disableScissor();
|
||||
|
||||
if (maxScroll > 0) {
|
||||
renderScope.drawRoundedRectangle(
|
||||
width - scrollBarWidth.value - scrollBarPadding.value,
|
||||
calculateScrollBarY(),
|
||||
scrollBarWidth.value,
|
||||
calculateScrollBarHeight(),
|
||||
scrollBarRadius.value,
|
||||
Theme.SCROLL.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scroll(int mouseX, int mouseY, double horizontalAmount, double verticalAmount) {
|
||||
scroll -= verticalAmount;
|
||||
if (scroll < 0) {
|
||||
scroll = 0;
|
||||
} else if (scroll > maxScroll) {
|
||||
scroll = maxScroll;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element dimensions(int width, int height) {
|
||||
super.dimensions(width, height);
|
||||
|
||||
maxScroll = 0;
|
||||
for (Element element : children) {
|
||||
maxScroll = Math.max(maxScroll, (element.y + element.height + padding) - (height - padding * 2));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int calculateScrollBarHeight() {
|
||||
if (maxScroll <= 0)
|
||||
return height - (scrollBarPadding.value * 2);
|
||||
return Math.max(20, (height * height) / (height + maxScroll + 10)) - (scrollBarPadding.value * 2);
|
||||
}
|
||||
|
||||
int calculateScrollBarY() {
|
||||
int scrollBarHeight = calculateScrollBarHeight();
|
||||
if (maxScroll <= 0)
|
||||
return scrollBarPadding.value;
|
||||
int y = (scroll * (height - scrollBarHeight - scrollBarPadding.value * 2)) / maxScroll + scrollBarPadding.value;
|
||||
return Math.min(y, height - scrollBarHeight - scrollBarPadding.value);
|
||||
}
|
||||
|
||||
private void calculateMaxScroll() {
|
||||
maxScroll = 0;
|
||||
|
||||
for (Element element : children) {
|
||||
int bottom = element.y + element.height;
|
||||
maxScroll = Math.max(maxScroll, bottom - height + padding);
|
||||
}
|
||||
|
||||
if (maxScroll > 0) {
|
||||
maxScroll = maxScroll + 10;
|
||||
} else {
|
||||
maxScroll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
ElementRenderer.INSTANCE.keyPressed(children, keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(double mouseX, double mouseY, int button) {
|
||||
ElementRenderer.INSTANCE.mouseClicked(children, mouseX - padding, mouseY - padding + scroll, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
ElementRenderer.INSTANCE.mouseDragged(children, mouseX - padding, mouseY - padding + scroll, button, deltaX,
|
||||
deltaY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(double mouseX, double mouseY, int button) {
|
||||
ElementRenderer.INSTANCE.mouseReleased(children, mouseX - padding, mouseY - padding + scroll, button);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.Utils;
|
||||
|
||||
public class TabMenu extends Element {
|
||||
public static class TabMenuComponent {
|
||||
Runnable onClick;
|
||||
SaturnIdentifier sprite;
|
||||
|
||||
public TabMenuComponent(SaturnIdentifier sprite, Runnable onClick) {
|
||||
this.onClick = onClick;
|
||||
this.sprite = sprite;
|
||||
}
|
||||
}
|
||||
|
||||
TabMenuComponent[] components;
|
||||
public int selectedScreen = 0;
|
||||
|
||||
public TabMenu(int active, TabMenuComponent... components) {
|
||||
this.components = components;
|
||||
width = 25 * components.length + 6;
|
||||
height = 30;
|
||||
this.selectedScreen = active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, Theme.PRIMARY.value);
|
||||
|
||||
int col = 0;
|
||||
for (TabMenuComponent component : components) {
|
||||
int x = 25 * col + 5;
|
||||
|
||||
boolean hovering = ctx.isHovering(x, 5, 20, 20) || selectedScreen == col;
|
||||
|
||||
if (hovering) {
|
||||
renderScope.drawRoundedRectangle(x, 5, 20, 20, Theme.WIDGET_RADIUS.value, Theme.ACCENT.value);
|
||||
}
|
||||
|
||||
renderScope.drawTexture(component.sprite, x + 5, 10, 0, 0, 10, 10,
|
||||
hovering ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
|
||||
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
int col = 0;
|
||||
for (TabMenuComponent component : components) {
|
||||
int x = 25 * col + 5;
|
||||
if (Utils.isHovering(mouseX - x, mouseY - 5, 20, 20, 1.0f)) {
|
||||
component.onClick.run();
|
||||
}
|
||||
col++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class Text extends Element {
|
||||
private String text;
|
||||
|
||||
public Text(String text) {
|
||||
this.text = text;
|
||||
width = Fonts.getWidth(text, Theme.FONT.value);
|
||||
height = Fonts.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawText(this.text, 0, 0, Theme.FONT.value, Theme.FOREGROUND.value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.saturnclient.ui.elements;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
public class TextureButton extends Element {
|
||||
SaturnIdentifier sprite;
|
||||
private Runnable onClick;
|
||||
static int padding = 14;
|
||||
|
||||
public TextureButton(SaturnIdentifier sprite, Runnable onClick) {
|
||||
this.sprite = sprite;
|
||||
this.onClick = onClick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value,
|
||||
ctx.isHovering() ? Theme.ACCENT.value : Theme.PRIMARY.value);
|
||||
|
||||
int texWidth = width - padding;
|
||||
int texHeight = height - padding;
|
||||
|
||||
renderScope.drawTexture(sprite, padding / 2, padding / 2, 0, 0, texWidth, texHeight,
|
||||
ctx.isHovering() ? Theme.ACCENT_FG.value : Theme.PRIMARY_FG.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
if (onClick != null) {
|
||||
onClick.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.saturnclient.ui.resources;
|
||||
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
|
||||
public class Fonts {
|
||||
public static final SaturnIdentifier INTER = SaturnIdentifier.of("saturnclient", "inter");
|
||||
public static final SaturnIdentifier INTER_BOLD = SaturnIdentifier.of("saturnclient", "inter_bold");
|
||||
public static final SaturnIdentifier DEFAULT = SaturnIdentifier.ofVanilla("default");
|
||||
|
||||
public static SaturnIdentifier getFont(int font) {
|
||||
switch (font) {
|
||||
case 0:
|
||||
return DEFAULT;
|
||||
case 1:
|
||||
return INTER;
|
||||
default:
|
||||
return INTER_BOLD;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getWidth(String text, int font) {
|
||||
int w = 0;
|
||||
for (String line : text.split("\n")) {
|
||||
w = Math.max(w, MinecraftProvider.PROVIDER.getWidth(line, font));
|
||||
}
|
||||
if (font == 0) {
|
||||
return w * 2;
|
||||
} else {
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getHeight() {
|
||||
return 18;
|
||||
}
|
||||
|
||||
public static int centerX(int w, String text, int font) {
|
||||
return (w - Fonts.getWidth(text, font)) / 2;
|
||||
}
|
||||
|
||||
public static int centerY(int h) {
|
||||
return (h - 18) / 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.saturnclient.ui.resources;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.kitfox.svg.SVGDiagram;
|
||||
import com.kitfox.svg.SVGUniverse;
|
||||
|
||||
import org.saturnclient.common.minecraft.IMinecraftClient;
|
||||
import org.saturnclient.common.minecraft.MinecraftProvider;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
|
||||
public class SvgTexture {
|
||||
|
||||
private static List<SaturnIdentifier> svgCache = new ArrayList<>();
|
||||
|
||||
private static BufferedImage renderSvg(InputStream svgStream, int width, int height) throws Exception {
|
||||
// Load SVG
|
||||
SVGUniverse universe = new SVGUniverse();
|
||||
java.net.URI uri = universe.loadSVG(svgStream, "tempSvg");
|
||||
SVGDiagram diagram = universe.getDiagram(uri);
|
||||
|
||||
// Get intrinsic size of SVG
|
||||
float svgWidth = (float) diagram.getWidth();
|
||||
float svgHeight = (float) diagram.getHeight();
|
||||
|
||||
// Compute scale factors
|
||||
float scaleX = width / svgWidth;
|
||||
float scaleY = height / svgHeight;
|
||||
|
||||
// Create output image
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = image.createGraphics();
|
||||
|
||||
// Enable anti-aliasing for smooth scaling
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
|
||||
// Apply scaling transform
|
||||
g.scale(scaleX, scaleY);
|
||||
|
||||
// Render SVG
|
||||
diagram.render(g);
|
||||
|
||||
g.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
public static SaturnIdentifier getSvg(IMinecraftClient client, SaturnIdentifier svgImage, int width, int height) {
|
||||
SaturnIdentifier id = SaturnIdentifier
|
||||
.of(svgImage.toString().replaceAll("\\.svg$", (width + "_" + height).toString() + ".png"));
|
||||
|
||||
if (svgCache.contains(id)) {
|
||||
return id;
|
||||
}
|
||||
|
||||
try (InputStream svgStream = client.getResource(svgImage)) {
|
||||
|
||||
BufferedImage image = renderSvg(svgStream, width, height);
|
||||
|
||||
MinecraftProvider.PROVIDER.registerBufferedImageTexture(id, image);
|
||||
|
||||
return id;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.saturnclient.ui.resources;
|
||||
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnIdentifier;
|
||||
|
||||
public class Textures {
|
||||
public static final SaturnIdentifier CROSSHAIR_RANGE = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/hud/crosshair_range.png");
|
||||
public static final SaturnIdentifier COSMETICS = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/cosmetics.png");
|
||||
public static final SaturnIdentifier HUD_ICON = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/hud.png");
|
||||
public static final SaturnIdentifier SEARCH = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/search.png");
|
||||
public static final SaturnIdentifier CLOSE = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/close.png");
|
||||
public static final SaturnIdentifier MODS_TAB = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/mods_tab.png");
|
||||
public static final SaturnIdentifier SETTINGS = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/settings.png");
|
||||
public static final SaturnIdentifier CLOAK = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/cloak.png");
|
||||
public static final SaturnIdentifier HAT = new SaturnIdentifier("saturnclient", "textures/gui/components/hat.png");
|
||||
public static final SaturnIdentifier RESET = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/reset.png");
|
||||
public static final SaturnIdentifier TOGGLE_INDICATOR = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/toggle_indicator.png");
|
||||
public static final SaturnIdentifier LEFT = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/left.png");
|
||||
public static final SaturnIdentifier RIGHT = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/right.png");
|
||||
public static final SaturnIdentifier STORE = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/store.png");
|
||||
public static final SaturnIdentifier COINS = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/coins.png");
|
||||
public static final SaturnIdentifier SHIRT = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/shirt.png");
|
||||
public static final SaturnIdentifier CIRCLE_X = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/circle_x.png");
|
||||
public static final SaturnIdentifier INFO = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/info.png");
|
||||
public static final SaturnIdentifier CHECK = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/check.png");
|
||||
|
||||
public static final SaturnIdentifier LOGO = new SaturnIdentifier("saturnclient", "textures/logo/logo.png");
|
||||
public static final SaturnIdentifier REALISTIC_LOGO = new SaturnIdentifier("saturnclient",
|
||||
"textures/logo/realistic.png");
|
||||
public static final SaturnIdentifier LOGO_TEXT = new SaturnIdentifier("saturnclient", "textures/logo/text.png");
|
||||
public static final SaturnIdentifier LOGO_TEXT_BIG = new SaturnIdentifier("saturnclient",
|
||||
"textures/logo/text_big.png");
|
||||
public static final SaturnIdentifier SPLASH = new SaturnIdentifier("saturnclient", "textures/gui/splash.png");
|
||||
|
||||
// Widgets
|
||||
public static final SaturnIdentifier BUTTON_BORDER = new SaturnIdentifier("saturnclient", "button_border");
|
||||
public static final SaturnIdentifier BUTTON = new SaturnIdentifier("saturnclient", "button");
|
||||
public static final SaturnIdentifier BUTTON_OP = new SaturnIdentifier("saturnclient", "button_op");
|
||||
public static final SaturnIdentifier SETTINGS_BG = new SaturnIdentifier("saturnclient", "settings_bg");
|
||||
public static final SaturnIdentifier RECT = new SaturnIdentifier("saturnclient", "rect");
|
||||
public static final SaturnIdentifier RECT_BORDER = new SaturnIdentifier("saturnclient", "rect_border");
|
||||
public static final SaturnIdentifier MOD = new SaturnIdentifier("saturnclient", "textures/gui/components/mod.png");
|
||||
public static final SaturnIdentifier MOD_BG = new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/components/mod_bg.png");
|
||||
|
||||
public static SaturnIdentifier getCloakPreview(String cloak) {
|
||||
return new SaturnIdentifier("saturnclient",
|
||||
"textures/gui/cloak/" + (cloak.isEmpty() ? "none" : cloak) + ".png");
|
||||
}
|
||||
|
||||
public static SaturnIdentifier getHatPreview(String hat) {
|
||||
return new SaturnIdentifier("saturnclient", "textures/gui/hat/" + (hat.isEmpty() ? "none" : hat) + ".png");
|
||||
}
|
||||
|
||||
public static SaturnIdentifier getEmotePreview(String emote) {
|
||||
return new SaturnIdentifier("saturnclient", "textures/gui/emote/" + (emote == null ? "none" : emote) + ".png");
|
||||
}
|
||||
|
||||
public static SaturnIdentifier getModIcon(String modId) {
|
||||
return new SaturnIdentifier("saturnclient", "textures/gui/mod/" + modId + ".svg");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package org.saturnclient.ui.screens;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.manager.ConfigManager;
|
||||
import org.saturnclient.config.manager.Property;
|
||||
import org.saturnclient.ui.SaturnScreen;
|
||||
import org.saturnclient.ui.components.Sidebar;
|
||||
import org.saturnclient.ui.components.inputs.FloatInput;
|
||||
import org.saturnclient.ui.components.inputs.HexInput;
|
||||
import org.saturnclient.ui.components.inputs.IntInput;
|
||||
import org.saturnclient.ui.components.inputs.KeybindingSelector;
|
||||
import org.saturnclient.ui.components.inputs.Select;
|
||||
import org.saturnclient.ui.components.inputs.Toggle;
|
||||
import org.saturnclient.ui.elements.Scroll;
|
||||
import org.saturnclient.ui.elements.Text;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
public class ConfigEditor extends SaturnScreen {
|
||||
private ConfigManager config;
|
||||
|
||||
public ConfigEditor(ConfigManager config) {
|
||||
super("Config Editor");
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ui() {
|
||||
int p = 10;
|
||||
int g = 10;
|
||||
|
||||
Scroll scroll = new Scroll(p);
|
||||
|
||||
drawProperties(scroll, config.getProperties(), 0, 0, 480 + 10 + (g * 2));
|
||||
|
||||
int scrollWidth = 480 + 10 + (g * 2) + (p * 2);
|
||||
|
||||
draw(scroll.dimensions(scrollWidth, 350).center(width, height));
|
||||
|
||||
draw(new Sidebar(1, this.provider::close).centerOffset(width, height, -(scrollWidth / 2 + 20), 0));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private int drawProperties(Scroll configScroll, Map<String, Property<?>> properties, int row, int col, int w) {
|
||||
for (Map.Entry<String, Property<?>> propEntry : properties.entrySet()) {
|
||||
Property<?> prop = propEntry.getValue();
|
||||
String propName = propEntry.getKey();
|
||||
boolean full = isFull(prop);
|
||||
|
||||
// Always reset to col 0 if full-width component needs to be drawn mid-row
|
||||
if (full && col != 0) {
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
|
||||
int modX = (w / 2) * col; // two-column layout
|
||||
int modY = 25 * row;
|
||||
|
||||
if (prop.getType() == Property.PropertyType.NAMESPACE) {
|
||||
configScroll.draw(
|
||||
new Text(
|
||||
propName).position(Fonts.centerX(520, propName, Theme.FONT.value), modY + 1)
|
||||
.scale(0.7f));
|
||||
} else {
|
||||
configScroll.draw(
|
||||
new Text(
|
||||
propName).position(modX, modY + 1).scale(0.7f));
|
||||
}
|
||||
|
||||
switch (prop.getType()) {
|
||||
case BOOLEAN:
|
||||
configScroll.draw(
|
||||
new Toggle((Property<Boolean>) prop)
|
||||
.position(modX + (w / 2) - 40, modY)
|
||||
.scale(0.5f));
|
||||
break;
|
||||
|
||||
case HEX:
|
||||
configScroll.draw(new HexInput((Property<Integer>) prop).position(w / 2, modY));
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
configScroll.draw(new IntInput((Property<Integer>) prop).position(w / 2, modY));
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
configScroll.draw(new FloatInput((Property<Float>) prop).position(w / 2, modY));
|
||||
break;
|
||||
|
||||
case NAMESPACE:
|
||||
Map<String, Property<?>> nestedProperties = (Map<String, Property<?>>) prop.value;
|
||||
row = drawProperties(configScroll, nestedProperties, row + 1, col, w);
|
||||
break;
|
||||
|
||||
case SELECT:
|
||||
configScroll.draw(new Select((Property<Integer>) prop).position(w / 2, modY));
|
||||
break;
|
||||
|
||||
case KEYBINDING:
|
||||
configScroll.draw(new KeybindingSelector((Property<Integer>) prop).position(w / 2, modY));
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
}
|
||||
|
||||
if (full) {
|
||||
row++; // full-width takes a whole row
|
||||
col = 0;
|
||||
} else {
|
||||
col++;
|
||||
if (col > 1) { // max 2 columns
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
public static boolean isFull(Property<?> prop) {
|
||||
switch (prop.getType()) {
|
||||
case BOOLEAN:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.saturnclient.ui.screens;
|
||||
|
||||
import org.saturnclient.cosmetics.Emotes;
|
||||
import org.saturnclient.client.ServiceClient;
|
||||
import org.saturnclient.common.minecraft.bindings.SaturnClientBindings;
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.config.Config;
|
||||
import org.saturnclient.ui.SaturnScreen;
|
||||
import org.saturnclient.ui.Utils;
|
||||
import org.saturnclient.ui.anim.Fade;
|
||||
import org.saturnclient.ui.anim.SlideY;
|
||||
import org.saturnclient.ui.elements.AnimationStagger;
|
||||
import org.saturnclient.ui.elements.ImageTexture;
|
||||
import org.saturnclient.ui.elements.TextureButton;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
public class EmoteWheel extends SaturnScreen {
|
||||
int page = 1;
|
||||
|
||||
public EmoteWheel() {
|
||||
super("Emote Wheel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ui() {
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
|
||||
// =============================
|
||||
// Logo
|
||||
// =============================
|
||||
|
||||
draw(new ImageTexture(Textures.LOGO_TEXT)
|
||||
.dimensions(98, 10)
|
||||
.centerOffset(width, height, 0, -105)
|
||||
.animation(new Fade(AnimationConfig.logo.duration.value)));
|
||||
|
||||
draw(new ImageTexture(Config.getLogo())
|
||||
.dimensions(98, 98)
|
||||
.centerOffset(width, height, 0, -149)
|
||||
.animation(new SlideY(AnimationConfig.logo, -20)));
|
||||
|
||||
// =============================
|
||||
// Navigation Buttons
|
||||
// =============================
|
||||
|
||||
draw(new TextureButton(Textures.LEFT, () -> {
|
||||
if (page > 1) {
|
||||
page--;
|
||||
elements.clear();
|
||||
ui();
|
||||
}
|
||||
}).dimensions(30, 30)
|
||||
.centerOffset(width, height, -50, 105)
|
||||
.animation(new Fade(500)));
|
||||
|
||||
draw(new TextureButton(Textures.RIGHT, () -> {
|
||||
if ((page * 8) < Emotes.availableEmotes.size()) {
|
||||
page++;
|
||||
elements.clear();
|
||||
ui();
|
||||
}
|
||||
}).dimensions(30, 30)
|
||||
.centerOffset(width, height, 50, 105)
|
||||
.animation(new Fade(500)));
|
||||
|
||||
// =============================
|
||||
// Emote Grid (Staggered)
|
||||
// =============================
|
||||
|
||||
AnimationStagger emoteStagger = new AnimationStagger(AnimationConfig.emoteWheel);
|
||||
|
||||
while (row < 3) {
|
||||
|
||||
int idx = (row * 3 + col) + ((page - 1) * 8);
|
||||
|
||||
if (row == 1 && col == 1) {
|
||||
col++;
|
||||
}
|
||||
|
||||
String emote = Utils.getOrNull(Emotes.availableEmotes, idx);
|
||||
|
||||
emoteStagger.draw(
|
||||
new TextureButton(Textures.getEmotePreview(emote), () -> {
|
||||
if (emote != null)
|
||||
SaturnClientBindings.emotes().setEmote(ServiceClient.uuid, emote);
|
||||
|
||||
provider.close();
|
||||
})
|
||||
.dimensions(70, 70)
|
||||
.centerOffset(width, height,
|
||||
-80 + (col * 80),
|
||||
-35 + (row * 80))
|
||||
.animation(new SlideY(AnimationConfig.emoteWheel, 12)));
|
||||
|
||||
if (col < 2) {
|
||||
col++;
|
||||
} else {
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
draw(emoteStagger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPause() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user