Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
720ee3d8bd | ||
|
|
b4b348a54c | ||
|
|
a3be72c443 | ||
|
|
1c553d14bf | ||
|
|
cd967a907c | ||
|
|
ba04c45b75 | ||
|
|
ecb07ce730 | ||
|
|
6cd10240fc | ||
|
|
d162db3464 |
@@ -8,11 +8,12 @@
|
|||||||
<b>Saturn Client is a free and open source Minecraft client</b>
|
<b>Saturn Client is a free and open source Minecraft client</b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
- Cloak rendering: `IIpho3nix` & `Dhyan Blum`
|
- Cloak rendering: `IIpho3nix` & `Dhyan Blum`
|
||||||
- Who Am I: `FokshaWasTaken`
|
- Who Am I: `FokshaWasTaken`
|
||||||
- Panton font (ui): `Ivan Petrov` & `Fontfabric`
|
|
||||||
- Panorama: https://www.planetminecraft.com/texture-pack/minecraft-cavesand-cliffs-part-ii-main-menu-panorama/
|
- Panorama: https://www.planetminecraft.com/texture-pack/minecraft-cavesand-cliffs-part-ii-main-menu-panorama/
|
||||||
|
|
||||||
If any of the code or assets are in your name and you want to remove them, please submit an issue, we are still in alpha to have any artists so we would also appreciate if you could help us make some cosmetics
|
If any of the code or assets are in your name and you want to remove them, please submit an issue, we are still in alpha to have any artists so we would also appreciate if you could help us make some cosmetics
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ yarn_mappings=1.21.4+build.7
|
|||||||
loader_version=0.16.10
|
loader_version=0.16.10
|
||||||
fabric_version=0.114.0+1.21.4
|
fabric_version=0.114.0+1.21.4
|
||||||
|
|
||||||
mod_version = 0.0.3-beta0
|
mod_version = 0.0.4-beta1
|
||||||
maven_group = org.saturnclient
|
maven_group = org.saturnclient
|
||||||
archives_base_name = saturnclient
|
archives_base_name = saturnclient
|
||||||
|
|
||||||
player_anim = 2.0.3+1.21.4
|
player_anim = 2.0.3+1.21.4
|
||||||
|
|||||||
@@ -1,26 +1,19 @@
|
|||||||
package org.saturnclient.modules;
|
package org.saturnclient.modules;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
|
|
||||||
import net.minecraft.client.font.TextRenderer;
|
|
||||||
import net.minecraft.client.render.RenderLayer;
|
|
||||||
|
|
||||||
import org.saturnclient.modules.mods.*;
|
import org.saturnclient.modules.mods.*;
|
||||||
import org.saturnclient.saturnclient.SaturnClient;
|
|
||||||
import org.saturnclient.saturnclient.menus.HudEditor;
|
|
||||||
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
|
|
||||||
import org.saturnclient.ui2.RenderScope;
|
|
||||||
|
|
||||||
public class ModManager {
|
public class ModManager {
|
||||||
public static Module[] MODS = {
|
public static Module[] MODS = {
|
||||||
new Crosshair(),
|
new Crosshair(),
|
||||||
new AutoSprint(),
|
new AutoSprint(),
|
||||||
new ArmorDisplay(),
|
new ArmorDisplay(),
|
||||||
new Fps(),
|
new Fps(),
|
||||||
new PotionDisplay(),
|
new PotionDisplay(),
|
||||||
new Coordinates(),
|
new Coordinates(),
|
||||||
new Freelook(),
|
new Freelook(),
|
||||||
new Keystrokes()
|
new Keystrokes()
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
@@ -31,39 +24,5 @@ public class ModManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
HudRenderCallback.EVENT.register((context, _o) -> {
|
|
||||||
TextRenderer textRenderer = SaturnClient.client.textRenderer;
|
|
||||||
|
|
||||||
if (textRenderer != null &&
|
|
||||||
!(SaturnClient.client.currentScreen instanceof HudEditor)) {
|
|
||||||
RenderScope renderScope = new RenderScope(context.getMatrices(),
|
|
||||||
((DrawContextAccessor) context).getVertexConsumers());
|
|
||||||
|
|
||||||
for (Module m : MODS) {
|
|
||||||
if (m instanceof HudMod && m.isEnabled()) {
|
|
||||||
ModDimensions dim = ((HudMod) m).getDimensions();
|
|
||||||
|
|
||||||
renderScope.matrices.push();
|
|
||||||
|
|
||||||
renderScope.matrices.translate(dim.x.value, (float) dim.y.value, 0);
|
|
||||||
|
|
||||||
renderScope.matrices.scale(dim.scale.value, dim.scale.value, 1.0f);
|
|
||||||
|
|
||||||
if (dim.renderBackground) {
|
|
||||||
renderScope.drawRoundedRectangle(0, 0, dim.width, dim.height, dim.radius.value, dim.bgColor.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
|
|
||||||
|
|
||||||
((HudMod) m).renderHud(renderScope);
|
|
||||||
|
|
||||||
renderScope.matrices.pop();
|
|
||||||
} else {
|
|
||||||
m.render(renderScope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package org.saturnclient.modules.mods.mixins;
|
||||||
|
|
||||||
|
import org.saturnclient.modules.HudMod;
|
||||||
|
import org.saturnclient.modules.ModDimensions;
|
||||||
|
import org.saturnclient.modules.ModManager;
|
||||||
|
import org.saturnclient.saturnclient.SaturnClient;
|
||||||
|
import org.saturnclient.saturnclient.menus.HudEditor;
|
||||||
|
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
|
||||||
|
import org.saturnclient.ui2.RenderScope;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import net.minecraft.client.font.TextRenderer;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.hud.InGameHud;
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.client.render.RenderTickCounter;
|
||||||
|
|
||||||
|
@Mixin(InGameHud.class)
|
||||||
|
public class RenderMixin {
|
||||||
|
@Inject(method = "renderChat", at = @At("TAIL"))
|
||||||
|
public void renderMods(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
|
||||||
|
TextRenderer textRenderer = SaturnClient.client.textRenderer;
|
||||||
|
|
||||||
|
if (textRenderer != null &&
|
||||||
|
!(SaturnClient.client.currentScreen instanceof HudEditor)) {
|
||||||
|
RenderScope renderScope = new RenderScope(context.getMatrices(),
|
||||||
|
((DrawContextAccessor) context).getVertexConsumers());
|
||||||
|
|
||||||
|
for (org.saturnclient.modules.Module m : ModManager.MODS) {
|
||||||
|
if (m instanceof HudMod && m.isEnabled()) {
|
||||||
|
ModDimensions dim = ((HudMod) m).getDimensions();
|
||||||
|
|
||||||
|
renderScope.matrices.push();
|
||||||
|
|
||||||
|
renderScope.matrices.translate(dim.x.value, (float) dim.y.value, 0);
|
||||||
|
|
||||||
|
renderScope.matrices.scale(dim.scale.value, dim.scale.value, 1.0f);
|
||||||
|
|
||||||
|
if (dim.renderBackground) {
|
||||||
|
renderScope.drawRoundedRectangle(0, 0, dim.width, dim.height, dim.radius.value,
|
||||||
|
dim.bgColor.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderScope.setRenderLayer(RenderLayer::getGuiTextured);
|
||||||
|
|
||||||
|
((HudMod) m).renderHud(renderScope);
|
||||||
|
|
||||||
|
renderScope.matrices.pop();
|
||||||
|
} else {
|
||||||
|
m.render(renderScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,9 +39,9 @@ public class SaturnClient implements ModInitializer {
|
|||||||
client = MinecraftClient.getInstance();
|
client = MinecraftClient.getInstance();
|
||||||
SaturnClientConfig.init();
|
SaturnClientConfig.init();
|
||||||
ModManager.init();
|
ModManager.init();
|
||||||
|
|
||||||
ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> ConfigManager.save());
|
ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> ConfigManager.save());
|
||||||
|
|
||||||
SpecialModelLoaderEvents.LOAD_SCOPE.register(() -> {
|
SpecialModelLoaderEvents.LOAD_SCOPE.register(() -> {
|
||||||
return (resourceManager, location) -> MOD_ID.equals(location.getNamespace());
|
return (resourceManager, location) -> MOD_ID.equals(location.getNamespace());
|
||||||
});
|
});
|
||||||
@@ -49,11 +49,12 @@ public class SaturnClient implements ModInitializer {
|
|||||||
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
|
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
|
||||||
if (screen != null && !(screen instanceof TitleMenu)) {
|
if (screen != null && !(screen instanceof TitleMenu)) {
|
||||||
if (screen instanceof SaturnScreen) {
|
if (screen instanceof SaturnScreen) {
|
||||||
((SaturnScreen) screen).draw(new ImageTexture(Textures.LOGO_TEXT_BIG).dimensions(180, 18).position(screen.width - 180 - 20, screen.height - 18 - 20));
|
((SaturnScreen) screen).draw(new ImageTexture(Textures.LOGO_TEXT_BIG).dimensions(180, 18)
|
||||||
|
.position(screen.width - 180 - 20, screen.height - 18 - 20));
|
||||||
} else {
|
} else {
|
||||||
ScreenEvents.afterRender(screen).register((screen1, context, mouseX, mouseY, tickDelta) -> {
|
ScreenEvents.afterRender(screen).register((screen1, context, mouseX, mouseY, tickDelta) -> {
|
||||||
RenderScope renderScope = new RenderScope(context.getMatrices(),
|
RenderScope renderScope = new RenderScope(context.getMatrices(),
|
||||||
((DrawContextAccessor) context).getVertexConsumers());
|
((DrawContextAccessor) context).getVertexConsumers());
|
||||||
|
|
||||||
int width = context.getScaledWindowWidth();
|
int width = context.getScaledWindowWidth();
|
||||||
int height = context.getScaledWindowHeight();
|
int height = context.getScaledWindowHeight();
|
||||||
@@ -71,7 +72,7 @@ public class SaturnClient implements ModInitializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
KeyInputHandler.register();
|
KeyInputHandler.register();
|
||||||
Emotes.initialize();
|
Emotes.initialize();
|
||||||
if (Auth.authenticate()) {
|
if (Auth.authenticate()) {
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ public class ConfigManager {
|
|||||||
|
|
||||||
// Generic method to store any type of property
|
// Generic method to store any type of property
|
||||||
public <T> Property<T> property(String name, Property<T> value) {
|
public <T> Property<T> property(String name, Property<T> value) {
|
||||||
System.out.println("Adding property: " + name);
|
|
||||||
currentMap.put(name, value);
|
currentMap.put(name, value);
|
||||||
loadProp(name, value);
|
loadProp(name, value);
|
||||||
return value;
|
return value;
|
||||||
@@ -98,7 +97,6 @@ public class ConfigManager {
|
|||||||
new String(Files.readAllBytes(configFile.toPath()))).getAsJsonObject();
|
new String(Files.readAllBytes(configFile.toPath()))).getAsJsonObject();
|
||||||
|
|
||||||
for (String namespace : properties.keySet()) {
|
for (String namespace : properties.keySet()) {
|
||||||
SaturnClient.LOGGER.info("Loading namespace: " + namespace);
|
|
||||||
JsonElement configElement = jsonObject.get(namespace);
|
JsonElement configElement = jsonObject.get(namespace);
|
||||||
|
|
||||||
if (configElement == null)
|
if (configElement == null)
|
||||||
@@ -120,8 +118,6 @@ public class ConfigManager {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static void loadProperties(JsonObject config, Map<String, Property<?>> propertyMap) {
|
private static void loadProperties(JsonObject config, Map<String, Property<?>> propertyMap) {
|
||||||
SaturnClient.LOGGER.info("Loading properties: " + propertyMap);
|
|
||||||
|
|
||||||
for (String propertyName : propertyMap.keySet()) {
|
for (String propertyName : propertyMap.keySet()) {
|
||||||
JsonElement c = config.get(propertyName);
|
JsonElement c = config.get(propertyName);
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ public class Property<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Property<T> copy() {
|
||||||
|
return new Property<>(this.value, this.type);
|
||||||
|
}
|
||||||
|
|
||||||
public static Property<Integer> font(int value) {
|
public static Property<Integer> font(int value) {
|
||||||
return select(value, "Default", "Inter", "Inter bold");
|
return select(value, "Default", "Inter", "Inter bold");
|
||||||
}
|
}
|
||||||
@@ -89,13 +93,17 @@ public class Property<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void next() {
|
public void next() {
|
||||||
if ((Integer) value < availableValues.length-1) setValue((Integer)value+1);
|
if ((Integer) value < availableValues.length - 1)
|
||||||
else setValue(0);
|
setValue((Integer) value + 1);
|
||||||
|
else
|
||||||
|
setValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prev() {
|
public void prev() {
|
||||||
if ((Integer) value > 0) setValue((Integer)value-1);
|
if ((Integer) value > 0)
|
||||||
else setValue(availableValues.length - 1);
|
setValue((Integer) value - 1);
|
||||||
|
else
|
||||||
|
setValue(availableValues.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelection(int selection) {
|
public void setSelection(int selection) {
|
||||||
@@ -156,12 +164,8 @@ public class Property<T> {
|
|||||||
return true;
|
return true;
|
||||||
if (value instanceof String && primitive.isString())
|
if (value instanceof String && primitive.isString())
|
||||||
return true;
|
return true;
|
||||||
|
if (type == PropertyType.HEX && primitive.isString())
|
||||||
// Check if JSON string represents a valid hex integer
|
return true;
|
||||||
if (value instanceof String && primitive.isString()) {
|
|
||||||
String str = primitive.getAsString();
|
|
||||||
return str.matches("0x[0-9A-Fa-f]+");
|
|
||||||
}
|
|
||||||
} else if (element.isJsonObject()) {
|
} else if (element.isJsonObject()) {
|
||||||
return isNamespace(value);
|
return isNamespace(value);
|
||||||
}
|
}
|
||||||
@@ -197,18 +201,58 @@ public class Property<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isKeyPressed() {
|
public boolean isKeyPressed() {
|
||||||
return (Integer) value == -1 ? false : GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(), (Integer) (Object) value) == GLFW.GLFW_PRESS;
|
return (Integer) value == -1 ? false
|
||||||
|
: GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(),
|
||||||
|
(Integer) (Object) value) == GLFW.GLFW_PRESS && SaturnClient.client.currentScreen == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean wasKeyPressed() {
|
public boolean wasKeyPressed() {
|
||||||
long window = SaturnClient.client.getWindow().getHandle();
|
boolean isPressed = this.isKeyPressed();
|
||||||
int key = (Integer) value;
|
wasPressedLastTick = isPressed && !wasPressedLastTick;
|
||||||
|
return wasPressedLastTick;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isPressed = key != -1 && GLFW.glfwGetKey(window, key) == GLFW.GLFW_PRESS;
|
@SuppressWarnings("unchecked")
|
||||||
|
public void load(String name, JsonElement element) {
|
||||||
|
if (element != null && element.isJsonObject()) {
|
||||||
|
JsonElement value = element.getAsJsonObject().get(name);
|
||||||
|
if (value != null) {
|
||||||
|
switch (this.getType()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
((Property<Boolean>) this).setValue(value.getAsBoolean());
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
JsonPrimitive primitive = value.getAsJsonPrimitive();
|
||||||
|
if (primitive.isNumber())
|
||||||
|
((Property<Integer>) this).setValue(value.getAsInt());
|
||||||
|
else if (primitive.isString())
|
||||||
|
((Property<Integer>) this).setValue(parseHexToInt(value.getAsString()));
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
((Property<Float>) this).setValue(value.getAsFloat());
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
((Property<String>) this).setValue(value.getAsString());
|
||||||
|
break;
|
||||||
|
case HEX:
|
||||||
|
((Property<Integer>) this).setValue(parseHexToInt(value.getAsString()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean wasJustPressed = isPressed && !wasPressedLastTick;
|
public static int parseHexToInt(String hex) {
|
||||||
wasPressedLastTick = isPressed;
|
hex = hex.replaceAll("#", "");
|
||||||
|
|
||||||
return wasJustPressed;
|
if (hex.length() == 6) {
|
||||||
|
hex = "FF" + hex;
|
||||||
|
} else if (hex.length() != 8) {
|
||||||
|
throw new IllegalArgumentException("Hex string must be 6 or 8 characters long");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) Long.parseLong(hex, 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,127 +3,75 @@ package org.saturnclient.saturnclient.config;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.saturnclient.saturnclient.SaturnClient;
|
import org.saturnclient.saturnclient.SaturnClient;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.JsonPrimitive;
|
|
||||||
|
|
||||||
public class ThemeManager {
|
public class ThemeManager {
|
||||||
|
|
||||||
private static File themeFile = new File(
|
private static File themeFile = new File(
|
||||||
SaturnClient.client.runDirectory,
|
SaturnClient.client.runDirectory,
|
||||||
"saturn.theme.json");
|
"saturn.theme.json");
|
||||||
private static Map<String, Map<String, Property<?>>> properties = new HashMap<>();
|
private static List<ThemeManager> theme = new ArrayList<>();
|
||||||
private static JsonObject cachedThemeJson = null;
|
private static JsonObject cachedThemeJson = null;
|
||||||
|
|
||||||
// private Map<String, Map<String, Property<?>>> states;
|
private Map<String, Map<String, Object>> states;
|
||||||
private Map<String, Property<?>> currentStyling;
|
private Map<String, Property<?>> currentStyling;
|
||||||
private String state;
|
|
||||||
private String[] states;
|
|
||||||
private String namespace;
|
private String namespace;
|
||||||
|
|
||||||
public ThemeManager(String namespace, String... states) {
|
public ThemeManager(String namespace, String... states) {
|
||||||
// this.states = new LinkedHashMap<>();
|
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
this.states = states;
|
this.states = new LinkedHashMap<>();
|
||||||
currentStyling = new LinkedHashMap<>();
|
this.currentStyling = new LinkedHashMap<>();
|
||||||
|
this.states.put(null, new LinkedHashMap<>());
|
||||||
properties.put(namespace, new LinkedHashMap<>());
|
|
||||||
|
|
||||||
for (String s : states) {
|
for (String s : states) {
|
||||||
properties.put(namespace+"@"+s, new LinkedHashMap<>());
|
this.states.put(s, new LinkedHashMap<>());
|
||||||
}
|
}
|
||||||
|
theme.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setState(String state) {
|
public void setState(String state) {
|
||||||
this.state = state;
|
for (Map.Entry<String, Object> tProp : states.get(state).entrySet()) {
|
||||||
if (this.state != null) {
|
currentStyling.get(tProp.getKey()).setValue(tProp.getValue());
|
||||||
for (Map.Entry<String, Property<?>> tProp : properties.get(namespace+"@"+state).entrySet()) {
|
|
||||||
currentStyling.get(tProp.getKey()).setValue(tProp.getValue().value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (Map.Entry<String, Property<?>> tProp : properties.get(namespace).entrySet()) {
|
|
||||||
Property<?> p = currentStyling.get(tProp.getKey());
|
|
||||||
if (p != null) p.setValue(tProp.getValue().value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyState(String state) {
|
public void applyState(String state) {
|
||||||
if (this.state != null) {
|
for (Map.Entry<String, Object> tProp : states.get(state).entrySet()) {
|
||||||
for (Map.Entry<String, Property<?>> tProp : properties.get(namespace+"@"+state).entrySet()) {
|
if (!states.get(null).get(tProp.getKey()).equals(tProp.getValue()))
|
||||||
Property<?> p = currentStyling.get(tProp.getKey());
|
currentStyling.get(tProp.getKey()).setValue(tProp.getValue());
|
||||||
Property<?> currProp = properties.get(namespace).get(tProp.getKey());
|
|
||||||
if (currProp != null && p.value.equals(currProp.value)) {
|
|
||||||
p.setValue(tProp.getValue().value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setState(state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic method to store any type of property
|
|
||||||
public <T> Property<T> property(String name, Property<T> prop) {
|
public <T> Property<T> property(String name, Property<T> prop) {
|
||||||
for (String state : states) {
|
for (Map.Entry<String, Map<String, Object>> state : this.states.entrySet()) {
|
||||||
Property<?> property = Property.from(prop.value);
|
Property<?> property = prop.copy();
|
||||||
properties.get(namespace+"@"+state).put(name, property);
|
if (cachedThemeJson == null) {
|
||||||
loadProp(state, name, property);
|
load();
|
||||||
|
}
|
||||||
|
String stateName = state.getKey();
|
||||||
|
property.load(name, cachedThemeJson.get(stateName != null ? namespace + "@" + stateName : namespace));
|
||||||
|
state.getValue().put(name, property.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadProp(null, name, prop);
|
|
||||||
properties.get(namespace).put(name, Property.from(prop.value));
|
|
||||||
currentStyling.put(name, prop);
|
currentStyling.put(name, prop);
|
||||||
|
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void propertyStateDefault(String state, String name, T value) {
|
public <T> void propertyStateDefault(String state, String name, T value) {
|
||||||
Property<?> prop = properties.get(namespace+"@"+state).get(name);
|
Property<?> prop = currentStyling.get(name).copy();
|
||||||
prop.setValue(value, value); // sets the current and default value
|
prop.setValue(value, value);
|
||||||
loadProp(state, name, prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> void loadProp(String state, String name, Property<T> prop) {
|
|
||||||
if (cachedThemeJson == null) {
|
if (cachedThemeJson == null) {
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
prop.load(name, cachedThemeJson.get(state != null ? namespace + "@" + state : namespace));
|
||||||
JsonElement element = cachedThemeJson.get(state != null ? namespace+"@"+state : namespace);
|
states.get(state).put(name, prop.value);
|
||||||
if (element != null && element.isJsonObject()) {
|
|
||||||
JsonObject theme = element.getAsJsonObject();
|
|
||||||
JsonElement value = theme.get(name);
|
|
||||||
if (value != null && prop.matchesJson(value)) {
|
|
||||||
switch (prop.getType()) {
|
|
||||||
case BOOLEAN:
|
|
||||||
((Property<Boolean>) prop).setValue(value.getAsBoolean());
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
((Property<Integer>) prop).setValue(value.getAsInt());
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
((Property<Float>) prop).setValue(value.getAsFloat());
|
|
||||||
break;
|
|
||||||
case STRING:
|
|
||||||
((Property<String>) prop).setValue(value.getAsString());
|
|
||||||
break;
|
|
||||||
case HEX:
|
|
||||||
((Property<Integer>) prop).setValue(value.getAsInt());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void load() {
|
public static void load() {
|
||||||
@@ -135,85 +83,11 @@ public class ThemeManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cachedThemeJson = JsonParser.parseString(
|
cachedThemeJson = JsonParser.parseString(
|
||||||
new String(Files.readAllBytes(themeFile.toPath()))).getAsJsonObject();
|
new String(Files.readAllBytes(themeFile.toPath()))).getAsJsonObject();
|
||||||
|
|
||||||
SaturnClient.LOGGER.info("Theme loaded");
|
SaturnClient.LOGGER.info("Theme loaded");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
SaturnClient.LOGGER.error("Error reading the theme file", e);
|
SaturnClient.LOGGER.error("Error reading the theme file", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void save() {
|
|
||||||
try {
|
|
||||||
SaturnClient.LOGGER.info("Starting to save theme...");
|
|
||||||
|
|
||||||
JsonObject jsonObject = new JsonObject();
|
|
||||||
|
|
||||||
// Iterate through all namespaces and their properties
|
|
||||||
for (String namespace : properties.keySet()) {
|
|
||||||
JsonObject namespaceTheme = new JsonObject();
|
|
||||||
Map<String, Property<?>> propertyMap = properties.get(namespace);
|
|
||||||
|
|
||||||
// Save properties for this namespace
|
|
||||||
saveProperties(namespaceTheme, propertyMap);
|
|
||||||
|
|
||||||
// Add the namespace theme to the main JSON object
|
|
||||||
jsonObject.add(namespace, namespaceTheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format the json so it can easily be edited
|
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
|
||||||
String formattedJson = gson.toJson(jsonObject);
|
|
||||||
|
|
||||||
// Write the JSON object to the theme file
|
|
||||||
Files.write(themeFile.toPath(), formattedJson.getBytes());
|
|
||||||
SaturnClient.LOGGER.info("Theme saved successfully.");
|
|
||||||
} catch (IOException e) {
|
|
||||||
SaturnClient.LOGGER.error("Error saving the theme file", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static void saveProperties(JsonObject theme, Map<String, Property<?>> propertyMap) {
|
|
||||||
// Iterate through each property in the namespace
|
|
||||||
for (String propertyName : propertyMap.keySet()) {
|
|
||||||
Property<?> property = propertyMap.get(propertyName);
|
|
||||||
JsonElement propertyValue = null;
|
|
||||||
|
|
||||||
if (property.getType() == Property.PropertyType.NAMESPACE) {
|
|
||||||
// Handle nested namespace
|
|
||||||
JsonObject nestedTheme = new JsonObject();
|
|
||||||
Map<String, Property<?>> nestedProperties = (Map<String, Property<?>>) property.value;
|
|
||||||
saveProperties(nestedTheme, nestedProperties);
|
|
||||||
propertyValue = nestedTheme;
|
|
||||||
} else {
|
|
||||||
// Convert the property value based on its type
|
|
||||||
switch (property.getType()) {
|
|
||||||
case BOOLEAN:
|
|
||||||
propertyValue = new JsonPrimitive((Boolean) property.value);
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
propertyValue = new JsonPrimitive((Integer) property.value);
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
propertyValue = new JsonPrimitive((Float) property.value);
|
|
||||||
break;
|
|
||||||
case STRING:
|
|
||||||
propertyValue = new JsonPrimitive((String) property.value);
|
|
||||||
break;
|
|
||||||
case HEX:
|
|
||||||
propertyValue = new JsonPrimitive((Integer) property.value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SaturnClient.LOGGER.warn(
|
|
||||||
"Unknown property type for: " + propertyName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyValue != null) {
|
|
||||||
theme.add(propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class KeyInputHandler {
|
|||||||
client.setScreen(new ShiftMenu());
|
client.setScreen(new ShiftMenu());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SaturnClientConfig.openEmoteWheel.wasKeyPressed()) {
|
if (SaturnClientConfig.openEmoteWheel.wasKeyPressed() && client.currentScreen == null) {
|
||||||
client.setScreen(new EmoteWheel());
|
client.setScreen(new EmoteWheel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public class Toggle extends Element {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||||
|
theme.setState(null);
|
||||||
|
|
||||||
if (prop.value) {
|
if (prop.value) {
|
||||||
theme.setState("enabled");
|
theme.setState("enabled");
|
||||||
}
|
}
|
||||||
@@ -38,8 +40,6 @@ public class Toggle extends Element {
|
|||||||
renderScope.drawRoundedRectangle(0, 0, width, height, cornerRadius.value, bgColor.value);
|
renderScope.drawRoundedRectangle(0, 0, width, height, cornerRadius.value, bgColor.value);
|
||||||
|
|
||||||
renderScope.drawRoundedRectangle(prop.value ? 30 : 0, 0, 30, 30, 30, fgColor.value);
|
renderScope.drawRoundedRectangle(prop.value ? 30 : 0, 0, 30, 30, 30, fgColor.value);
|
||||||
|
|
||||||
theme.setState(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
@@ -5,7 +5,8 @@
|
|||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"client": [
|
"client": [
|
||||||
"CameraMixin",
|
"CameraMixin",
|
||||||
"EntityMixin"
|
"EntityMixin",
|
||||||
|
"RenderMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|||||||