hexidecimal

This commit is contained in:
2025-03-26 17:50:38 +01:00
parent 6fc49863e1
commit 5e7ed4381e
18 changed files with 475 additions and 30 deletions
@@ -7,6 +7,7 @@ import net.minecraft.util.math.ColorHelper;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import org.saturnclient.saturnclient.cloaks.Cloaks;
import org.saturnclient.saturnclient.config.ConfigManager;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.saturnclient.event.KeyInputHandler;
import org.saturnclient.saturnmods.ModManager;
import org.saturnclient.ui.SaturnAnimation;
@@ -23,13 +24,31 @@ public class SaturnClient implements ModInitializer {
public static final String MOD_ID = "saturnclient";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static int COLOR = ColorHelper.getArgb(255, 251, 60, 79);
public static ConfigManager config = new ConfigManager("Saturn Client");
public static Property<Integer> COLOR = config.property(
"Primary color",
new Property<Integer>(
ColorHelper.getArgb(255, 251, 60, 79),
Property.PropertyType.HEX
)
);
public static Property<Integer> NORMAL = config.property(
"Normal color",
new Property<Integer>(
ColorHelper.getArgb(255, 182, 182, 182),
Property.PropertyType.HEX
)
);
// public static int NORMAL = ColorHelper.getArgb(255, 182, 182, 182);
public static int WHITE = ColorHelper.getArgb(255, 255, 255, 255);
public static int NORMAL = ColorHelper.getArgb(255, 182, 182, 182);
public static TextRenderer textRenderer = null;
public static int getWhite(float alpha) {
return ((int) (alpha * 255) << 24) | (NORMAL & 0x00FFFFFF);
return ((int) (alpha * 255) << 24) | (NORMAL.value & 0x00FFFFFF);
}
public static SaturnAnimation[] getAnimations() {
@@ -41,6 +41,7 @@ public class ConfigManager {
SaturnClient.LOGGER.info("Starting to load config...");
if (!configFile.exists()) {
configFile.createNewFile();
Files.write(configFile.toPath(), "{}".getBytes());
}
JsonObject jsonObject = JsonParser.parseString(
@@ -97,6 +98,9 @@ public class ConfigManager {
case STRING:
((Property<String>) p).value = c.getAsString();
break;
case HEX:
((Property<Integer>) p).value = c.getAsInt();
break;
default:
break;
}
@@ -152,6 +156,11 @@ public class ConfigManager {
(String) property.value
);
break;
case HEX:
propertyValue = new JsonPrimitive(
(Integer) property.value
);
break;
default:
SaturnClient.LOGGER.warn(
"Unknown property type for: " + propertyName
@@ -10,12 +10,28 @@ public class Property<T> {
INTEGER,
FLOAT,
STRING,
HEX,
}
public T value;
private PropertyType type;
public Property(T value) {
this.value = value;
if (value instanceof Boolean) {
type = PropertyType.BOOLEAN;
} else if (value instanceof Integer) {
type = PropertyType.INTEGER;
} else if (value instanceof Float) {
type = PropertyType.FLOAT;
} else if (value instanceof String) {
type = PropertyType.STRING;
}
}
public Property(T value, PropertyType type) {
this.value = value;
this.type = type;
}
public boolean getBool() {
@@ -46,20 +62,26 @@ public class Property<T> {
throw new IllegalStateException("Property does not contain a string");
}
public PropertyType getType() {
if (value instanceof Boolean) {
return PropertyType.BOOLEAN;
}
if (value instanceof Integer) {
return PropertyType.INTEGER;
}
if (value instanceof Float) {
return PropertyType.FLOAT;
}
public int getHexString() {
if (value instanceof String) {
return PropertyType.STRING;
String str = (String) value;
if (str.startsWith("0x") || str.startsWith("0X")) {
try {
return Integer.parseInt(str.substring(2), 16);
} catch (NumberFormatException e) {
throw new IllegalStateException(
"Invalid hexadecimal integer format"
);
}
}
}
return null;
throw new IllegalStateException(
"Property does not contain a valid hex integer"
);
}
public PropertyType getType() {
return type;
}
public boolean matchesJson(JsonElement element) {
@@ -69,6 +91,12 @@ public class Property<T> {
if (value instanceof Integer && primitive.isNumber()) return true;
if (value instanceof Float && primitive.isNumber()) return true;
if (value instanceof String && primitive.isString()) return true;
// Check if JSON string represents a valid hex integer
if (value instanceof String && primitive.isString()) {
String str = primitive.getAsString();
return str.matches("0x[0-9A-Fa-f]+");
}
}
return false;
}
@@ -8,6 +8,7 @@ import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.Textures;
import org.saturnclient.ui.components.SaturnFloat;
import org.saturnclient.ui.components.SaturnHex;
import org.saturnclient.ui.components.SaturnInteger;
import org.saturnclient.ui.components.SaturnString;
import org.saturnclient.ui.components.SaturnToggle;
@@ -151,6 +152,26 @@ public class ConfigEditor extends SaturnUi {
)
);
break;
case HEX:
configScroll.draw(
new SaturnText(
propName.substring(0, 1).toUpperCase() +
propName.substring(1)
)
.setX(modX)
.setY(modY)
.setScale(0.8f)
);
configScroll.draw(
new SaturnHex(
(Property<Integer>) prop,
(rectWidth / 2) - 17,
modY,
70
)
);
break;
}
if (full) {
@@ -50,7 +50,7 @@ public class ModMenu extends SaturnUi {
tabsX = (width - tabSize) / 2;
draw(
new SaturnClickableImage(Textures.SETTINGS, () -> {
System.out.println("Pressed");
client.setScreen(new SaturnConfigEditor());
})
.setX(tabsX)
.setY(tabsY + 3)
@@ -0,0 +1,204 @@
package org.saturnclient.saturnclient.menus;
import java.util.Map;
import net.minecraft.text.Text;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.Textures;
import org.saturnclient.ui.components.SaturnFloat;
import org.saturnclient.ui.components.SaturnHex;
import org.saturnclient.ui.components.SaturnInteger;
import org.saturnclient.ui.components.SaturnString;
import org.saturnclient.ui.components.SaturnToggle;
import org.saturnclient.ui.widgets.SaturnScroll;
import org.saturnclient.ui.widgets.SaturnSprite;
import org.saturnclient.ui.widgets.SaturnText;
public class SaturnConfigEditor extends SaturnUi {
public SaturnConfigEditor() {
super(Text.of("Config editor"));
}
@SuppressWarnings("unchecked")
@Override
protected void init() {
int rectWidth = 330;
int rectHeight = 228;
int rectX = (width - rectWidth) / 2;
int rectY = (height - rectHeight + 15) / 2;
draw(
new SaturnSprite(Textures.SETTINGS_BG)
.setX(rectX)
.setY(rectY)
.setWidth(rectWidth)
.setHeight(rectHeight)
.setAnimations(SaturnClient.getAnimations())
);
int tabsX = (width - 43) / 2;
int tabsY = rectY - 17;
draw(
new SaturnSprite(Textures.TABS)
.setX(tabsX)
.setY(tabsY)
.setWidth(43)
.setHeight(15)
.setAnimations(SaturnClient.getAnimations())
);
SaturnScroll configScroll = new SaturnScroll();
int row = 0;
int col = 0;
for (Map.Entry<String, Property<?>> propEntry : SaturnClient.config
.getProperties()
.entrySet()) {
Property<?> prop = propEntry.getValue();
String propName = propEntry.getKey();
boolean full = isFull(prop);
if (full && col > 0) {
col = 0;
row++;
}
int modX = ((rectWidth / 2) - 17) * col;
int modY = 14 * row;
switch (prop.getType()) {
case BOOLEAN:
configScroll.draw(
new SaturnToggle((Property<Boolean>) prop)
.setX(modX)
.setY(modY)
);
configScroll.draw(
new SaturnText(
propName.substring(0, 1).toUpperCase() +
propName.substring(1)
)
.setX(modX + 18)
.setY(modY)
.setScale(0.8f)
);
break;
case INTEGER:
configScroll.draw(
new SaturnText(
propName.substring(0, 1).toUpperCase() +
propName.substring(1)
)
.setX(modX)
.setY(modY)
.setScale(0.8f)
);
configScroll.draw(
new SaturnInteger(
(Property<Integer>) prop,
(rectWidth / 2) - 17,
modY,
70
)
);
break;
case FLOAT:
configScroll.draw(
new SaturnText(
propName.substring(0, 1).toUpperCase() +
propName.substring(1)
)
.setX(modX)
.setY(modY)
.setScale(0.8f)
);
configScroll.draw(
new SaturnFloat(
(Property<Float>) prop,
(rectWidth / 2) - 17,
modY,
70
)
);
break;
case STRING:
configScroll.draw(
new SaturnText(
propName.substring(0, 1).toUpperCase() +
propName.substring(1)
)
.setX(modX)
.setY(modY)
.setScale(0.8f)
);
configScroll.draw(
new SaturnString(
(Property<String>) prop,
(rectWidth / 2) - 17,
modY,
70
)
);
break;
case HEX:
configScroll.draw(
new SaturnText(
propName.substring(0, 1).toUpperCase() +
propName.substring(1)
)
.setX(modX)
.setY(modY)
.setScale(0.8f)
);
configScroll.draw(
new SaturnHex(
(Property<Integer>) prop,
(rectWidth / 2) - 17,
modY,
70
)
);
break;
}
if (full) {
row++;
} else {
col++;
if (col > 1) {
col = 0;
row++;
}
}
}
draw(
configScroll
.setX(rectX + 17)
.setY(rectY + 10)
.setWidth(rectWidth - 17)
.setHeight(rectHeight - 10)
.setAnimations(SaturnClient.getAnimations())
);
super.init();
}
public static boolean isFull(Property<?> prop) {
switch (prop.getType()) {
case BOOLEAN:
return false;
default:
return true;
}
}
}
@@ -31,6 +31,11 @@ public class ArmorDisplay implements SaturnMod, HudMod {
75
);
public static Property<Integer> fgColor = config.property(
"Foreground color",
new Property<>(SaturnClient.WHITE, Property.PropertyType.HEX)
);
private boolean renderItem(DrawContext context, ItemStack item, int y) {
if (item.isEmpty()) {
return false;
@@ -52,7 +57,7 @@ public class ArmorDisplay implements SaturnMod, HudMod {
"" + (item.getMaxDamage() - item.getDamage()),
0,
0,
SaturnClient.WHITE,
fgColor.value,
false
);
@@ -21,6 +21,11 @@ public class Coordinates implements SaturnMod, HudMod {
);
private static ModDimensions dimensions = new ModDimensions(config);
public static Property<Integer> fgColor = config.property(
"Foreground color",
new Property<>(SaturnClient.WHITE, Property.PropertyType.HEX)
);
public Coordinates() {}
public void renderDummy(DrawContext context) {
@@ -33,7 +38,7 @@ public class Coordinates implements SaturnMod, HudMod {
playerX + " " + playerY + " " + playerZ,
0,
0,
SaturnClient.WHITE,
fgColor.value,
false
);
@@ -54,7 +59,7 @@ public class Coordinates implements SaturnMod, HudMod {
playerX + " " + playerY + " " + playerZ,
0,
0,
SaturnClient.WHITE,
fgColor.value,
false
);
}
@@ -108,7 +108,9 @@ public class SaturnFloat extends SaturnWidget {
0,
this.width,
this.height,
focused ? SaturnClient.COLOR : SaturnClient.getWhite(this.alpha)
focused
? SaturnClient.COLOR.value
: SaturnClient.getWhite(this.alpha)
);
int scrollOffset = getScrollOffset();
@@ -0,0 +1,146 @@
package org.saturnclient.ui.components;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.RenderLayer;
import org.lwjgl.glfw.GLFW;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.config.Property;
import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.SaturnWidget;
import org.saturnclient.ui.Textures;
public class SaturnHex extends SaturnWidget {
private String text = "#"; // Always starts with '#'
public Property<Integer> prop;
public int cursorPosition = 1; // After '#'
private final TextRenderer textRenderer = MinecraftClient.getInstance()
.textRenderer;
public SaturnHex(Property<Integer> prop, int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
this.prop = prop;
this.text = intToHex(prop.value); // Convert stored int to hex
this.height = textRenderer.fontHeight + 4;
this.scale = 0.8f;
}
@Override
public void click(int mouseX, int mouseY) {
cursorPosition = Math.min(7, text.length()); // Keep cursor inside hex length
}
@Override
public void charTyped(char chr) {
if (isHexChar(chr) && text.length() < 7) { // Limit to 6 hex digits + '#'
text =
text.substring(0, cursorPosition) +
chr +
text.substring(cursorPosition);
cursorPosition++;
if (text.length() == 7) { // Only update value when full hex is entered
prop.value = hexToInt(text);
}
}
}
@Override
public void keyPressed(int keyCode, int scanCode, int modifiers) {
if (keyCode == GLFW.GLFW_KEY_BACKSPACE && cursorPosition > 1) { // Prevent deleting '#'
text =
text.substring(0, cursorPosition - 1) +
text.substring(cursorPosition);
cursorPosition--;
} else if (keyCode == GLFW.GLFW_KEY_LEFT && cursorPosition > 1) {
cursorPosition--;
} else if (
keyCode == GLFW.GLFW_KEY_RIGHT && cursorPosition < text.length()
) {
cursorPosition++;
}
if (text.length() == 1) { // Reset if empty (keep '#')
text = "#";
cursorPosition = 1;
}
if (text.length() == 7) { // Update only when valid hex
prop.value = hexToInt(text);
}
}
@Override
public void render(
DrawContext context,
boolean hovering,
int mouseX,
int mouseY
) {
context.drawGuiTexture(
RenderLayer::getGuiTextured,
Textures.BUTTON_BORDER,
0,
0,
this.width,
this.height,
focused
? SaturnClient.COLOR.value
: SaturnClient.getWhite(this.alpha)
);
int textColor = focused ? 0xFFFFFF : 0xAAAAAA;
context.drawText(
textRenderer,
SaturnUi.text(text),
2,
2,
textColor,
false
);
if (focused) {
int cursorX =
2 +
textRenderer.getWidth(
SaturnUi.text(text.substring(0, cursorPosition))
);
context.fill(
cursorX,
2,
cursorX + 1,
textRenderer.fontHeight + 4,
0xFFFFFFFF
);
}
}
public void clearText() {
text = "#";
cursorPosition = 1;
prop.value = 0xFFFFFFFF; // Default white
}
private boolean isHexChar(char chr) {
return (
(chr >= '0' && chr <= '9') ||
(chr >= 'A' && chr <= 'F') ||
(chr >= 'a' && chr <= 'f')
);
}
public static int hexToInt(String hex) {
hex = hex.replace("#", "");
int rgb = Integer.parseInt(hex, 16);
return (0xFF << 24) | rgb;
}
public static String intToHex(int color) {
int rgb = color & 0xFFFFFF;
return String.format("#%06X", rgb).toLowerCase();
}
}
@@ -108,7 +108,9 @@ public class SaturnInteger extends SaturnWidget {
0,
this.width,
this.height,
focused ? SaturnClient.COLOR : SaturnClient.getWhite(this.alpha)
focused
? SaturnClient.COLOR.value
: SaturnClient.getWhite(this.alpha)
);
int scrollOffset = getScrollOffset();
@@ -30,7 +30,7 @@ public class SaturnModComp extends SaturnWidget {
boolean hovering_settings = settingsHovering(mouseX, mouseY);
int color = !hovering_settings && (enabled || hovering)
? SaturnClient.COLOR
? SaturnClient.COLOR.value
: SaturnClient.getWhite(alpha);
int size = 12;
@@ -47,7 +47,7 @@ public class SaturnModComp extends SaturnWidget {
20,
86,
20,
SaturnClient.COLOR
SaturnClient.COLOR.value
);
}
@@ -100,7 +100,7 @@ public class SaturnModComp extends SaturnWidget {
7,
7,
hovering_settings
? SaturnClient.COLOR
? SaturnClient.COLOR.value
: SaturnClient.getWhite(alpha)
);
}
@@ -92,7 +92,9 @@ public class SaturnString extends SaturnWidget {
0,
this.width,
this.height,
focused ? SaturnClient.COLOR : SaturnClient.getWhite(this.alpha)
focused
? SaturnClient.COLOR.value
: SaturnClient.getWhite(this.alpha)
);
int scrollOffset = getScrollOffset();
@@ -25,7 +25,7 @@ public class SaturnToggle extends SaturnWidget {
int mouseY
) {
int color = prop.value
? SaturnClient.COLOR
? SaturnClient.COLOR.value
: SaturnClient.getWhite(alpha);
int w = 13;
int h = 6;
@@ -40,7 +40,8 @@ public class SaturnButton extends SaturnWidget {
MinecraftClient minecraftClient = MinecraftClient.getInstance();
int hoverColor =
((int) (alpha * 255) << 24) | (SaturnClient.COLOR & 0x00FFFFFF);
((int) (alpha * 255) << 24) |
(SaturnClient.COLOR.value & 0x00FFFFFF);
if (background) {
RenderSystem.setShaderTexture(0, Textures.BUTTON);
@@ -14,7 +14,7 @@ public class SaturnClickableImage extends SaturnWidget {
public boolean selected = false;
public Consumer<SaturnClickableImage> onPress;
public int color = SaturnClient.getWhite(1.0f);
public int hoverColor = SaturnClient.COLOR;
public int hoverColor = SaturnClient.COLOR.value;
public SaturnClickableImage(
Identifier texture,
@@ -14,7 +14,7 @@ public class SaturnClickableSprite extends SaturnWidget {
public boolean selected = false;
public Consumer<SaturnClickableSprite> onPress;
public int color = SaturnClient.getWhite(1.0f);
public int hoverColor = SaturnClient.COLOR;
public int hoverColor = SaturnClient.COLOR.value;
public SaturnClickableSprite(
Identifier sprite,
@@ -47,7 +47,8 @@ public class SaturnImageButton extends SaturnButton {
super.render(context, hovering, mouseX, mouseY);
int hoverColor =
((int) (alpha * 255) << 24) | (SaturnClient.COLOR & 0x00FFFFFF);
((int) (alpha * 255) << 24) |
(SaturnClient.COLOR.value & 0x00FFFFFF);
context.drawTexture(
RenderLayer::getGuiTextured,