v1.2.0: improved how the game handles being interrupted while saving

This commit is contained in:
Evan Debenham 2022-01-27 15:49:29 -05:00
parent 6b4d608022
commit 90b8ff9a66
3 changed files with 76 additions and 1 deletions

View File

@ -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);

View File

@ -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.

View File

@ -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;