Skip to content

Commit a588aee

Browse files
committed
add config ui
1 parent 6b0cfe1 commit a588aee

File tree

4 files changed

+268
-0
lines changed

4 files changed

+268
-0
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ base {
1212

1313
repositories {
1414
maven { url 'https://jitpack.io' }
15+
maven { url 'https://api.modrinth.com/maven' }
1516
}
1617

1718
loom {
@@ -48,6 +49,7 @@ dependencies {
4849
modImplementation include("org.java-websocket:Java-WebSocket:1.5.2")
4950
modImplementation include("com.google.code.gson:gson:2.10.1")
5051
modImplementation include("com.neovisionaries:nv-websocket-client:2.14")
52+
modImplementation "maven.modrinth:yacl:3.8.2+1.21.11-fabric"
5153
}
5254

5355
processResources {

src/client/java/com/coflnet/CoflModClient.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import com.coflnet.gui.RenderUtils;
3434
import com.coflnet.gui.cofl.CoflBinGUI;
35+
import com.coflnet.gui.cofl.CoflSettingsScreen;
3536
import com.coflnet.gui.tfm.TfmBinGUI;
3637
import com.google.gson.Gson;
3738
import com.google.gson.GsonBuilder;
@@ -97,6 +98,7 @@ public class CoflModClient implements ClientModInitializer {
9798
private static final KeyBinding.Category SKYCOFL_UNCHANGEABLE_CATEGORY = KeyBinding.Category.create(Identifier.of("coflnet", "skycofl_unchangeable"));
9899
public static KeyBinding bestflipsKeyBinding;
99100
public static KeyBinding uploadItemKeyBinding;
101+
public static KeyBinding openSettingsKeyBinding;
100102
public static List<KeyBinding> additionalKeyBindings = new ArrayList<KeyBinding>();
101103
public static Map<KeyBinding, HotkeyRegister> keybindingsToHotkeys = new HashMap<KeyBinding, HotkeyRegister>();
102104
public static ArrayList<String> knownIds = new ArrayList<>();
@@ -160,6 +162,11 @@ public void onInitializeClient() {
160162
InputUtil.Type.KEYSYM,
161163
GLFW.GLFW_KEY_I,
162164
SKYCOFL_CATEGORY));
165+
openSettingsKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
166+
"keybinding.coflmod.opensettings",
167+
InputUtil.Type.KEYSYM,
168+
GLFW.GLFW_KEY_O,
169+
SKYCOFL_CATEGORY));
163170

164171
ClientTickEvents.END_CLIENT_TICK.register(client -> {
165172
// Process scoreboard updates if dirty flag is set (set by ScoreboardMixin)
@@ -185,6 +192,17 @@ public void onInitializeClient() {
185192
if(uploadItemKeyBinding.wasPressed())
186193
handleGetHoveredItem(client);
187194

195+
if (openSettingsKeyBinding.wasPressed()) {
196+
CoflSkyCommand.processCommand(new String[]{"get", "json"}, username);
197+
try {
198+
client.setScreen(CoflSettingsScreen.create(client.currentScreen));
199+
} catch (Throwable t) {
200+
sendChatMessage("§cFailed to open settings GUI. YACL is missing or failed to load (please add the lastest version of YACL mod to your mods).");
201+
System.out.println("Failed to open settings GUI: " + t.getMessage());
202+
t.printStackTrace();
203+
}
204+
}
205+
188206
if (additionalKeyBindings == null) return;
189207
try{
190208
for (KeyBinding additionalKeyBinding : additionalKeyBindings) {
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
package com.coflnet.gui.cofl;
2+
3+
import CoflCore.CoflCore;
4+
import CoflCore.CoflSkyCommand;
5+
import CoflCore.classes.Settings;
6+
import dev.isxander.yacl3.api.ConfigCategory;
7+
import dev.isxander.yacl3.api.Option;
8+
import dev.isxander.yacl3.api.OptionDescription;
9+
import dev.isxander.yacl3.api.YetAnotherConfigLib;
10+
import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder;
11+
import dev.isxander.yacl3.api.controller.DoubleFieldControllerBuilder;
12+
import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder;
13+
import dev.isxander.yacl3.api.controller.IntegerFieldControllerBuilder;
14+
import dev.isxander.yacl3.api.controller.LongFieldControllerBuilder;
15+
import dev.isxander.yacl3.api.controller.StringControllerBuilder;
16+
import net.minecraft.client.MinecraftClient;
17+
import net.minecraft.client.gui.screen.Screen;
18+
import net.minecraft.text.Text;
19+
20+
import java.util.ArrayList;
21+
import java.util.Comparator;
22+
import java.util.LinkedHashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
public class CoflSettingsScreen {
27+
28+
public static Screen create(Screen parent) {
29+
List<Settings> known = CoflCore.config.knownSettings == null ? List.of() : CoflCore.config.knownSettings;
30+
Map<String, List<Settings>> byCategory = new LinkedHashMap<>();
31+
32+
for (Settings setting : known) {
33+
String category = setting.getSettingCategory();
34+
if (category == null || category.isBlank()) {
35+
category = "General";
36+
}
37+
byCategory.computeIfAbsent(category, ignored -> new ArrayList<>()).add(setting);
38+
}
39+
40+
YetAnotherConfigLib.Builder builder = YetAnotherConfigLib.createBuilder()
41+
.title(Text.of("SkyCofl Settings"));
42+
43+
byCategory.entrySet().stream()
44+
.sorted(Map.Entry.comparingByKey(String.CASE_INSENSITIVE_ORDER))
45+
.forEach(entry -> {
46+
ConfigCategory.Builder categoryBuilder = ConfigCategory.createBuilder()
47+
.name(Text.of(capitalize(entry.getKey())));
48+
49+
entry.getValue().stream()
50+
.sorted(Comparator.comparing(s -> fallback(s.getSettingName(), s.getSettingKey()), String.CASE_INSENSITIVE_ORDER))
51+
.forEach(setting -> {
52+
Option<?> option = buildOption(setting);
53+
if (option != null) {
54+
categoryBuilder.option(option);
55+
}
56+
});
57+
58+
builder.category(categoryBuilder.build());
59+
});
60+
61+
builder.save(() -> {
62+
});
63+
64+
return builder.build().generateScreen(parent);
65+
}
66+
67+
private static Option<?> buildOption(Settings setting) {
68+
String settingName = fallback(setting.getSettingName(), setting.getSettingKey());
69+
String settingInfo = fallback(setting.getSettingInfo(), "No description available.");
70+
String type = fallback(setting.getSettingType(), "String");
71+
72+
return switch (type) {
73+
case "Boolean" -> buildBooleanOption(setting, settingName, settingInfo);
74+
case "Int32", "Int16", "Byte", "SByte" -> buildIntegerOption(setting, settingName, settingInfo);
75+
case "Int64" -> buildLongOption(setting, settingName, settingInfo);
76+
case "Double" -> buildDoubleOption(setting, settingName, settingInfo);
77+
case "Single" -> buildFloatOption(setting, settingName, settingInfo);
78+
default -> buildStringOption(setting, settingName, settingInfo);
79+
};
80+
}
81+
82+
private static Option<Boolean> buildBooleanOption(Settings setting, String name, String info) {
83+
boolean current = toBoolean(setting.getSettingValue());
84+
return Option.<Boolean>createBuilder()
85+
.name(Text.of(name))
86+
.description(OptionDescription.of(Text.of(info)))
87+
.binding(current,
88+
() -> toBoolean(setting.getSettingValue()),
89+
value -> {
90+
setting.setSettingValue(value);
91+
sendSet(setting.getSettingKey(), Boolean.toString(value));
92+
})
93+
.controller(TickBoxControllerBuilder::create)
94+
.build();
95+
}
96+
97+
private static Option<Integer> buildIntegerOption(Settings setting, String name, String info) {
98+
int current = toInt(setting.getSettingValue());
99+
return Option.<Integer>createBuilder()
100+
.name(Text.of(name))
101+
.description(OptionDescription.of(Text.of(info)))
102+
.binding(current,
103+
() -> toInt(setting.getSettingValue()),
104+
value -> {
105+
setting.setSettingValue(value);
106+
sendSet(setting.getSettingKey(), Integer.toString(value));
107+
})
108+
.controller(IntegerFieldControllerBuilder::create)
109+
.build();
110+
}
111+
112+
private static Option<Long> buildLongOption(Settings setting, String name, String info) {
113+
long current = toLong(setting.getSettingValue());
114+
return Option.<Long>createBuilder()
115+
.name(Text.of(name))
116+
.description(OptionDescription.of(Text.of(info)))
117+
.binding(current,
118+
() -> toLong(setting.getSettingValue()),
119+
value -> {
120+
setting.setSettingValue(value);
121+
sendSet(setting.getSettingKey(), Long.toString(value));
122+
})
123+
.controller(LongFieldControllerBuilder::create)
124+
.build();
125+
}
126+
127+
private static Option<Double> buildDoubleOption(Settings setting, String name, String info) {
128+
double current = toDouble(setting.getSettingValue());
129+
return Option.<Double>createBuilder()
130+
.name(Text.of(name))
131+
.description(OptionDescription.of(Text.of(info)))
132+
.binding(current,
133+
() -> toDouble(setting.getSettingValue()),
134+
value -> {
135+
setting.setSettingValue(value);
136+
sendSet(setting.getSettingKey(), Double.toString(value));
137+
})
138+
.controller(DoubleFieldControllerBuilder::create)
139+
.build();
140+
}
141+
142+
private static Option<Float> buildFloatOption(Settings setting, String name, String info) {
143+
float current = toFloat(setting.getSettingValue());
144+
return Option.<Float>createBuilder()
145+
.name(Text.of(name))
146+
.description(OptionDescription.of(Text.of(info)))
147+
.binding(current,
148+
() -> toFloat(setting.getSettingValue()),
149+
value -> {
150+
setting.setSettingValue(value);
151+
sendSet(setting.getSettingKey(), Float.toString(value));
152+
})
153+
.controller(FloatFieldControllerBuilder::create)
154+
.build();
155+
}
156+
157+
private static Option<String> buildStringOption(Settings setting, String name, String info) {
158+
String current = toStringValue(setting.getSettingValue());
159+
return Option.<String>createBuilder()
160+
.name(Text.of(name))
161+
.description(OptionDescription.of(Text.of(info)))
162+
.binding(current,
163+
() -> toStringValue(setting.getSettingValue()),
164+
value -> {
165+
setting.setSettingValue(value);
166+
sendSet(setting.getSettingKey(), value);
167+
})
168+
.controller(StringControllerBuilder::create)
169+
.build();
170+
}
171+
172+
private static void sendSet(String key, String value) {
173+
if (MinecraftClient.getInstance() == null || MinecraftClient.getInstance().getSession() == null) {
174+
return;
175+
}
176+
CoflSkyCommand.processCommand(new String[]{"set", key, value}, MinecraftClient.getInstance().getSession().getUsername());
177+
}
178+
179+
private static String fallback(String primary, String fallback) {
180+
if (primary == null || primary.isBlank()) {
181+
return fallback;
182+
}
183+
return primary;
184+
}
185+
186+
private static String capitalize(String text) {
187+
if (text == null || text.isBlank()) {
188+
return "General";
189+
}
190+
return Character.toUpperCase(text.charAt(0)) + text.substring(1);
191+
}
192+
193+
private static boolean toBoolean(Object value) {
194+
if (value instanceof Boolean b) {
195+
return b;
196+
}
197+
return "true".equalsIgnoreCase(String.valueOf(value)) || "1".equals(String.valueOf(value));
198+
}
199+
200+
private static int toInt(Object value) {
201+
if (value instanceof Number number) {
202+
return number.intValue();
203+
}
204+
try {
205+
return Integer.parseInt(String.valueOf(value));
206+
} catch (Exception ignored) {
207+
return 0;
208+
}
209+
}
210+
211+
private static long toLong(Object value) {
212+
if (value instanceof Number number) {
213+
return number.longValue();
214+
}
215+
try {
216+
return Long.parseLong(String.valueOf(value));
217+
} catch (Exception ignored) {
218+
return 0L;
219+
}
220+
}
221+
222+
private static double toDouble(Object value) {
223+
if (value instanceof Number number) {
224+
return number.doubleValue();
225+
}
226+
try {
227+
return Double.parseDouble(String.valueOf(value));
228+
} catch (Exception ignored) {
229+
return 0D;
230+
}
231+
}
232+
233+
private static float toFloat(Object value) {
234+
if (value instanceof Number number) {
235+
return number.floatValue();
236+
}
237+
try {
238+
return Float.parseFloat(String.valueOf(value));
239+
} catch (Exception ignored) {
240+
return 0F;
241+
}
242+
}
243+
244+
private static String toStringValue(Object value) {
245+
return value == null ? "" : String.valueOf(value);
246+
}
247+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"keybinding.coflmod.bestflips": "Cofl: Show best flips",
3+
"keybinding.coflmod.opensettings": "Cofl: Open settings",
34
"key.category.coflnet.skycofl": "SkyCofl keys",
45
"key.category.coflnet.skycofl_unchangeable": "SkyCofl keys"
56
}

0 commit comments

Comments
 (0)