33import com .google .gson .FieldNamingPolicy ;
44import com .google .gson .Gson ;
55import com .google .gson .GsonBuilder ;
6+ import com .google .gson .JsonParseException ;
67import com .google .gson .annotations .SerializedName ;
78import it .unimi .dsi .fastutil .objects .Object2BooleanArrayMap ;
89import it .unimi .dsi .fastutil .objects .Object2ObjectArrayMap ;
1718import org .lwjgl .glfw .GLFW ;
1819
1920import java .io .File ;
20- import java .io .FileReader ;
21- import java .io .FileWriter ;
2221import java .io .IOException ;
2322import java .lang .reflect .Modifier ;
23+ import java .nio .charset .StandardCharsets ;
24+ import java .nio .file .Files ;
25+ import java .nio .file .Path ;
2426import java .util .Arrays ;
2527import java .util .EnumSet ;
2628import java .util .Map ;
@@ -38,30 +40,37 @@ public class SodiumExtraGameOptions implements StorageEventHandler {
3840 public RenderSettings renderSettings = new RenderSettings ();
3941 @ SerializedName (SodiumExtraConfigKeys .EXTRA_SETTINGS )
4042 public ExtraSettings extraSettings = new ExtraSettings ();
41- private File file ;
43+ private Path path ;
4244
4345 public static SodiumExtraGameOptions load (File file ) {
46+ return load (file .toPath ());
47+ }
48+
49+ public static SodiumExtraGameOptions load (Path path ) {
4450 SodiumExtraGameOptions config ;
51+ boolean shouldWriteChanges = true ;
4552
46- if (file .exists ()) {
47- try (FileReader reader = new FileReader ( file )) {
53+ if (Files .exists (path )) {
54+ try (var reader = Files . newBufferedReader ( path , StandardCharsets . UTF_8 )) {
4855 config = gson .fromJson (reader , SodiumExtraGameOptions .class );
49- } catch (Exception e ) {
50- SodiumExtraClientMod .logger ().error ("Could not parse config, falling back to defaults!" , e );
56+ if (config == null ) {
57+ throw new JsonParseException ("Root element must be a JSON object" );
58+ }
59+ } catch (IOException | JsonParseException | IllegalStateException e ) {
60+ SodiumExtraClientMod .logger ().warn ("Could not read config, falling back to defaults" , e );
5161 config = new SodiumExtraGameOptions ();
62+ shouldWriteChanges = moveCorruptConfig (path );
5263 }
5364 } else {
5465 config = new SodiumExtraGameOptions ();
5566 }
5667
57- if (config == null ) {
58- SodiumExtraClientMod .logger ().error ("Could not parse config, falling back to defaults!" );
59- config = new SodiumExtraGameOptions ();
60- }
61-
6268 config .sanitize ();
63- config .file = file ;
64- config .writeChanges ();
69+ config .path = path ;
70+
71+ if (shouldWriteChanges ) {
72+ config .writeChanges ();
73+ }
6574
6675 return config ;
6776 }
@@ -92,20 +101,27 @@ private void sanitize() {
92101 }
93102
94103 public void writeChanges () {
95- File dir = this .file .getParentFile ();
104+ if (this .path == null ) {
105+ SodiumExtraClientMod .logger ().warn ("Could not save configuration file because no path was set" );
106+ return ;
107+ }
96108
97- if (!dir .exists ()) {
98- if (!dir .mkdirs ()) {
99- throw new RuntimeException ("Could not create parent directories" );
100- }
101- } else if (!dir .isDirectory ()) {
102- throw new RuntimeException ("The parent file is not a directory" );
109+ try {
110+ this .sanitize ();
111+ ConfigFileIO .writeStringAtomically (this .path , gson .toJson (this ) + System .lineSeparator ());
112+ } catch (IOException e ) {
113+ SodiumExtraClientMod .logger ().warn ("Could not save configuration file" , e );
103114 }
115+ }
104116
105- try (FileWriter writer = new FileWriter (this .file )) {
106- gson .toJson (this , writer );
117+ private static boolean moveCorruptConfig (Path path ) {
118+ try {
119+ Path corruptPath = ConfigFileIO .moveCorruptFile (path );
120+ SodiumExtraClientMod .logger ().warn ("Moved corrupt configuration file to {}" , corruptPath );
121+ return true ;
107122 } catch (IOException e ) {
108- throw new RuntimeException ("Could not save configuration file" , e );
123+ SodiumExtraClientMod .logger ().warn ("Could not move corrupt configuration file" , e );
124+ return false ;
109125 }
110126 }
111127
0 commit comments