2222
2323package io .github .axolotlclient .modules .hud .gui .hud ;
2424
25+ import java .io .IOException ;
2526import java .util .ArrayList ;
2627import java .util .List ;
28+ import java .util .Map ;
2729import java .util .Optional ;
2830
2931import com .mojang .blaze3d .platform .InputConstants ;
3739import io .github .axolotlclient .modules .hud .util .DrawUtil ;
3840import io .github .axolotlclient .modules .hud .util .Rectangle ;
3941import io .github .axolotlclient .util .ClientColors ;
42+ import io .github .axolotlclient .util .GsonHelper ;
4043import io .github .axolotlclient .util .events .Events ;
4144import io .github .axolotlclient .util .events .impl .PlayerDirectionChangeEvent ;
45+ import io .github .axolotlclient .util .options .GenericOption ;
46+ import lombok .Getter ;
47+ import lombok .Setter ;
4248import net .minecraft .Util ;
4349import net .minecraft .client .KeyMapping ;
4450import net .minecraft .client .gui .GuiGraphics ;
@@ -84,7 +90,8 @@ public class KeystrokeHud extends TextHudEntry {
8490 new int []{-1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 },
8591 new int []{-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }
8692 });
87- private ArrayList <Keystroke > keystrokes ;
93+ private final KeystrokesGenericOption keystrokesOption = new KeystrokesGenericOption ("keystrokes" , "keystrokes.configure" );
94+ public ArrayList <Keystroke > keystrokes ;
8895 private float mouseX = 0 ;
8996 private float mouseY = 0 ;
9097 private float lastMouseX = 0 ;
@@ -110,13 +117,7 @@ public static Optional<String> getMouseKeyBindName(KeyMapping keyBinding) {
110117 return Optional .empty ();
111118 }
112119
113- public void setKeystrokes () {
114- if (client .getWindow () == null ) {
115- keystrokes = null ;
116- return ;
117- // Wait until render is called
118- }
119- keystrokes = new ArrayList <>();
120+ public void setDefaultKeystrokes () {
120121 DrawPosition pos = getPos ();
121122 // LMB
122123 keystrokes .add (createFromKey (new Rectangle (0 , 36 , 26 , 17 ), pos , client .options .keyAttack ));
@@ -132,7 +133,7 @@ public void setKeystrokes() {
132133 keystrokes .add (createFromKey (new Rectangle (36 , 18 , 17 , 17 ), pos , client .options .keyRight ));
133134
134135 // Space
135- keystrokes .add (new Keystroke (new Rectangle (0 , 54 , 53 , 7 ), pos , client .options .keyJump , (stroke , matrices ) -> {
136+ keystrokes .add (new KeyOptionKeystroke (new Rectangle (0 , 54 , 53 , 7 ), pos , client .options .keyJump , (stroke , matrices ) -> {
136137 Rectangle bounds = stroke .bounds ;
137138 Rectangle spaceBounds = new Rectangle (bounds .x () + stroke .offset .x () + 4 ,
138139 bounds .y () + stroke .offset .y () + 2 , bounds .width () - 8 , 1 );
@@ -142,6 +143,16 @@ public void setKeystrokes() {
142143 (stroke .getFGColor ().toInt () & 16579836 ) >> 2 | stroke .getFGColor ().toInt () & -16777216 ));
143144 }
144145 }));
146+ }
147+
148+ public void setKeystrokes () {
149+ if (client .getWindow () == null ) {
150+ keystrokes = null ;
151+ return ;
152+ // Wait until render is called
153+ }
154+ keystrokes = new ArrayList <>();
155+ setDefaultKeystrokes ();
145156 KeyMapping .releaseAll ();
146157 KeyMapping .setAll ();
147158
@@ -178,14 +189,7 @@ public void onMouseMovementOption(boolean value) {
178189 }
179190
180191 public Keystroke createFromString (Rectangle bounds , DrawPosition offset , KeyMapping key , String word ) {
181- return new Keystroke (bounds , offset , key , (stroke , matrices ) -> {
182- Rectangle strokeBounds = stroke .bounds ;
183- float x = (strokeBounds .x () + stroke .offset .x () + ((float ) strokeBounds .width () / 2 ))
184- - ((float ) client .font .width (word ) / 2 );
185- float y = strokeBounds .y () + stroke .offset .y () + ((float ) strokeBounds .height () / 2 ) - 4 ;
186-
187- drawString (matrices , word , (int ) x , (int ) y , stroke .getFGColor ().toInt (), shadow .get ());
188- });
192+ return new KeyOptionKeystroke (bounds , offset , key , word );
189193 }
190194
191195 @ Override
@@ -288,9 +292,11 @@ public interface KeystrokeRenderer {
288292 void render (Keystroke stroke , GuiGraphics graphics );
289293 }
290294
291- public class Keystroke {
295+ public abstract class Keystroke {
292296
293- protected final KeyMapping key ;
297+ @ Getter
298+ @ Setter
299+ protected KeyMapping key ;
294300 protected final KeystrokeRenderer render ;
295301 protected final Rectangle bounds ;
296302 private final int animTime = 100 ;
@@ -346,5 +352,108 @@ public Color getOutlineColor() {
346352 return key .isDown () ? ClientColors .blend (outlineColor .get (), pressedOutlineColor .get (), getPercentPressed ())
347353 : ClientColors .blend (pressedOutlineColor .get (), outlineColor .get (), getPercentPressed ());
348354 }
355+
356+ public Map <String , Object > serialize () {
357+ return Map .of ("key" , key .saveString (),
358+ "bounds" , Map .of ("x" , bounds .x (), "y" , bounds .y (), "width" , bounds .width (), "height" , bounds .height ()));
359+ }
360+ }
361+
362+ @ SuppressWarnings ("unchecked" )
363+ private Keystroke deserializeKey (Map <String , ?> json ) {
364+ if ("option" .equals (json .get ("type" ))) {
365+ KeyMapping key = KeyMapping .get ((String ) json .get ("option" ));
366+ String name = getMouseKeyBindName (key ).orElse (key .getTranslatedKeyMessage ().getString ().toUpperCase ());
367+ if (name .length () > 4 ) {
368+ name = name .substring (0 , 2 );
369+ }
370+ return new KeyOptionKeystroke (getRectangle ((Map <String , ?>) json .get ("bounds" )), getPos (), key , name );
371+ } else {
372+ KeyMapping key = new KeyMapping ("" , 0 , "keystrokehud.keys_category" );
373+ key .setKey (InputConstants .getKey ((String ) json .get ("key" )));
374+ return new CustomKeystroke (getRectangle ((Map <String , ?>) json .get ("bounds" )), getPos (), key );
375+ }
376+ }
377+
378+ private static Rectangle getRectangle (Map <String , ?> json ) {
379+ return new Rectangle ((int ) json .get ("x" ), (int ) json .get ("y" ), (int ) json .get ("width" ), (int ) json .get ("height" ));
380+ }
381+
382+ public class KeyOptionKeystroke extends Keystroke {
383+
384+ public KeyOptionKeystroke (Rectangle bounds , DrawPosition offset , KeyMapping key , KeystrokeRenderer render ) {
385+ super (bounds , offset , key , render );
386+ }
387+
388+ public KeyOptionKeystroke (Rectangle bounds , DrawPosition offset , KeyMapping key , String word ) {
389+ this (bounds , offset , key , (stroke , matrices ) -> {
390+ Rectangle strokeBounds = stroke .bounds ;
391+ float x = (strokeBounds .x () + stroke .offset .x () + ((float ) strokeBounds .width () / 2 ))
392+ - ((float ) client .font .width (word ) / 2 );
393+ float y = strokeBounds .y () + stroke .offset .y () + ((float ) strokeBounds .height () / 2 ) - 4 ;
394+
395+ drawString (matrices , word , (int ) x , (int ) y , stroke .getFGColor ().toInt (), shadow .get ());
396+ });
397+ }
398+
399+
400+ @ Override
401+ public Map <String , Object > serialize () {
402+ Map <String , Object > json = super .serialize ();
403+ json .put ("type" , "option" );
404+ json .put ("option" , key .getName ());
405+ return json ;
406+ }
407+ }
408+
409+ public class CustomKeystroke extends Keystroke {
410+
411+ public CustomKeystroke (Rectangle bounds , DrawPosition offset , KeyMapping key ) {
412+ super (bounds , offset , key , (stroke , matrices ) -> {
413+ String word = key .getName ();
414+ Rectangle strokeBounds = stroke .bounds ;
415+ float x = (strokeBounds .x () + stroke .offset .x () + ((float ) strokeBounds .width () / 2 ))
416+ - ((float ) client .font .width (word ) / 2 );
417+ float y = strokeBounds .y () + stroke .offset .y () + ((float ) strokeBounds .height () / 2 ) - 4 ;
418+
419+ drawString (matrices , word , (int ) x , (int ) y , stroke .getFGColor ().toInt (), shadow .get ());
420+ });
421+ }
422+
423+ @ Override
424+ public Map <String , Object > serialize () {
425+ Map <String , Object > json = super .serialize ();
426+ json .put ("type" , "custom" );
427+ json .put ("key" , key .saveString ());
428+ return json ;
429+ }
430+ }
431+
432+ public class KeystrokesGenericOption extends GenericOption {
433+
434+ public KeystrokesGenericOption (String name , String label ) {
435+ super (name , label , () -> {
436+
437+ });
438+ }
439+
440+ @ Override
441+ public String toSerializedValue () {
442+ return GsonHelper .GSON .toJson (keystrokes .stream ().map (Keystroke ::serialize ).toList ());
443+ }
444+
445+ @ SuppressWarnings ("unchecked" )
446+ @ Override
447+ public void fromSerializedValue (String s ) {
448+ keystrokes .clear ();
449+ try {
450+ List <?> entries = (List <?>) GsonHelper .read (s );
451+ entries .stream ().map (e -> (Map <String , Object >) e )
452+ .map (KeystrokeHud .this ::deserializeKey )
453+ .forEach (keystrokes ::add );
454+ } catch (IOException e ) {
455+
456+ }
457+ }
349458 }
350459}
0 commit comments