Added Quests and Real Settings (yay)

This commit is contained in:
2026-07-11 09:53:19 +02:00
parent 596612880b
commit d3fc829dee
12 changed files with 666 additions and 150 deletions
@@ -1,6 +1,7 @@
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;
@@ -12,20 +13,19 @@ 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.UIHelper.ScalableLabel;
import de.fullrisk.citrusDev.UIHelper.ScalableButton;
import de.fullrisk.citrusDev.UIHelper.ScaleValue;
import de.fullrisk.citrusDev.client.PlaytimeTracker;
import java.util.List;
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<FlowLayout> {
private static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five");
static final Identifier MC_FIVE = Identifier.fromNamespaceAndPath("citrus-dev", "minecraft_five");
private static final Surface GLASS_PANEL = Surface.blur(5f, 15f)
static final Surface GLASS_PANEL = Surface.blur(5f, 15f)
.and(Surface.flat(0x40FFFFFF))
.and(Surface.outline(0x64de4b));
@@ -47,6 +47,11 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
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;
@@ -101,7 +106,7 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
row.child(sidebar);
content = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH), Sizing.fixed(ROW_HEIGHT));
content.gap(6);
content.gap(2);
content.padding(Insets.of(4));
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
@@ -125,7 +130,6 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
rootComponent.child(panel);
// Now that content is attached to the tree, decide what to show.
if ("FPS".equals(initialModule)) {
openModuleSettings("FPS", fpsModuleSettings());
} else {
@@ -154,7 +158,7 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
content.clearChildren();
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
buildQuestsPanel(content);
QuestsPanel.build(content, CONTENT_WIDTH, ROW_HEIGHT);
}),
new TabDef("settings", () -> {
content.clearChildren();
@@ -244,7 +248,6 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
return button;
}
private void buildGeneralPanel(FlowLayout content) {
FlowLayout iconButton = UIContainers.horizontalFlow(Sizing.content(), Sizing.content());
iconButton.gap(8);
@@ -281,7 +284,7 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
iconButton.child(textStack);
iconButton.child(UIComponents.spacer());
FlowLayout settingsButton = makeSmallButton(
FlowLayout settingsButton = SettingsControls.makeSmallButton(
FLAT,
Identifier.fromNamespaceAndPath("citrus-dev", "textures/icons/settings.png"),
() -> {
@@ -300,6 +303,7 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
toggle = !toggle;
fpsLabel.color(Color.ofRgb(toggle ? 0xffffff : 0x797b86));
iconButton.surface(toggle ? GLASS_PANEL : DISABLED);
CitrusToast.show("Module Enabled", "FPS counter is now active");
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
@@ -313,31 +317,23 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
content.child(iconButton);
}
private void buildQuestsPanel(FlowLayout content) {
content.child(UIComponents.label(Component.literal("Quests - coming soon")));
}
private void buildSettingsPanel(FlowLayout content) {
content.child(UIComponents.label(Component.literal("Settings")));
}
/**
* Opens a per-module settings view inside the "content" container,
* replacing whatever was there before. A back arrow returns to General.
*/
private void openModuleSettings(String title, List<SettingRow> rows) {
content.clearChildren();
// re-assert alignment explicitly - clearChildren can reset it
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(6);
header.gap(4);
header.child(makeTextButton(FLAT, "<", () -> {
header.child(SettingsControls.makeTextButton(FLAT, "<", () -> {
content.clearChildren();
content.horizontalAlignment(HorizontalAlignment.CENTER);
content.verticalAlignment(VerticalAlignment.TOP);
@@ -350,17 +346,32 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
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) {
content.child(makeSettingRow(row));
FlowLayout settingRow = makeSettingRow(row);
settingRow.verticalSizing(Sizing.fixed(16)); // pin each row to a compact fixed height
rowsContainer.child(settingRow);
}
var scrollArea = UIContainers.verticalScroll(
Sizing.fixed(CONTENT_WIDTH - 8),
Sizing.fixed(ROW_HEIGHT - 24),
rowsContainer
);
content.child(scrollArea);
}
private FlowLayout makeSettingRow(SettingRow setting) {
FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content());
row.verticalAlignment(VerticalAlignment.TOP);
FlowLayout row = UIContainers.horizontalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.fixed(16));
row.verticalAlignment(VerticalAlignment.CENTER);
row.horizontalAlignment(HorizontalAlignment.LEFT);
row.padding(Insets.of(2));
row.gap(6);
row.padding(Insets.of(0));
row.gap(4);
row.child(UIComponents.label(Component.literal(setting.label()))
.color(Color.ofRgb(0xa3a3ac)));
@@ -371,114 +382,28 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
}
private List<SettingRow> fpsModuleSettings() {
List<SettingsControls.ButtonState> 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 sizeSlider = SettingsControls.makeSlider(
FLAT,
80,
0.0, 20.0,
4.0,
value -> (int) value + "px",
value -> Module_FPS.fpsContainer.gap((int) value)
);
return List.of(
new SettingRow("Position", makeCyclingButton())
new SettingRow("Position", SettingsControls.makeCyclingButton(GLASS_PANEL, positionStates)),
new SettingRow("Size", sizeSlider)
);
}
private record ButtonState(String label, Runnable onSelect) {}
private FlowLayout makeCyclingButton() {
List<ButtonState> states = List.of(
new ButtonState("Off", () -> {
Module_FPS.setPosition(1, 1);
}),
new ButtonState("Low", () -> {
Module_FPS.setPosition(99, 1);
}),
new ButtonState("Medium", () -> {
Module_FPS.setPosition(99, 99);
}),
new ButtonState("High", () -> {
Module_FPS.setPosition(1, 99);
})
);
int[] currentIndex = {0};
FlowLayout button = UIContainers.verticalFlow(Sizing.fixed(50), Sizing.fixed(16));
button.verticalAlignment(VerticalAlignment.CENTER);
button.horizontalAlignment(HorizontalAlignment.CENTER);
button.surface(GLASS_PANEL);
var label = UIComponents.label(Component.literal(states.get(0).label()))
.color(Color.ofRgb(0xFFFFFF));
button.child(label);
button.mouseDown().subscribe((click, doubled) -> {
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
);
currentIndex[0] = (currentIndex[0] + 1) % states.size();
ButtonState newState = states.get(currentIndex[0]);
label.text(Component.literal(newState.label()));
newState.onSelect().run();
return true;
});
button.mouseEnter().subscribe(() -> {
label.color(Color.ofRgb(0xFFFFFF));
});
button.mouseLeave().subscribe(() -> {
label.color(Color.ofRgb(0xCCCCCC));
});
return button;
}
private FlowLayout makeSmallButton(Surface baseSurface, Identifier texture, Runnable onClick) {
FlowLayout button = UIContainers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16));
button.verticalAlignment(VerticalAlignment.CENTER);
button.horizontalAlignment(HorizontalAlignment.CENTER);
button.surface(baseSurface);
button.child(UIComponents.texture(texture, 0, 0, 12, 12, 12, 12))
.horizontalAlignment(HorizontalAlignment.CENTER)
.verticalAlignment(VerticalAlignment.CENTER);
button.mouseEnter().subscribe(() -> button.surface(
Surface.blur(5f, 15f).and(Surface.flat(0x70FFFFFF)).and(Surface.outline(0xFFFFFFFF))
));
button.mouseLeave().subscribe(() -> button.surface(baseSurface));
button.mouseDown().subscribe((click, doubled) -> {
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
);
onClick.run();
return true;
});
return button;
}
private FlowLayout makeTextButton(Surface baseSurface, String text, Runnable onClick) {
FlowLayout button = UIContainers.verticalFlow(Sizing.content(), Sizing.content());
button.verticalAlignment(VerticalAlignment.CENTER);
button.horizontalAlignment(HorizontalAlignment.CENTER);
button.padding(Insets.of(2, 2, 4, 4));
button.surface(baseSurface);
button.child(UIComponents.label(Component.literal(text)).color(Color.ofRgb(0xFFFFFF)));
button.mouseEnter().subscribe(() -> button.surface(
Surface.blur(5f, 15f).and(Surface.flat(0x70FFFFFF)).and(Surface.outline(0xFFFFFFFF))
));
button.mouseLeave().subscribe(() -> button.surface(baseSurface));
button.mouseDown().subscribe((click, doubled) -> {
Minecraft.getInstance().getSoundManager().play(
SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.value(), 2.0F, 2)
);
onClick.run();
return true;
});
return button;
}
@Override
public boolean isPauseScreen() {
return false;