From 0391cdd1cabcd72ca2ead937490ba9d4261bb5b5 Mon Sep 17 00:00:00 2001 From: FullRisk Date: Mon, 13 Jul 2026 20:27:49 +0200 Subject: [PATCH] Reworked ENTIRE UI (God help me) and cleaned up MyScreen.java (from 700 lines to 400) --- .../java/de/fullrisk/citrusDev/Config.java | 1 + .../java/de/fullrisk/citrusDev/UI/MainUI.java | 434 +++++++++++ .../de/fullrisk/citrusDev/UI/MyScreen.java | 730 ------------------ .../de/fullrisk/citrusDev/UI/QuestsPanel.java | 6 +- .../citrusDev/UIHelper/ModuleRow.java | 24 +- .../citrusDev/UIHelper/ModuleRows.java | 82 ++ .../citrusDev/UIHelper/ModuleSettings.java | 117 +++ .../citrusDev/UIHelper/SettingsControls.java | 12 +- .../citrusDev/client/CitrusDevClient.java | 4 +- 9 files changed, 664 insertions(+), 746 deletions(-) create mode 100644 src/main/java/de/fullrisk/citrusDev/UI/MainUI.java delete mode 100644 src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java create mode 100644 src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java create mode 100644 src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java diff --git a/src/main/java/de/fullrisk/citrusDev/Config.java b/src/main/java/de/fullrisk/citrusDev/Config.java index 6231e1b..91ca383 100644 --- a/src/main/java/de/fullrisk/citrusDev/Config.java +++ b/src/main/java/de/fullrisk/citrusDev/Config.java @@ -44,6 +44,7 @@ public class Config { public boolean effectsNameEnabled = true; public float panelBlur = 5.0f; + public boolean darkMode = false; private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); diff --git a/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java b/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java new file mode 100644 index 0000000..c66d033 --- /dev/null +++ b/src/main/java/de/fullrisk/citrusDev/UI/MainUI.java @@ -0,0 +1,434 @@ +package de.fullrisk.citrusDev.UI; + +import de.fullrisk.citrusDev.Config; +import de.fullrisk.citrusDev.UIHelper.*; +import io.wispforest.owo.ui.base.BaseOwoScreen; +import io.wispforest.owo.ui.component.UIComponents; +import io.wispforest.owo.ui.container.FlowLayout; +import io.wispforest.owo.ui.container.UIContainers; +import io.wispforest.owo.ui.core.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FontDescription; +import net.minecraft.resources.Identifier; +import net.minecraft.sounds.SoundEvents; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class MainUI extends BaseOwoScreen { + + public static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five"); + + public static Surface PANEL_SURFACE = buildPanelSurface(); + public static Surface GLASS_PANEL = buildGlassSurface(); + public static Surface DISABLED = buildDisabledSurface(); + public static Surface FLAT = buildFlatSurface(); + + private static Surface buildPanelSurface() { + float blur = Config.get().panelBlur; + int fill = Config.get().darkMode ? 0x601c1c1c : 0x40FFFFFF; + if (blur <= 0f) return Surface.flat(fill).and(Surface.outline(0x64de4b)); + return Surface.blur(blur, 15f).and(Surface.flat(fill)).and(Surface.outline(0x64de4b)); + } + + private static Surface buildGlassSurface() { + int fill = Config.get().darkMode ? 0x70282828 : 0x40FFFFFF; + return Surface.blur(5f, 15f).and(Surface.flat(fill)).and(Surface.outline(0x64de4b)); + } + + private static Surface buildDisabledSurface() { + int fill = Config.get().darkMode ? 0x30050505 : 0x401c1c1c; + return Surface.blur(5f, 15f).and(Surface.flat(fill)); + } + + private static Surface buildFlatSurface() { + int fill = Config.get().darkMode ? 0x601c1c1c : 0x40FFFFFF; + return Surface.blur(5f, 15f).and(Surface.flat(fill)); + } + + public static void rebuildSurfaces() { + PANEL_SURFACE = buildPanelSurface(); + GLASS_PANEL = buildGlassSurface(); + DISABLED = buildDisabledSurface(); + FLAT = buildFlatSurface(); + if (panelRef != null) panelRef.surface(PANEL_SURFACE); + } + + private static int text() { return Config.get().darkMode ? 0xFFd0d4da : 0xFFb0b6c0; } + private static int bright() { return 0xFFFFFF; } + private static int tabText() { return 0xCCCCCC; } + + public static final int PANEL_WIDTH = 320; + public static final int PANEL_HEIGHT = 190; + public static final int INNER_WIDTH = PANEL_WIDTH - 4; + public static final int INNER_HEIGHT = PANEL_HEIGHT - 4; + public static final int NAVBAR_HEIGHT = 24; + public static final int DIVIDER_SIZE = 1; + public static final int SIDEBAR_WIDTH = 44; + public static final int ROW_HEIGHT = INNER_HEIGHT - NAVBAR_HEIGHT - DIVIDER_SIZE; + public static final int CONTENT_WIDTH = INNER_WIDTH - SIDEBAR_WIDTH - DIVIDER_SIZE; + + private static final Map MODULE_TAGS = Map.of( + "FPS", new String[]{"HUD"}, + "Keystrokes", new String[]{"HUD"}, + "Coordinates", new String[]{"HUD"}, + "Fullbright", new String[]{"World"}, + "Hitbox", new String[]{"Combat"}, + "Effects", new String[]{"HUD"} + ); + private static final String[] CATEGORIES = {"ALL", "HUD", "Combat", "World"}; + + private record TabDef(String label, Runnable onClick) {} + + private FlowLayout content; + private final String initialModule; + private static FlowLayout panelRef; + private String activeCategory = "ALL"; + private static String searchText = ""; + private FlowLayout moduleListContainer; + private List allModuleRows; + + public MainUI() { this(null); } + + public MainUI(String initialModule) { + super(Component.literal("Citrus Dev")); + this.initialModule = initialModule; + Minecraft.getInstance().getSoundManager().play( + SimpleSoundInstance.forUI(SoundEvents.UI_TOAST_IN, 1.5F, 2) + ); + } + + @Override + protected OwoUIAdapter createAdapter() { + return OwoUIAdapter.create(this, UIContainers::verticalFlow); + } + + @Override + protected void build(FlowLayout rootComponent) { + rootComponent.gap(0); + rootComponent.horizontalAlignment(HorizontalAlignment.CENTER).verticalAlignment(VerticalAlignment.CENTER); + + FlowLayout panel = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); + panelRef = panel; + panel.gap(0); + panel.padding(Insets.of(2)); + panel.horizontalAlignment(HorizontalAlignment.CENTER).verticalAlignment(VerticalAlignment.CENTER); + panel.horizontalSizing(Sizing.fixed(0)); + panel.verticalSizing(Sizing.fixed(0)); + panel.horizontalSizing().animate(300, Easing.CUBIC, Sizing.fixed(PANEL_WIDTH)).forwards(); + panel.verticalSizing().animate(300, Easing.CUBIC, Sizing.fixed(PANEL_HEIGHT)).forwards(); + panel.surface(PANEL_SURFACE); + + FlowLayout navbar = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(NAVBAR_HEIGHT)); + navbar.verticalAlignment(VerticalAlignment.CENTER); + navbar.horizontalAlignment(HorizontalAlignment.CENTER); + navbar.gap(16); + + var logo = UIComponents.texture(Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/citrus-logo.png"), 0, 0, 30, 30, 30, 30); + logo.positioning(Positioning.absolute(4, (NAVBAR_HEIGHT - 30) / 2)); + navbar.child(logo); + + for (TabDef tab : List.of( + new TabDef("general", () -> switchToContent(c -> buildGeneralPanel(c))), + new TabDef("quests", () -> switchToContent(c -> QuestsPanel.build(c, CONTENT_WIDTH, ROW_HEIGHT))), + new TabDef("settings", () -> switchToContent(this::buildSettingsPanel)) + )) { + navbar.child(makeTab(tab.label(), tab.onClick())); + } + panel.child(navbar); + + FlowLayout navDividerSpacer = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(DIVIDER_SIZE)); + panel.child(navDividerSpacer); + + FlowLayout navDivider = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(DIVIDER_SIZE)); + navDivider.surface(Surface.flat(0x80FFFFFF)); + navDivider.positioning(Positioning.absolute(0, NAVBAR_HEIGHT)); + panel.child(navDivider); + + FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(ROW_HEIGHT)); + row.gap(0); + row.child(buildSidebar()); + + content = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH), Sizing.fixed(ROW_HEIGHT)); + content.gap(2); + content.padding(Insets.of(4)); + content.horizontalAlignment(HorizontalAlignment.CENTER); + content.verticalAlignment(VerticalAlignment.TOP); + row.child(content); + panel.child(row); + + var version = new ScalableLabel(Component.literal("Citrus-Dev v2.0")); + version.horizontalTextAlignment(HorizontalAlignment.RIGHT); + version.verticalTextAlignment(VerticalAlignment.BOTTOM); + version.horizontalSizing(Sizing.fixed(CONTENT_WIDTH - 8)); + version.verticalSizing(Sizing.fixed(12)); + version.positioning(Positioning.relative(100, 100)); + version.scale().set(new ScaleValue(0.7f)); + panel.child(version); + + rootComponent.child(panel); + + if (initialModule != null) openModuleByKey(initialModule); + else buildGeneralPanel(content); + } + + private void switchToContent(java.util.function.Consumer builder) { + content.clearChildren(); + content.horizontalAlignment(HorizontalAlignment.CENTER); + content.verticalAlignment(VerticalAlignment.TOP); + builder.accept(content); + } + + private FlowLayout makeTab(String text, Runnable onClick) { + FlowLayout tab = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); + tab.verticalAlignment(VerticalAlignment.CENTER); + tab.horizontalAlignment(HorizontalAlignment.CENTER); + tab.padding(Insets.of(2, 0, 2, 2)); + tab.gap(2); + + var label = UIComponents.label(Component.literal(text).withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(tabText())).shadow(true); + tab.child(label); + + FlowLayout underline = UIContainers.horizontalFlow(Sizing.fixed(Math.max(text.length() * 6, 10)), Sizing.fixed(1)); + underline.surface(Surface.flat(0x00FFFFFF)); + tab.child(underline); + + tab.mouseEnter().subscribe(() -> { label.color(Color.ofRgb(bright())); underline.surface(Surface.flat(0xFFFFFFFF)); }); + tab.mouseLeave().subscribe(() -> { label.color(Color.ofRgb(tabText())); underline.surface(Surface.flat(0x00FFFFFF)); }); + tab.mouseDown().subscribe((click, doubled) -> { + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)); + onClick.run(); + return true; + }); + return tab; + } + + // --- Sidebar --- + private static int sidebarBtnFill() { return Config.get().darkMode ? 0x803a3a3a : 0x80FFFFFF; } + private static int sidebarBtnHover() { return Config.get().darkMode ? 0xA0505050 : 0xA0FFFFFF; } + private static int sidebarBtnOutline() { return Config.get().darkMode ? 0xFF888888 : 0xFFFFFFFF; } + private static int sidebarBtnHoverOutline() { return Config.get().darkMode ? 0xFFcccccc : 0xFFFFFFFF; } + + private FlowLayout buildSidebar() { + FlowLayout sidebar = UIContainers.verticalFlow(Sizing.fixed(SIDEBAR_WIDTH), Sizing.fixed(ROW_HEIGHT)); + sidebar.horizontalAlignment(HorizontalAlignment.CENTER); + sidebar.verticalAlignment(VerticalAlignment.TOP); + sidebar.padding(Insets.of(4)); + sidebar.gap(2); + + sidebar.child(makeSidebarButton("-", 430)); + sidebar.child(makeSidebarButton("+", 400)); + sidebar.child(UIComponents.spacer()); + + // Edit button + FlowLayout editButton = UIContainers.verticalFlow(Sizing.fixed(36), Sizing.fixed(18)); + editButton.horizontalAlignment(HorizontalAlignment.CENTER); + editButton.verticalAlignment(VerticalAlignment.CENTER); + editButton.surface(Surface.flat(sidebarBtnFill()).and(Surface.outline(sidebarBtnOutline()))); + editButton.child(UIComponents.texture(Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/edit.png"), 0, 0, 16, 16, 16, 16)); + editButton.mouseEnter().subscribe(() -> editButton.surface(Surface.flat(sidebarBtnHover()).and(Surface.outline(sidebarBtnHoverOutline())))); + editButton.mouseLeave().subscribe(() -> editButton.surface(Surface.flat(sidebarBtnFill()).and(Surface.outline(sidebarBtnOutline())))); + editButton.mouseDown().subscribe((click, doubled) -> { + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)); + DraggableHud.setEditMode(true); + Minecraft.getInstance().setScreen(null); + return true; + }); + sidebar.child(editButton); + + return sidebar; + } + + private ScalableButton makeSidebarButton(String symbol, int animateDelay) { + var button = new ScalableButton(Component.literal(symbol), btn -> + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)), + sidebarBtnFill(), sidebarBtnHover(), sidebarBtnOutline(), sidebarBtnHoverOutline(), 1); + button.horizontalSizing(Sizing.fixed(36)); + button.verticalSizing(Sizing.fixed(18)); + button.scale().set(new ScaleValue(0f)); + button.scale().animate(animateDelay, Easing.CUBIC, new ScaleValue(1f)).forwards(); + button.mouseEnter().subscribe(() -> button.scale().animate(120, Easing.CUBIC, new ScaleValue(1.1f)).forwards()); + button.mouseLeave().subscribe(() -> button.scale().animate(120, Easing.CUBIC, new ScaleValue(1.0f)).forwards()); + return button; + } + + // --- Category bar --- + private FlowLayout buildCategoryBar(Runnable onFilterChanged) { + FlowLayout bar = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(18)); + bar.gap(4); + bar.verticalAlignment(VerticalAlignment.CENTER); + bar.horizontalAlignment(HorizontalAlignment.LEFT); + + for (String cat : CATEGORIES) { + boolean isActive = cat.equals(activeCategory); + FlowLayout catButton = UIContainers.verticalFlow(Sizing.fixed(Math.max(cat.length() * 7 + 8, 30)), Sizing.fixed(16)); + catButton.verticalAlignment(VerticalAlignment.CENTER); + catButton.horizontalAlignment(HorizontalAlignment.CENTER); + catButton.padding(Insets.of(2, 0, 2, 0)); + catButton.surface(isActive + ? Surface.flat(0x6064de4b).and(Surface.outline(0x64de4b)) + : Surface.flat(0x30FFFFFF).and(Surface.outline(0x64de4b))); + + var catLabel = UIComponents.label(Component.literal(cat).withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(isActive ? bright() : tabText())) + .horizontalTextAlignment(HorizontalAlignment.CENTER); + catButton.child(catLabel); + + catButton.mouseEnter().subscribe(() -> { if (!cat.equals(activeCategory)) catButton.surface(Surface.flat(0x50FFFFFF).and(Surface.outline(0xFFFFFFFF))); }); + catButton.mouseLeave().subscribe(() -> { if (!cat.equals(activeCategory)) catButton.surface(Surface.flat(0x30FFFFFF).and(Surface.outline(0x64de4b))); }); + catButton.mouseDown().subscribe((click, doubled) -> { + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)); + activeCategory = cat; + onFilterChanged.run(); + return true; + }); + bar.child(catButton); + } + + bar.child(UIComponents.spacer()); + + FlowLayout searchWrapper = UIContainers.horizontalFlow(Sizing.fixed(90), Sizing.fixed(16)); + searchWrapper.verticalAlignment(VerticalAlignment.CENTER); + searchWrapper.horizontalAlignment(HorizontalAlignment.RIGHT); + searchWrapper.padding(Insets.of(0, 4, 0, 4)); + searchWrapper.surface(FLAT.and(Surface.outline(0x64de4b))); + + var searchBox = UIComponents.textBox(Sizing.fixed(82)); + searchBox.setValue(searchText); + searchBox.setTextColor(text()); + searchBox.setHint(Component.literal("Search...").withStyle(s -> s.withColor(tabText()))); + searchBox.setFilter(s -> true); + searchBox.setBordered(false); + searchBox.onChanged().subscribe(newText -> { + searchText = newText; + rebuildModuleList(); + }); + searchWrapper.child(searchBox); + + bar.child(searchWrapper); + + return bar; + } + + private boolean matchesFilter(String moduleName) { + if (!activeCategory.equals("ALL")) { + String[] tags = MODULE_TAGS.get(moduleName); + if (tags == null || !Arrays.asList(tags).contains(activeCategory)) return false; + } + return searchText.isEmpty() || moduleName.toLowerCase().contains(searchText.toLowerCase()); + } + + // --- General panel --- + private void buildGeneralPanel(FlowLayout content) { + content.child(buildCategoryBar(() -> { content.clearChildren(); buildGeneralPanel(content); })); + + allModuleRows = ModuleRows.buildAll(this::openModuleByKey); + moduleListContainer = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); + moduleListContainer.gap(4); + moduleListContainer.verticalAlignment(VerticalAlignment.TOP); + moduleListContainer.horizontalAlignment(HorizontalAlignment.CENTER); + rebuildModuleList(); + + content.child(UIContainers.verticalScroll(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(ROW_HEIGHT - 24), moduleListContainer)); + } + + private void rebuildModuleList() { + moduleListContainer.clearChildren(); + for (ModuleRows.Entry entry : allModuleRows) { + if (matchesFilter(entry.name())) moduleListContainer.child(entry.row()); + } + } + + // --- Settings panel --- + private void buildSettingsPanel(FlowLayout content) { + FlowLayout rows = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); + rows.gap(8); + rows.verticalAlignment(VerticalAlignment.TOP); + rows.horizontalAlignment(HorizontalAlignment.LEFT); + + // Blur slider + rows.child(makeSettingRow("Panel Blur", SettingsControls.makeSlider( + FLAT, 80, 0.0, 15.0, Config.get().panelBlur, + value -> (int) value + "px", + value -> { Config.get().panelBlur = (float) (double) value; Config.get().save(); rebuildSurfaces(); } + ))); + + // Dark mode toggle + rows.child(makeSettingRow("Dark Mode", SettingsControls.makeCheckbox( + FLAT, GLASS_PANEL, Config.get().darkMode, value -> { + Config.get().darkMode = value; + Config.get().save(); + rebuildSurfaces(); + Minecraft.getInstance().setScreen(new MainUI()); + } + ))); + + content.child(rows); + } + + private FlowLayout makeSettingRow(String label, FlowLayout control) { + FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(16)); + row.verticalAlignment(VerticalAlignment.CENTER); + row.horizontalAlignment(HorizontalAlignment.LEFT); + row.gap(4); + row.child(UIComponents.label(Component.literal(label).withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(text()))); + row.child(UIComponents.spacer()); + row.child(control); + return row; + } + + // --- Module settings --- + private void openModuleSettings(String title, List rows) { + content.clearChildren(); + content.horizontalAlignment(HorizontalAlignment.LEFT); + content.verticalAlignment(VerticalAlignment.TOP); + + // Header with back button + FlowLayout header = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); + header.verticalAlignment(VerticalAlignment.CENTER); + header.horizontalAlignment(HorizontalAlignment.LEFT); + header.gap(4); + header.child(SettingsControls.makeTextButton(FLAT, "<", () -> switchToContent(this::buildGeneralPanel))); + header.child(UIComponents.label(Component.literal(title).withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(bright()))); + content.child(header); + + // Setting rows + FlowLayout rowsContainer = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); + rowsContainer.gap(1); + rowsContainer.verticalAlignment(VerticalAlignment.TOP); + rowsContainer.horizontalAlignment(HorizontalAlignment.LEFT); + + for (ModuleSettings.SettingRow setting : rows) { + FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(16)); + row.verticalAlignment(VerticalAlignment.CENTER); + row.horizontalAlignment(HorizontalAlignment.LEFT); + row.gap(4); + row.child(UIComponents.label(Component.literal(setting.label()).withStyle(s -> s.withFont(new FontDescription.Resource(MC_FIVE)))) + .color(Color.ofRgb(text()))); + row.child(UIComponents.spacer()); + row.child(setting.control()); + rowsContainer.child(row); + } + + content.child(UIContainers.verticalScroll(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(ROW_HEIGHT - 24), rowsContainer)); + } + + private void openModuleByKey(String key) { + switch (key) { + case "FPS" -> openModuleSettings("FPS", ModuleSettings.fps()); + case "Key" -> openModuleSettings("Keystrokes", ModuleSettings.keystrokes()); + case "Coords" -> openModuleSettings("Coordinates", ModuleSettings.coords()); + case "Hitbox" -> openModuleSettings("Hitbox", ModuleSettings.hitbox(this::openModuleByKey)); + case "Effects" -> openModuleSettings("Effects", ModuleSettings.effects()); + default -> buildGeneralPanel(content); + } + } + + @Override + public boolean isPauseScreen() { return false; } +} \ No newline at end of file diff --git a/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java b/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java deleted file mode 100644 index 94270af..0000000 --- a/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java +++ /dev/null @@ -1,730 +0,0 @@ -package de.fullrisk.citrusDev.UI; - -import de.fullrisk.citrusDev.Config; -import de.fullrisk.citrusDev.UIHelper.*; -import io.wispforest.owo.ui.base.BaseOwoScreen; -import io.wispforest.owo.ui.component.UIComponents; -import io.wispforest.owo.ui.container.FlowLayout; -import io.wispforest.owo.ui.container.UIContainers; -import io.wispforest.owo.ui.core.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.sounds.SimpleSoundInstance; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.FontDescription; -import net.minecraft.resources.Identifier; -import net.minecraft.sounds.SoundEvents; -import de.fullrisk.citrusDev.client.PlaytimeTracker; - -import java.util.List; -import java.util.Set; -import java.util.concurrent.Flow; - -import static de.fullrisk.citrusDev.UI.Module_FPS.fpsContainer; -import static de.fullrisk.citrusDev.UI.Module_FPS.toggle; - -public class MyScreen extends BaseOwoScreen { - - static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five"); - - static Surface PANEL_SURFACE = buildPanelSurface(); - - static Surface GLASS_PANEL = Surface.blur(5f, 15f) - .and(Surface.flat(0x40FFFFFF)) - .and(Surface.outline(0x64de4b)); - - private static Surface DISABLED = Surface.blur(5f, 15f) - .and(Surface.flat(0x401c1c1c)); - - private static Surface FLAT = Surface.blur(5f, 15f) - .and(Surface.flat(0x40FFFFFF)); - - private static Surface buildPanelSurface() { - float blur = Config.get().panelBlur; - if (blur <= 0f) { - return Surface.flat(0x40FFFFFF) - .and(Surface.outline(0x64de4b)); - } - return Surface.blur(blur, 15f) - .and(Surface.flat(0x40FFFFFF)) - .and(Surface.outline(0x64de4b)); - } - - public static void rebuildSurfaces() { - PANEL_SURFACE = buildPanelSurface(); - if (panelRef != null) { - panelRef.surface(PANEL_SURFACE); - } - } - - private static final int PANEL_WIDTH = 250; - private static final int PANEL_HEIGHT = 150; - private static final int INNER_WIDTH = PANEL_WIDTH - 4; - private static final int INNER_HEIGHT = PANEL_HEIGHT - 4; - private static final int NAVBAR_HEIGHT = 24; - private static final int DIVIDER_SIZE = 1; - private static final int SIDEBAR_WIDTH = 34; - private static final int ROW_HEIGHT = INNER_HEIGHT - NAVBAR_HEIGHT - DIVIDER_SIZE; - private static final int CONTENT_WIDTH = INNER_WIDTH - SIDEBAR_WIDTH - DIVIDER_SIZE; - - private record TabDef(String label, Runnable onClick) {} - private record SettingRow(String label, FlowLayout control) {} - private record QuestData(String title, String description, int requiredPlaytime) { - boolean isUnlocked() { - return PlaytimeTracker.getCurrentPlaytimeSeconds() >= requiredPlaytime; - } - } - - private FlowLayout content; - private final String initialModule; - private static FlowLayout panelRef; - - - public MyScreen() { - this(null); - } - - public MyScreen(String initialModule) { - super(Component.literal("Citrus Dev")); - this.initialModule = initialModule; - Minecraft.getInstance().getSoundManager().play( - SimpleSoundInstance.forUI(SoundEvents.UI_TOAST_IN, 1.5F, 2) - ); - } - - @Override - protected OwoUIAdapter createAdapter() { - return OwoUIAdapter.create(this, UIContainers::verticalFlow); - } - - @Override - protected void build(FlowLayout rootComponent) { - rootComponent.gap(0); - rootComponent - .horizontalAlignment(HorizontalAlignment.CENTER) - .verticalAlignment(VerticalAlignment.CENTER); - - FlowLayout panel = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); - panelRef = panel; - panel.gap(0); - panel.padding(Insets.of(2)); - panel.horizontalAlignment(HorizontalAlignment.CENTER); - panel.verticalAlignment(VerticalAlignment.CENTER); - panel.horizontalSizing(Sizing.fixed(0)); - panel.verticalSizing(Sizing.fixed(0)); - panel.horizontalSizing().animate(300, Easing.CUBIC, Sizing.fixed(PANEL_WIDTH)).forwards(); - panel.verticalSizing().animate(300, Easing.CUBIC, Sizing.fixed(PANEL_HEIGHT)).forwards(); - panel.surface(PANEL_SURFACE); - - FlowLayout navbar = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(NAVBAR_HEIGHT)); - buildNavbar(navbar); - panel.child(navbar); - - FlowLayout navDivider = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(DIVIDER_SIZE)); - navDivider.surface(Surface.flat(0x80FFFFFF)); - panel.child(navDivider); - - FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(INNER_WIDTH), Sizing.fixed(ROW_HEIGHT)); - row.gap(0); - - FlowLayout sidebar = buildSidebar(); - row.child(sidebar); - - content = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH), Sizing.fixed(ROW_HEIGHT)); - content.gap(2); - content.padding(Insets.of(4)); - content.horizontalAlignment(HorizontalAlignment.CENTER); - content.verticalAlignment(VerticalAlignment.TOP); - row.child(content); - - panel.child(row); - - FlowLayout sidebarDivider = UIContainers.verticalFlow(Sizing.fixed(DIVIDER_SIZE), Sizing.fixed(INNER_HEIGHT)); - sidebarDivider.surface(Surface.flat(0x80FFFFFF)); - sidebarDivider.positioning(Positioning.absolute(SIDEBAR_WIDTH, 0)); - panel.child(sidebarDivider); - - var version = new ScalableLabel(Component.literal("Citrus-Dev v2.0")); - version.horizontalTextAlignment(HorizontalAlignment.RIGHT); - version.verticalTextAlignment(VerticalAlignment.BOTTOM); - version.horizontalSizing(Sizing.fixed(202)); - version.verticalSizing(Sizing.fixed(12)); - version.positioning(Positioning.relative(125, 100)); - version.scale().set(new ScaleValue(0.7f)); - panel.child(version); - - rootComponent.child(panel); - - if (initialModule != null) { - openModuleByKey(initialModule); - } else { - buildGeneralPanel(content); - } - } - - private void buildNavbar(FlowLayout navbar) { - navbar.horizontalAlignment(HorizontalAlignment.RIGHT); - navbar.verticalAlignment(VerticalAlignment.CENTER); - navbar.padding(Insets.of(0, 0, 0, 24)); - navbar.gap(16); - navbar.child(UIComponents.texture( - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/citrus-logo.png"), - 0, 0, 30, 30, 30, 30 - )).horizontalAlignment(HorizontalAlignment.LEFT); - - List tabs = List.of( - new TabDef("general", () -> { - content.clearChildren(); - content.horizontalAlignment(HorizontalAlignment.CENTER); - content.verticalAlignment(VerticalAlignment.TOP); - buildGeneralPanel(content); - }), - new TabDef("quests", () -> { - content.clearChildren(); - content.horizontalAlignment(HorizontalAlignment.CENTER); - content.verticalAlignment(VerticalAlignment.TOP); - QuestsPanel.build(content, CONTENT_WIDTH, ROW_HEIGHT); - }), - new TabDef("settings", () -> { - content.clearChildren(); - content.horizontalAlignment(HorizontalAlignment.CENTER); - content.verticalAlignment(VerticalAlignment.TOP); - buildSettingsPanel(content); - }) - ); - - for (TabDef tab : tabs) { - navbar.child(makeTab(tab.label(), tab.onClick())); - } - } - - private FlowLayout makeTab(String text, Runnable onClick) { - FlowLayout tab = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); - tab.verticalAlignment(VerticalAlignment.CENTER); - tab.horizontalAlignment(HorizontalAlignment.CENTER); - tab.padding(Insets.of(2, 0, 2, 2)); - tab.gap(2); - - var label = UIComponents.label(Component.literal(text) - .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) - .color(Color.ofRgb(0xCCCCCC)) - .shadow(true);; - tab.child(label); - - int underlineWidth = Math.max(text.length() * 6, 10); - FlowLayout underline = UIContainers.horizontalFlow(Sizing.fixed(underlineWidth), Sizing.fixed(1)); - underline.surface(Surface.flat(0x00FFFFFF)); - tab.child(underline); - - tab.mouseEnter().subscribe(() -> { - label.color(Color.ofRgb(0xFFFFFF)); - underline.surface(Surface.flat(0xFFFFFFFF)); - }); - tab.mouseLeave().subscribe(() -> { - label.color(Color.ofRgb(0xCCCCCC)); - underline.surface(Surface.flat(0x00FFFFFF)); - }); - - tab.mouseDown().subscribe((click, doubled) -> { - Minecraft.getInstance().getSoundManager().play( - SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2) - ); - onClick.run(); - return true; - }); - - return tab; - } - - private FlowLayout buildSidebar() { - FlowLayout sidebar = UIContainers.verticalFlow(Sizing.fixed(SIDEBAR_WIDTH), Sizing.fixed(ROW_HEIGHT)); - sidebar.horizontalAlignment(HorizontalAlignment.CENTER); - sidebar.verticalAlignment(VerticalAlignment.TOP); - sidebar.padding(Insets.of(4)); - sidebar.gap(2); - - sidebar.child(makeSidebarButton("-", 430)); - sidebar.child(makeSidebarButton("+", 400)); - - sidebar.child(UIComponents.spacer()); - - FlowLayout editButton = UIContainers.verticalFlow(Sizing.fixed(20), Sizing.fixed(20)); - editButton.horizontalAlignment(HorizontalAlignment.CENTER); - editButton.verticalAlignment(VerticalAlignment.CENTER); - editButton.surface(Surface.flat(0x80FFFFFF).and(Surface.outline(0xFFFFFFFF))); - editButton.child(UIComponents.texture( - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/edit.png"), - 0, 0, 16, 16, 16, 16 - )); - - editButton.mouseEnter().subscribe(() -> - editButton.surface(Surface.flat(0xA0FFFFFF).and(Surface.outline(0xFFFFFFFF)))); - editButton.mouseLeave().subscribe(() -> - editButton.surface(Surface.flat(0x80FFFFFF).and(Surface.outline(0xFFFFFFFF)))); - - editButton.mouseDown().subscribe((click, doubled) -> { - Minecraft.getInstance().getSoundManager().play( - SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2) - ); - DraggableHud.setEditMode(true); - Minecraft.getInstance().setScreen(null); - return true; - }); - - sidebar.child(editButton); - - return sidebar; - } - - private ScalableButton makeSidebarButton(String symbol, int animateDelay) { - var button = new ScalableButton(Component.literal(symbol), btn -> { - Minecraft.getInstance().getSoundManager().play( - SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2) - ); - }, - 0x80FFFFFF, - 0xA0FFFFFF, - 0xFFFFFFFF, - 0xFFFFFFFF, - 1 - ); - button.horizontalSizing(Sizing.fixed(20)); - button.verticalSizing(Sizing.fixed(20)); - - button.scale().set(new ScaleValue(0f)); - button.scale().animate(animateDelay, Easing.CUBIC, new ScaleValue(1f)).forwards(); - - button.mouseEnter().subscribe(() -> button.scale().animate(120, Easing.CUBIC, new ScaleValue(1.1f)).forwards()); - button.mouseLeave().subscribe(() -> button.scale().animate(120, Easing.CUBIC, new ScaleValue(1.0f)).forwards()); - - return button; - } - - private void buildGeneralPanel(FlowLayout content) { - - FlowLayout fpsRow = ModuleRow.build( - GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/fps.png"), - 18, 18, - MC_FIVE, - "FPS", - "Displays your FPS", - new ModuleRow.ToggleState() { - public boolean get() { return toggle; } - public void set(boolean value) { toggle = value; } - }, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"), - () -> { - Config.get().lastModule = "FPS"; - Config.get().save(); - openModuleSettings("FPS", fpsModuleSettings()); - }, - "Module Enabled", "FPS counter is now active", - "Module Disabled", "FPS counter is now inactive" - ); - - FlowLayout keyStrokesRow = ModuleRow.build( - GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/keystrokes.png"), - 24, 24, - MC_FIVE, - "Keystrokes", - "Current Key Presses", - new ModuleRow.ToggleState() { - public boolean get() { return Module_KeyStrokes.isEnabled(); } - public void set(boolean value) { Module_KeyStrokes.setEnabled(value); } - }, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"), - () -> { - Config.get().lastModule = "Key"; - Config.get().save(); - openModuleSettings("Key", keyStrokesSettings()); - }, - "Module Enabled", "Keystrokes is now active", - "Module Disabled", "KeyStrokes is now inactive" - ); - - FlowLayout coordinatesRow = ModuleRow.build( - GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("minecraft", "textures/item/map.png"), - 18, 18, - MC_FIVE, - "Coordinates", - "Shows your Position", - new ModuleRow.ToggleState() { - public boolean get() { return Module_Coords.toggle; } - public void set(boolean value) { - Module_Coords.toggle = value; - Config.get().coordsEnabled = value; - Config.get().save(); - } - }, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"), - () -> { - Config.get().lastModule = "Coords"; - Config.get().save(); - openModuleSettings("Coords", CoordsSettings()); - }, - "Module Enabled", "Keystrokes is now active", - "Module Disabled", "Keystrokes is now inactive" - ); - - FlowLayout fullbrightRow = ModuleRow.build( - GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/fullbright.png"), - 18, 18, - MC_FIVE, - "Fullbright", - "Max brightness", - new ModuleRow.ToggleState() { - public boolean get() { return Module_Fullbright.isEnabled(); } - public void set(boolean value) { Module_Fullbright.setEnabled(value); } - }, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"), - () -> { - Config.get().lastModule = "Fullbright"; - Config.get().save(); - }, - "Module Enabled", "Fullbright is now active", - "Module Disabled", "Fullbright is now inactive" - ); - - FlowLayout hitboxRow = ModuleRow.build( - GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/block_culling_file.png"), - 18, 12, - MC_FIVE, - "hitbox", - "Customize hitboxes", - new ModuleRow.ToggleState() { - public boolean get() { return Module_Hitbox.isEnabled(); } - public void set(boolean value) { Module_Hitbox.setEnabled(value); } - }, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"), - () -> { - Config.get().lastModule = "Hitbox"; - Config.get().save(); - openModuleSettings("Hitbox", hitboxSettings()); - }, - "Module Enabled", "Hitbox color is now active", - "Module Disabled", "Hitbox color is now inactive" - ); - - FlowLayout effectsRow = ModuleRow.build( - GLASS_PANEL, DISABLED, FLAT, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/effect.png"), - 18, 18, - MC_FIVE, - "Effects", - "Shows active effects", - new ModuleRow.ToggleState() { - public boolean get() { return Module_Effects.isEnabled(); } - public void set(boolean value) { Module_Effects.setEnabled(value); } - }, - Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"), - () -> { - Config.get().lastModule = "Effects"; - Config.get().save(); - openModuleSettings("Effects", effectsSettings()); - }, - "Module Enabled", "Effects display is now active", - "Module Disabled", "Effects display is now inactive" - ); - - FlowLayout rowsContainer = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); - rowsContainer.gap(4); - rowsContainer.verticalAlignment(VerticalAlignment.TOP); - rowsContainer.horizontalAlignment(HorizontalAlignment.CENTER); - - rowsContainer.child(effectsRow); - rowsContainer.child(hitboxRow); - rowsContainer.child(coordinatesRow); - rowsContainer.child(keyStrokesRow); - rowsContainer.child(fpsRow); - rowsContainer.child(fullbrightRow); - - var scrollArea = UIContainers.verticalScroll( - Sizing.fixed(CONTENT_WIDTH - 8), - Sizing.fixed(ROW_HEIGHT- 8), - rowsContainer - ); - - content.child(scrollArea); - - } - - - private void buildSettingsPanel(FlowLayout content) { - FlowLayout rowsContainer = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); - rowsContainer.gap(8); - rowsContainer.verticalAlignment(VerticalAlignment.TOP); - rowsContainer.horizontalAlignment(HorizontalAlignment.LEFT); - rowsContainer.padding(Insets.of(0)); - - FlowLayout blurSlider = SettingsControls.makeSlider( - FLAT, - 80, - 0.0, 15.0, - Config.get().panelBlur, - value -> (int) value + "px", - value -> { - Config.get().panelBlur = (float) (double) value; - Config.get().save(); - rebuildSurfaces(); - } - ); - - FlowLayout blurRow = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(16)); - blurRow.verticalAlignment(VerticalAlignment.CENTER); - blurRow.horizontalAlignment(HorizontalAlignment.LEFT); - blurRow.padding(Insets.of(0)); - blurRow.gap(4); - blurRow.child(UIComponents.label(Component.literal("Panel Blur") - .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) - .color(Color.ofRgb(0xFF5c5c66))); - blurRow.child(UIComponents.spacer()); - blurRow.child(blurSlider); - rowsContainer.child(blurRow); - - content.child(rowsContainer); - } - - private void openModuleSettings(String title, List rows) { - content.clearChildren(); - - content.horizontalAlignment(HorizontalAlignment.LEFT); - content.verticalAlignment(VerticalAlignment.TOP); - - FlowLayout header = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); - header.verticalAlignment(VerticalAlignment.CENTER); - header.horizontalAlignment(HorizontalAlignment.LEFT); - header.gap(4); - - header.child(SettingsControls.makeTextButton(FLAT, "<", () -> { - content.clearChildren(); - content.horizontalAlignment(HorizontalAlignment.CENTER); - content.verticalAlignment(VerticalAlignment.TOP); - buildGeneralPanel(content); - })); - - header.child(UIComponents.label(Component.literal(title) - .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) - .color(Color.ofRgb(0x80FFFFFF))); - - content.child(header); - - FlowLayout rowsContainer = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); - rowsContainer.gap(1); - rowsContainer.verticalAlignment(VerticalAlignment.TOP); - rowsContainer.horizontalAlignment(HorizontalAlignment.LEFT); - rowsContainer.padding(Insets.of(0)); - - for (SettingRow row : rows) { - FlowLayout settingRow = makeSettingRow(row); - settingRow.verticalSizing(Sizing.fixed(16)); - rowsContainer.child(settingRow); - } - - var scrollArea = UIContainers.verticalScroll( - Sizing.fixed(CONTENT_WIDTH - 8), - Sizing.fixed(ROW_HEIGHT - 24), - rowsContainer - ); - content.child(scrollArea); - } - - private void openModuleByKey(String key) { - switch (key) { - case "FPS" -> openModuleSettings("FPS", fpsModuleSettings()); - case "Key" -> openModuleSettings("Keystrokes", keyStrokesSettings()); - case "Coords" -> openModuleSettings("Coordinates", CoordsSettings()); - case "Hitbox" -> openModuleSettings("Hitbox", hitboxSettings()); - case "Effects" -> openModuleSettings("Effects", effectsSettings()); - default -> buildGeneralPanel(content); - } - } - - private FlowLayout makeSettingRow(SettingRow setting) { - FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(16)); - row.verticalAlignment(VerticalAlignment.CENTER); - row.horizontalAlignment(HorizontalAlignment.LEFT); - row.padding(Insets.of(0)); - row.gap(4); - - row.child(UIComponents.label(Component.literal(setting.label()) - .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) - .color(Color.ofRgb(0xFF5c5c66))); - row.child(UIComponents.spacer()); - row.child(setting.control()); - - return row; - } - - private List fpsModuleSettings() { - List positionStates = List.of( - new SettingsControls.ButtonState("L-TOP", () -> Module_FPS.setPosition(1, 1)), - new SettingsControls.ButtonState("R-TOP", () -> Module_FPS.setPosition(99, 1)), - new SettingsControls.ButtonState("R-BOTTOM", () -> Module_FPS.setPosition(99, 99)), - new SettingsControls.ButtonState("L-BOTTOM", () -> Module_FPS.setPosition(1, 99)) - ); - - FlowLayout paddingSlider = SettingsControls.makeSlider( - FLAT, - 80, - 0.0, 15.0, - Config.get().fpsSize, - value -> (int) value + "px", - value -> Module_FPS.setFpsPadding((int) value) - ); - - - int currentIndex = positionIndex(Config.get().fpsX, Config.get().fpsY); - - return List.of( - new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, currentIndex)), - new SettingRow("", SettingsControls.makeSectionHeader(CONTENT_WIDTH - 8, "Display Options")), - new SettingRow("Padding", paddingSlider) - - ); - } - - private List keyStrokesSettings() { - List positionStates = List.of( - new SettingsControls.ButtonState("L-TOP", () -> Module_KeyStrokes.setPosition(1, 1)), - new SettingsControls.ButtonState("R-TOP", () -> Module_KeyStrokes.setPosition(99, 1)), - new SettingsControls.ButtonState("R-BOTTOM", () -> Module_KeyStrokes.setPosition(99, 99)), - new SettingsControls.ButtonState("L-BOTTOM", () -> Module_KeyStrokes.setPosition(1, 99)) - ); - - FlowLayout sizeSlider = SettingsControls.makeSlider( - FLAT, - 80, - 10.0, 30.0, - Config.get().keySize, - value -> (int) value + "px", - value -> Module_KeyStrokes.setKeySize((int) value) - ); - - int currentIndex = positionIndex(Config.get().keyX, Config.get().keyY); - - return List.of( - new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, currentIndex)), - new SettingRow("Size", sizeSlider) - ); - } - - private List CoordsSettings() { - List positionStates = List.of( - new SettingsControls.ButtonState("L-TOP", () -> Module_Coords.setPosition(1, 1)), - new SettingsControls.ButtonState("R-TOP", () -> Module_Coords.setPosition(99, 1)), - new SettingsControls.ButtonState("R-BOTTOM", () -> Module_Coords.setPosition(99, 99)), - new SettingsControls.ButtonState("L-BOTTOM", () -> Module_Coords.setPosition(1, 99)) - ); - - int currentIndex = positionIndex(Config.get().fpsX, Config.get().fpsY); - - FlowLayout biomeCheckbox = SettingsControls.makeCheckbox( - FLAT, - GLASS_PANEL, - Module_Coords.isBiomeEnabled(), - Module_Coords::setBiomeEnabled - ); - - FlowLayout sizeSlider = SettingsControls.makeSlider( - FLAT, - 80, - 0.0, 15.0, - Config.get().coordsP, - value -> (int) value + "px", - value -> Module_Coords.setCoordsPadding((int) value) - ); - - return List.of( - new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, currentIndex)), - new SettingRow("Show Biome", biomeCheckbox), - new SettingRow("Padding", sizeSlider) - ); - } - - private List hitboxSettings() { - - FlowLayout enabledCheckbox = SettingsControls.makeCheckbox( - FLAT, - GLASS_PANEL, - Module_Hitbox.isEnabled(), - value -> { - Module_Hitbox.setEnabled(value); - openModuleSettings("Hitbox", hitboxSettings()); - } - ); - - List rows = new java.util.ArrayList<>(); - rows.add(new SettingRow("Custom Color", enabledCheckbox)); - - if (Module_Hitbox.isEnabled()) { - FlowLayout hueSlider = SettingsControls.makeSlider( - FLAT, - 80, - 0.0, 360.0, - Module_Hitbox.getHue(), - value -> (int) (double) value + "°", - value -> Module_Hitbox.setHue((int) (double) value) - ); - rows.add(new SettingRow("Color", hueSlider)); - } - - return rows; - } - - private List effectsSettings() { - List positionStates = List.of( - new SettingsControls.ButtonState("L-TOP", () -> Module_Effects.setPosition(1, 1)), - new SettingsControls.ButtonState("R-TOP", () -> Module_Effects.setPosition(99, 1)), - new SettingsControls.ButtonState("R-BOTTOM", () -> Module_Effects.setPosition(99, 99)), - new SettingsControls.ButtonState("L-BOTTOM", () -> Module_Effects.setPosition(1, 99)) - ); - - int currentIndex = positionIndex(Config.get().effectsX, Config.get().effectsY); - - FlowLayout bgCheck = SettingsControls.makeCheckbox( - FLAT, - GLASS_PANEL, - Module_Effects.isBackgroundEnabled(), - Module_Effects::setBackgroundEnabled - ); - - FlowLayout timerCheck = SettingsControls.makeCheckbox( - FLAT, - GLASS_PANEL, - Module_Effects.isTimerEnabled(), - Module_Effects::setTimerEnabled - ); - - FlowLayout nameCheck = SettingsControls.makeCheckbox( - FLAT, - GLASS_PANEL, - Module_Effects.isNameEnabled(), - Module_Effects::setNameEnabled - ); - - return List.of( - new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, currentIndex)), - new SettingRow("Show Background", bgCheck), - new SettingRow("Show Timer", timerCheck), - new SettingRow("Show Name", nameCheck) - ); - } - - private int positionIndex(int x, int y) { - boolean right = x > 50; - boolean bottom = y > 50; - if (!right && !bottom) return 0; - if (right && !bottom) return 1; - if (right && bottom) return 2; - return 3; - } - - @Override - public boolean isPauseScreen() { - return false; - } -} \ No newline at end of file diff --git a/src/main/java/de/fullrisk/citrusDev/UI/QuestsPanel.java b/src/main/java/de/fullrisk/citrusDev/UI/QuestsPanel.java index 4dd2b2a..04a8407 100644 --- a/src/main/java/de/fullrisk/citrusDev/UI/QuestsPanel.java +++ b/src/main/java/de/fullrisk/citrusDev/UI/QuestsPanel.java @@ -81,7 +81,7 @@ public class QuestsPanel { statusBar.padding(Insets.of(4)); statusBar.verticalAlignment(VerticalAlignment.CENTER); statusBar.horizontalAlignment(HorizontalAlignment.LEFT); - statusBar.surface(MyScreen.GLASS_PANEL); + statusBar.surface(MainUI.GLASS_PANEL); LabelComponent playtimeLabel = UIComponents.label(Component.literal(formatPlaytime(playtime))); playtimeLabel.color(Color.ofRgb(0xFFFFFF)); @@ -112,7 +112,7 @@ public class QuestsPanel { summaryRow.child(UIComponents.label( Component.literal("quests " + unlockedCount + "/" + quests.size()) - .withStyle(style -> style.withFont(new FontDescription.Resource(MyScreen.MC_FIVE)))) + .withStyle(style -> style.withFont(new FontDescription.Resource(MainUI.MC_FIVE)))) .color(Color.ofRgb(0xFF5c5c66))); content.child(summaryRow); @@ -201,7 +201,7 @@ public class QuestsPanel { textStack.verticalAlignment(VerticalAlignment.TOP); var titleLabel = UIComponents.label(Component.literal(quest.title()) - .withStyle(style -> style.withFont(new FontDescription.Resource(MyScreen.MC_FIVE)))) + .withStyle(style -> style.withFont(new FontDescription.Resource(MainUI.MC_FIVE)))) .color(Color.ofRgb(unlocked ? 0xFFFFFF : 0x797b86)); textStack.child(titleLabel); diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRow.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRow.java index 4f6cbf8..781fcfa 100644 --- a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRow.java +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRow.java @@ -1,5 +1,6 @@ package de.fullrisk.citrusDev.UIHelper; +import de.fullrisk.citrusDev.Config; import io.wispforest.owo.ui.component.UIComponents; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.UIContainers; @@ -18,6 +19,17 @@ public class ModuleRow { void set(boolean value); } + private static int titleColor(boolean enabled) { + if (Config.get().darkMode) { + return enabled ? 0xffffff : 0xFF8a8e96; + } + return enabled ? 0xffffff : 0xFFaab0b8; + } + + private static int descColor() { + return Config.get().darkMode ? 0xFFa0a4aa : 0xFF6a6e76; + } + public static FlowLayout build( Surface enabledSurface, Surface disabledSurface, @@ -58,12 +70,12 @@ public class ModuleRow { Component.literal(title) .withStyle(style -> style.withFont(new FontDescription.Resource(titleFont))) ); - titleLabel.color(Color.ofRgb(state.get() ? 0xffffff : 0x797b86)); + titleLabel.color(Color.ofRgb(titleColor(state.get()))); textStack.child(titleLabel); textStack.child(UIComponents.label(Component.literal(description)) - .color(Color.ofRgb(0xFF5c5c66)) - .maxWidth(130)); + .color(Color.ofRgb(descColor())) + .maxWidth(190)); row.child(textStack); row.child(UIComponents.spacer()); @@ -78,7 +90,7 @@ public class ModuleRow { boolean newState = !state.get(); state.set(newState); - titleLabel.color(Color.ofRgb(newState ? 0xffffff : 0x797b86)); + titleLabel.color(Color.ofRgb(titleColor(newState))); row.surface(newState ? enabledSurface : disabledSurface); if (newState) { @@ -93,9 +105,9 @@ public class ModuleRow { return true; }); - row.horizontalSizing().animate(150, Easing.CUBIC, Sizing.fixed(200)).forwards(); + row.horizontalSizing().animate(150, Easing.CUBIC, Sizing.fixed(260)).forwards(); row.verticalSizing().animate(150, Easing.CUBIC, Sizing.fixed(35)).forwards(); return row; } -} \ No newline at end of file +} diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java new file mode 100644 index 0000000..85ddf7f --- /dev/null +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleRows.java @@ -0,0 +1,82 @@ +package de.fullrisk.citrusDev.UIHelper; + +import de.fullrisk.citrusDev.Config; +import de.fullrisk.citrusDev.UI.*; +import io.wispforest.owo.ui.container.FlowLayout; +import net.minecraft.resources.Identifier; + +import java.util.List; +import java.util.function.Consumer; + +import static de.fullrisk.citrusDev.UI.MainUI.*; + +public class ModuleRows { + + public record Entry(String name, FlowLayout row) {} + + private static final Identifier SETTINGS_ICON = Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"); + + public static List buildAll(Consumer openSettingsByKey) { + return List.of( + entry("Effects", ModuleRow.build( + GLASS_PANEL, DISABLED, FLAT, + Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/effect.png"), 18, 18, MC_FIVE, + "Effects", "Shows active effects", + toggleState(Module_Effects::isEnabled, Module_Effects::setEnabled), + SETTINGS_ICON, () -> { Config.get().lastModule = "Effects"; Config.get().save(); openSettingsByKey.accept("Effects"); }, + "Module Enabled", "Effects display is now active", + "Module Disabled", "Effects display is now inactive")), + entry("Hitbox", ModuleRow.build( + GLASS_PANEL, DISABLED, FLAT, + Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/block_culling_file.png"), 18, 12, MC_FIVE, + "Hitbox", "Customize hitboxes", + toggleState(Module_Hitbox::isEnabled, Module_Hitbox::setEnabled), + SETTINGS_ICON, () -> { Config.get().lastModule = "Hitbox"; Config.get().save(); openSettingsByKey.accept("Hitbox"); }, + "Module Enabled", "Hitbox color is now active", + "Module Disabled", "Hitbox color is now inactive")), + entry("Coordinates", ModuleRow.build( + GLASS_PANEL, DISABLED, FLAT, + Identifier.fromNamespaceAndPath("minecraft", "textures/item/map.png"), 18, 18, MC_FIVE, + "Coordinates", "Shows your Position", + toggleState(Module_Coords::isEnabled, Module_Coords::setEnabled), + SETTINGS_ICON, () -> { Config.get().lastModule = "Coords"; Config.get().save(); openSettingsByKey.accept("Coords"); }, + "Module Enabled", "Coordinates is now active", + "Module Disabled", "Coordinates is now inactive")), + entry("Keystrokes", ModuleRow.build( + GLASS_PANEL, DISABLED, FLAT, + Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/keystrokes.png"), 24, 24, MC_FIVE, + "Keystrokes", "Current Key Presses", + toggleState(Module_KeyStrokes::isEnabled, Module_KeyStrokes::setEnabled), + SETTINGS_ICON, () -> { Config.get().lastModule = "Key"; Config.get().save(); openSettingsByKey.accept("Key"); }, + "Module Enabled", "Keystrokes is now active", + "Module Disabled", "KeyStrokes is now inactive")), + entry("FPS", ModuleRow.build( + GLASS_PANEL, DISABLED, FLAT, + Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/fps.png"), 18, 18, MC_FIVE, + "FPS", "Displays your FPS", + toggleState(Module_FPS::isEnabled, Module_FPS::setEnabled), + SETTINGS_ICON, () -> { Config.get().lastModule = "FPS"; Config.get().save(); openSettingsByKey.accept("FPS"); }, + "Module Enabled", "FPS counter is now active", + "Module Disabled", "FPS counter is now inactive")), + entry("Fullbright", ModuleRow.build( + GLASS_PANEL, DISABLED, FLAT, + Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/fullbright.png"), 18, 18, MC_FIVE, + "Fullbright", "Max brightness", + toggleState(Module_Fullbright::isEnabled, Module_Fullbright::setEnabled), + SETTINGS_ICON, () -> { Config.get().lastModule = "Fullbright"; Config.get().save(); }, + "Module Enabled", "Fullbright is now active", + "Module Disabled", "Fullbright is now inactive")) + ); + } + + private static Entry entry(String name, FlowLayout row) { + return new Entry(name, row); + } + + private static ModuleRow.ToggleState toggleState(java.util.function.BooleanSupplier get, java.util.function.Consumer set) { + return new ModuleRow.ToggleState() { + public boolean get() { return get.getAsBoolean(); } + public void set(boolean value) { set.accept(value); } + }; + } +} diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java new file mode 100644 index 0000000..afa0981 --- /dev/null +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/ModuleSettings.java @@ -0,0 +1,117 @@ +package de.fullrisk.citrusDev.UIHelper; + +import de.fullrisk.citrusDev.Config; +import de.fullrisk.citrusDev.UI.Module_Coords; +import de.fullrisk.citrusDev.UI.Module_Effects; +import de.fullrisk.citrusDev.UI.Module_FPS; +import de.fullrisk.citrusDev.UI.Module_Hitbox; +import de.fullrisk.citrusDev.UI.Module_KeyStrokes; +import io.wispforest.owo.ui.container.FlowLayout; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import static de.fullrisk.citrusDev.UI.MainUI.*; + +public class ModuleSettings { + + public record SettingRow(String label, FlowLayout control) {} + + public static int positionIndex(int x, int y) { + boolean right = x > 50; + boolean bottom = y > 50; + if (!right && !bottom) return 0; + if (right && !bottom) return 1; + if (right && bottom) return 2; + return 3; + } + + public static List fps() { + var positionStates = List.of( + new SettingsControls.ButtonState("L-TOP", () -> Module_FPS.setPosition(1, 1)), + new SettingsControls.ButtonState("R-TOP", () -> Module_FPS.setPosition(99, 1)), + new SettingsControls.ButtonState("R-BOTTOM", () -> Module_FPS.setPosition(99, 99)), + new SettingsControls.ButtonState("L-BOTTOM", () -> Module_FPS.setPosition(1, 99)) + ); + + FlowLayout paddingSlider = SettingsControls.makeSlider( + FLAT, 80, 0.0, 15.0, Config.get().fpsSize, + value -> (int) value + "px", + value -> Module_FPS.setFpsPadding((int) value) + ); + + return List.of( + new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, positionIndex(Config.get().fpsX, Config.get().fpsY))), + new SettingRow("", SettingsControls.makeSectionHeader(CONTENT_WIDTH - 8, "Display Options")), + new SettingRow("Padding", paddingSlider) + ); + } + + public static List keystrokes() { + var positionStates = List.of( + new SettingsControls.ButtonState("L-TOP", () -> Module_KeyStrokes.setPosition(1, 1)), + new SettingsControls.ButtonState("R-TOP", () -> Module_KeyStrokes.setPosition(99, 1)), + new SettingsControls.ButtonState("R-BOTTOM", () -> Module_KeyStrokes.setPosition(99, 99)), + new SettingsControls.ButtonState("L-BOTTOM", () -> Module_KeyStrokes.setPosition(1, 99)) + ); + + FlowLayout sizeSlider = SettingsControls.makeSlider( + FLAT, 80, 10.0, 30.0, Config.get().keySize, + value -> (int) value + "px", + value -> Module_KeyStrokes.setKeySize((int) value) + ); + + return List.of( + new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, positionIndex(Config.get().keyX, Config.get().keyY))), + new SettingRow("Size", sizeSlider) + ); + } + + public static List coords() { + var positionStates = List.of( + new SettingsControls.ButtonState("L-TOP", () -> Module_Coords.setPosition(1, 1)), + new SettingsControls.ButtonState("R-TOP", () -> Module_Coords.setPosition(99, 1)), + new SettingsControls.ButtonState("R-BOTTOM", () -> Module_Coords.setPosition(99, 99)), + new SettingsControls.ButtonState("L-BOTTOM", () -> Module_Coords.setPosition(1, 99)) + ); + + return List.of( + new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, positionIndex(Config.get().fpsX, Config.get().fpsY))), + new SettingRow("Show Biome", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Coords.isBiomeEnabled(), Module_Coords::setBiomeEnabled)), + new SettingRow("Padding", SettingsControls.makeSlider(FLAT, 80, 0.0, 15.0, Config.get().coordsP, value -> (int) value + "px", value -> Module_Coords.setCoordsPadding((int) value))) + ); + } + + public static List hitbox(Consumer reopenSettings) { + List rows = new ArrayList<>(); + rows.add(new SettingRow("Custom Color", SettingsControls.makeCheckbox( + FLAT, GLASS_PANEL, Module_Hitbox.isEnabled(), + value -> { Module_Hitbox.setEnabled(value); reopenSettings.accept("Hitbox"); } + ))); + if (Module_Hitbox.isEnabled()) { + rows.add(new SettingRow("Color", SettingsControls.makeSlider( + FLAT, 80, 0.0, 360.0, Module_Hitbox.getHue(), + value -> (int) (double) value + "\u00B0", + value -> Module_Hitbox.setHue((int) (double) value) + ))); + } + return rows; + } + + public static List effects() { + var positionStates = List.of( + new SettingsControls.ButtonState("L-TOP", () -> Module_Effects.setPosition(1, 1)), + new SettingsControls.ButtonState("R-TOP", () -> Module_Effects.setPosition(99, 1)), + new SettingsControls.ButtonState("R-BOTTOM", () -> Module_Effects.setPosition(99, 99)), + new SettingsControls.ButtonState("L-BOTTOM", () -> Module_Effects.setPosition(1, 99)) + ); + + return List.of( + new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates, positionIndex(Config.get().effectsX, Config.get().effectsY))), + new SettingRow("Show Background", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Effects.isBackgroundEnabled(), Module_Effects::setBackgroundEnabled)), + new SettingRow("Show Timer", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Effects.isTimerEnabled(), Module_Effects::setTimerEnabled)), + new SettingRow("Show Name", SettingsControls.makeCheckbox(FLAT, GLASS_PANEL, Module_Effects.isNameEnabled(), Module_Effects::setNameEnabled)) + ); + } +} diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java index c88baa8..7d680db 100644 --- a/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java @@ -11,6 +11,8 @@ import net.minecraft.network.chat.FontDescription; import net.minecraft.resources.Identifier; import net.minecraft.sounds.SoundEvents; +import de.fullrisk.citrusDev.Config; + import java.util.List; import java.util.function.DoubleConsumer; import java.util.function.DoubleFunction; @@ -21,9 +23,9 @@ public class SettingsControls { private static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five"); - private static final Surface GLASS_PANEL = Surface.blur(5f, 15f) - .and(Surface.flat(0x40FFFFFF)) - .and(Surface.outline(0x64de4b)); + private static int secColor() { + return Config.get().darkMode ? 0xFFd0d4da : 0xFFb0b6c0; + } public record ButtonState(String label, Runnable onSelect) {} @@ -106,7 +108,7 @@ public class SettingsControls { return true; }); button.mouseEnter().subscribe(() -> label.color(Color.ofRgb(0xFFFFFF))); - button.mouseLeave().subscribe(() -> label.color(Color.ofRgb(0xCCCCCC))); + button.mouseLeave().subscribe(() -> label.color(Color.ofRgb(0xDDDDDD))); return button; } @@ -198,7 +200,7 @@ public class SettingsControls { var label = UIComponents.label(Component.literal(text.toUpperCase()) .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) - .color(Color.ofRgb(0xFF5c5c66)); + .color(Color.ofRgb(secColor())); row.child(label); FlowLayout longLine = UIContainers.horizontalFlow(Sizing.fill(100), Sizing.fixed(1)); diff --git a/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java b/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java index 62a6f57..90f5193 100644 --- a/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java +++ b/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java @@ -71,9 +71,9 @@ public class CitrusDevClient implements ClientModInitializer { while (openScreenKey.consumeClick()) { if (client.player != null && client.player.isShiftKeyDown()) { String lastModule = Config.get().lastModule; - client.setScreen(new MyScreen(lastModule)); + client.setScreen(new MainUI(lastModule)); } else { - client.setScreen(new MyScreen(null)); + client.setScreen(new MainUI(null)); } }