1010import net .minecraft .nbt .Tag ;
1111import net .minecraft .resources .ResourceLocation ;
1212import net .minecraft .SharedConstants ;
13+ import net .minecraft .util .Tuple ;
1314import net .minecraft .world .level .Level ;
14- import org .apache .commons .io .FileUtils ;
1515
1616import javax .annotation .Nonnull ;
1717import java .io .File ;
1818import java .io .IOException ;
1919import java .util .*;
20+ import java .util .function .BiFunction ;
2021
2122/**
2223 * This class is part of the ObserverLib Mod
@@ -155,56 +156,81 @@ private static <T extends IWorldRelatedData<T>> void writeDataToFile(IWorldRelat
155156 @ Nonnull
156157 private static <T extends IWorldRelatedData <T >> T loadDataFromFile (WorldCacheDomain domain , ResourceLocation dimTypeName , WorldCacheDomain .SaveKey <T > key ) {
157158 DirectorySet f = getDirectorySet (domain .getSaveDirectory (), dimTypeName , key );
158- if (!f .getActualDirectory ().exists () && !f .getBackupDirectory ().exists ()) {
159- return key .getNewInstance (key );
160- }
161- ObserverLib .log .info ("Load WorldRelatedData '" + key .getIdentifier () + "' for world " + dimTypeName );
162- boolean errored = false ;
163- T data = null ;
164- try {
165- if (f .getActualDirectory ().exists ()) {
166- data = attemptLoad (key , f .getActualDirectory ());
159+ IWorldRelatedData .FileLoader <T > loader = createLoadingContext (f , key );
160+
161+ ObserverLib .log .info ("Loading WorldData {}/{} for level {}" , key .getDomainName ().getNamespace (), key .getIdentifier (), dimTypeName );
162+ T loaded = loader .loadData (key .saveFileResolver (), key .getInstanceCodec ())
163+ .map (dataTpl -> {
164+ dataTpl .getA ().readAdditionalData (dataTpl .getB ().getParentFile (), loader );
165+ return dataTpl .getA ();
166+ })
167+ .orElseGet (key ::newInstance );
168+ ObserverLib .log .info ("Loading WorldData {}/{} for level {} finished" , key .getDomainName ().getNamespace (), key .getIdentifier (), dimTypeName );
169+ return loaded ;
170+ }
171+
172+ private static <F > IWorldRelatedData .FileLoader <F > createLoadingContext (DirectorySet dirSet , WorldCacheDomain .SaveKey <?> rootKey ) {
173+ String rootName = rootKey .saveFileResolver ().resolveFile (new File ("/" )).getAbsolutePath ();
174+ return (fileResolver , codec ) -> {
175+ if (!dirSet .getActualDirectory ().exists () && !dirSet .getBackupDirectory ().exists ()) {
176+ return Optional .empty ();
167177 }
168- } catch (Exception exc ) {
169- ObserverLib .log .info ("Loading worlddata '" + key .getIdentifier () + "' failed for its actual save. Attempting load from backup." );
170- errored = true ;
171- }
172- if (data == null ) {
178+ // Resolve from root to get an idea of what's being loaded.
179+ String attemptName = fileResolver .resolveFile (new File ("/" )).getAbsolutePath ();
180+ boolean isSaveRoot = attemptName .equals (rootName );
181+
182+ F data = null ;
183+ File dataFile = null ;
184+
185+ // Try load from actual fileset
173186 try {
174- if (f .getBackupDirectory ().exists ()) {
175- data = attemptLoad (key , f .getBackupDirectory ());
187+ if (dirSet .getActualDirectory ().exists ()) {
188+ dataFile = fileResolver .resolveFile (dirSet .getActualDirectory ());
189+ if (dataFile .exists ()) {
190+ CompoundTag dataTag = NbtIo .read (dataFile .toPath ());
191+ data = codec .parse (NbtOps .INSTANCE , dataTag .get ("data" )).getOrThrow (IOException ::new );
192+ }
176193 }
177194 } catch (Exception exc ) {
178- ObserverLib .log .info ("Loading worlddata '" + key . getIdentifier () + "' failed for its backup save. Creating empty one for current runtime and copying erroneous files to error directory." );
179- errored = true ;
195+ ObserverLib .log .warn ("Loading level data {} failed for its actual save. Attempting load from backup." ,
196+ ( isSaveRoot ? rootKey . getIdentifier () : rootKey . getIdentifier () + attemptName )) ;
180197 }
181- }
182- if (data == null && errored ) {
183- DirectorySet errorSet = f .getErrorDirectories ();
184- try {
185- if (f .getActualDirectory ().exists ()) {
186- Files .copy (f .getActualDirectory (), errorSet .getActualDirectory ());
187- FileUtils .deleteDirectory (f .getActualDirectory ());
198+ // Try load from backup fileset
199+ if (data == null ) {
200+ try {
201+ if (dirSet .getBackupDirectory ().exists ()) {
202+ dataFile = fileResolver .resolveFile (dirSet .getBackupDirectory ());
203+ if (dataFile .exists ()) {
204+ CompoundTag dataTag = NbtIo .read (dataFile .toPath ());
205+ data = codec .parse (NbtOps .INSTANCE , dataTag .get ("data" )).getOrThrow (IOException ::new );
206+ }
207+ }
208+ } catch (Exception exc ) {
209+ ObserverLib .log .warn ("Loading level data {} failed for its backup save. Copying erroneous files to error directory." ,
210+ (isSaveRoot ? rootKey .getIdentifier () : rootKey .getIdentifier () + attemptName ));
188211 }
189- if (f .getBackupDirectory ().exists ()) {
190- Files .copy (f .getBackupDirectory (), errorSet .getBackupDirectory ());
191- FileUtils .deleteDirectory (f .getBackupDirectory ());
212+ }
213+ // Copy files to error directory and give up.
214+ if (data == null ) {
215+ DirectorySet errorSet = dirSet .getErrorDirectories ();
216+ try {
217+ if (dirSet .getActualDirectory ().exists ()) {
218+ Files .copy (dirSet .getActualDirectory (), errorSet .getActualDirectory ());
219+ }
220+ if (dirSet .getBackupDirectory ().exists ()) {
221+ Files .copy (dirSet .getBackupDirectory (), errorSet .getBackupDirectory ());
222+ }
223+ } catch (Exception e ) {
224+ ObserverLib .log .warn ("Copying erroneous level data {} to the error directory failed." ,
225+ (isSaveRoot ? rootKey .getIdentifier () : rootKey .getIdentifier () + attemptName ));
226+ ObserverLib .log .error ("Copying files failed." , e );
192227 }
193- } catch (Exception e ) {
194- ObserverLib .log .info ("Attempting to copy erroneous worlddata '" + key .getIdentifier () + "' to its error files directory failed." );
195- e .printStackTrace ();
196228 }
197- }
198- if (data == null ) {
199- data = key .getNewInstance (key );
200- }
201- ObserverLib .log .info ("Loading of '" + key .getIdentifier () + "' for world " + dimTypeName + " finished." );
202- return data ;
203- }
204-
205- private static <T extends IWorldRelatedData <T >> T attemptLoad (WorldCacheDomain .SaveKey <T > key , File baseDirectory ) throws IOException {
206- CompoundTag dataTag = NbtIo .read (key .getSaveFile (baseDirectory ).toPath ());
207- return key .getInstanceCodec ().parse (NbtOps .INSTANCE , dataTag .get ("data" )).getOrThrow (IOException ::new );
229+ if (data == null ) {
230+ return Optional .empty ();
231+ }
232+ return Optional .of (new Tuple <>(data , dataFile ));
233+ };
208234 }
209235
210236 private synchronized static DirectorySet getDirectorySet (File baseDirectory , ResourceLocation dimTypeName , WorldCacheDomain .SaveKey <?> key ) {
@@ -217,15 +243,6 @@ private synchronized static DirectorySet getDirectorySet(File baseDirectory, Res
217243 return new DirectorySet (new File (worldDir , key .getIdentifier ()));
218244 }
219245
220- private static File getServerWorldDirectory (File baseDirectory ) {
221- File pDir = new File (baseDirectory , "worlddata" );
222- if (!pDir .exists ()) {
223- pDir .mkdirs ();
224- }
225- ensureFolder (pDir );
226- return pDir ;
227- }
228-
229246 private static void ensureFolder (File f ) {
230247 if (!f .isDirectory ()) {
231248 ObserverLib .log .warn ("dataFile exists, but is a file instead of a folder! Please ensure that this is a folder/delete the file!" );
0 commit comments