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+ }
0 commit comments