diff --git a/SPD-classes/src/main/java/com/watabou/utils/FileUtils.java b/SPD-classes/src/main/java/com/watabou/utils/FileUtils.java index edac90208..ffc3ba13d 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/FileUtils.java +++ b/SPD-classes/src/main/java/com/watabou/utils/FileUtils.java @@ -68,6 +68,50 @@ public class FileUtils { } // Files + + //looks to see if there is any evidence of interrupted saving + public static boolean cleanTempFiles(){ + return cleanTempFiles(""); + } + + public static boolean cleanTempFiles( String dirName ){ + FileHandle dir = getFileHandle(dirName); + boolean foundTemp = false; + for (FileHandle file : dir.list()){ + if (file.isDirectory()){ + foundTemp = cleanTempFiles(dirName + file.name()) || foundTemp; + } else { + if (file.name().endsWith(".tmp")){ + FileHandle temp = file; + FileHandle original = getFileHandle( defaultFileType, "", temp.path().replace(".tmp", "") ); + + //replace the base file with the temp one if base is invalid or temp is valid and newer + try { + bundleFromStream(temp.read()); + + try { + bundleFromStream(original.read()); + + if (temp.lastModified() > original.lastModified()) { + temp.moveTo(original); + } else { + temp.delete(); + } + + } catch (Exception e) { + temp.moveTo(original); + } + + } catch (Exception e) { + temp.delete(); + } + + foundTemp = true; + } + } + } + return foundTemp; + } public static boolean fileExists( String name ){ FileHandle file = getFileHandle( name ); @@ -119,7 +163,19 @@ public class FileUtils { //only works for base path public static void bundleToFile( String fileName, Bundle bundle ) throws IOException{ try { - bundleToStream(getFileHandle( fileName ).write(false), bundle); + FileHandle file = getFileHandle(fileName); + + //write to a temp file, then move the files. + // This helps prevent save corruption if writing is interrupted + if (file.exists()){ + FileHandle temp = getFileHandle(fileName + ".tmp"); + bundleToStream(temp.write(false), bundle); + file.delete(); + temp.moveTo(file); + } else { + bundleToStream(file.write(false), bundle); + } + } catch (GdxRuntimeException e){ //game classes expect an IO exception, so wrap the GDX exception in that throw new IOException(e); diff --git a/core/src/main/assets/messages/scenes/scenes.properties b/core/src/main/assets/messages/scenes/scenes.properties index eda909cbd..6db0dc329 100644 --- a/core/src/main/assets/messages/scenes/scenes.properties +++ b/core/src/main/assets/messages/scenes/scenes.properties @@ -110,3 +110,4 @@ scenes.welcomescene.lang_warning_title=Incomplete Translation scenes.welcomescene.lang_warning_msg=Some of the new content from this update has not yet been translated.\n\nSome phrases may be written in English.\n\nThe translation teams are working to resolve this and a full translation should be patched in soon.\n\nThank you for your patience. scenes.welcomescene.continue=Continue scenes.welcomescene.changelist=Changelist +scenes.welcomescene.save_warning=Shattered Pixel Dungeon was interrupted while trying to save your game data recently.\n\nShattered has built-in protections against this, so your game data is probably fine. You may want to check to be sure.\n\nThis usually happens when your device suddenly loses power, or if it terminates Shattered without letting it close properly. Battery saver features can often cause this on mobile devices. \ No newline at end of file diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java index 690216c95..630b9ad95 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java @@ -38,6 +38,9 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.Archs; import com.shatteredpixel.shatteredpixeldungeon.ui.Icons; import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; import com.shatteredpixel.shatteredpixeldungeon.ui.StyledButton; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndError; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndHardNotification; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndMessage; import com.watabou.glwrap.Blending; import com.watabou.noosa.Camera; import com.watabou.noosa.ColorBlock; @@ -58,6 +61,21 @@ public class WelcomeScene extends PixelScene { final int previousVersion = SPDSettings.version(); + if (FileUtils.cleanTempFiles()){ + add(new WndHardNotification(Icons.get(Icons.WARNING), + Messages.get(WndError.class, "title"), + Messages.get(this, "save_warning"), + Messages.get(this, "continue"), + 5){ + @Override + public void hide() { + super.hide(); + ShatteredPixelDungeon.resetScene(); + } + }); + return; + } + if (ShatteredPixelDungeon.versionCode == previousVersion && !SPDSettings.intro()) { ShatteredPixelDungeon.switchNoFade(TitleScene.class); return;