From 6fed28804a235196b40f9fce7c8b9dcfb90f8821 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Latner?= <matyas.latner@nic.cz>
Date: Wed, 21 Oct 2015 15:53:44 +0200
Subject: [PATCH] Fixed restoring of screen state and ability to restore
 application after screen loading failure

---
 core/src/cz/nic/tablexia/Tablexia.java        |  9 -----
 .../cz/nic/tablexia/TablexiaApplication.java  | 30 +++++++++++---
 core/src/cz/nic/tablexia/TablexiaStorage.java |  6 +--
 .../tablexia/game/AbstractTablexiaGame.java   | 30 ++++++++++----
 .../games/robbery/AbstractRobberyScreen.java  |  6 +--
 .../game/games/robbery/RobberyGame.java       |  1 -
 .../screen/AbstractTablexiaScreen.java        | 39 ++++++-------------
 .../screen/createuser/FormScreen.java         |  5 +++
 .../screen/createuser/PanoramaScreen.java     |  5 +++
 .../tablexia/screen/loader/LoaderScreen.java  | 10 ++++-
 .../viewport/FullscreenImageDebugScreen.java  |  5 ++-
 11 files changed, 86 insertions(+), 60 deletions(-)

diff --git a/core/src/cz/nic/tablexia/Tablexia.java b/core/src/cz/nic/tablexia/Tablexia.java
index d803f7b84..7bb3db82f 100644
--- a/core/src/cz/nic/tablexia/Tablexia.java
+++ b/core/src/cz/nic/tablexia/Tablexia.java
@@ -214,15 +214,6 @@ public class Tablexia extends TablexiaApplication {
         startLoading(TablexiaSettings.getInstance().getLocale());
     }
 
-    @Override
-    public void pause() {
-        if (menuController != null && getScreen() != null && getScreen().canBePaused()) {
-            // don't use menu open animation for android and iOS pause event (animation is run after resume)
-            menuController.doMenuAction(MainMenu.class, AbstractMenu.MenuAction.OPEN, Gdx.app.getType().equals(Application.ApplicationType.Desktop), false);
-        }
-        super.pause();
-    }
-
     @Override
     public void render() {
         // render other screens
diff --git a/core/src/cz/nic/tablexia/TablexiaApplication.java b/core/src/cz/nic/tablexia/TablexiaApplication.java
index 1c160a63e..70bdaf0ba 100644
--- a/core/src/cz/nic/tablexia/TablexiaApplication.java
+++ b/core/src/cz/nic/tablexia/TablexiaApplication.java
@@ -25,6 +25,7 @@ import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
 import cz.nic.tablexia.menu.MenuController;
 import cz.nic.tablexia.screen.AbstractTablexiaScreen;
 import cz.nic.tablexia.screen.AbstractTablexiaScreen.ScreenLoadingListener;
+import cz.nic.tablexia.util.Log;
 
 import static com.badlogic.gdx.scenes.scene2d.actions.Actions.fadeIn;
 import static com.badlogic.gdx.scenes.scene2d.actions.Actions.fadeOut;
@@ -272,7 +273,7 @@ public abstract class TablexiaApplication implements ApplicationListener {
      * @param newScreen         new screen to change for
      * @param screenTransaction screen transaction type
      */
-    public void setScreen(final AbstractTablexiaScreen<?> newScreen, ScreenTransaction screenTransaction) {
+    public void setScreen(final AbstractTablexiaScreen<?> newScreen, final ScreenTransaction screenTransaction) {
         if (screenTransaction == null) {
             setScreen(newScreen);
         } else {
@@ -301,7 +302,7 @@ public abstract class TablexiaApplication implements ApplicationListener {
                     new Runnable() {
                         @Override
                         public void run() {
-                            newScreen.performScreenVisible();
+                            processScreenVisible(screen);
                         }
                     });
         }
@@ -319,10 +320,14 @@ public abstract class TablexiaApplication implements ApplicationListener {
     @SuppressWarnings("unchecked")
     private void processNewScreen(AbstractTablexiaScreen<?> newScreen) {
         if (newScreen != null) {
-            inputMultiplexer.addProcessor(newScreen.getInputProcessor());
-            newScreen.show();
-            newScreen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
-            ApplicationBus.getInstance().post(new ScreenChangedEvent((Class<? extends AbstractTablexiaScreen<?>>) newScreen.getClass())).asynchronously();
+            try {
+                inputMultiplexer.addProcessor(newScreen.getInputProcessor());
+                newScreen.show();
+                newScreen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+                ApplicationBus.getInstance().post(new ScreenChangedEvent((Class<? extends AbstractTablexiaScreen<?>>) newScreen.getClass())).asynchronously();
+            } catch (Throwable t) {
+                performScreenLoadingErrorAction(newScreen, t);
+            }
         }
     }
 
@@ -336,6 +341,19 @@ public abstract class TablexiaApplication implements ApplicationListener {
         }
     }
 
+    private void processScreenVisible(AbstractTablexiaScreen<?> lastScreen) {
+        try {
+            lastScreen.performScreenVisible();
+        } catch (Throwable t) {
+            performScreenLoadingErrorAction(lastScreen, t);
+        }
+    }
+
+    private void performScreenLoadingErrorAction(AbstractTablexiaScreen<?> screen, Throwable t) {
+        Log.err(TablexiaApplication.this.getClass(), "Cannot load screen: " + screen.getClass(), t);
+        ApplicationBus.getInstance().post(new Tablexia.ChangeScreenEvent(TablexiaSettings.INITIAL_SCREEN, ScreenTransaction.FADE)).asynchronously();
+    }
+
 
 //////////////////////////// SCREEN TRANSACTIONS
 
diff --git a/core/src/cz/nic/tablexia/TablexiaStorage.java b/core/src/cz/nic/tablexia/TablexiaStorage.java
index a5c62d13a..5c6291475 100644
--- a/core/src/cz/nic/tablexia/TablexiaStorage.java
+++ b/core/src/cz/nic/tablexia/TablexiaStorage.java
@@ -186,7 +186,7 @@ public class TablexiaStorage {
     }
 
     public void resetScreenState(AbstractTablexiaScreen screen) {
-        if (screen.hasState()) {
+        if (screen.canResetState()) {
             resetScreenState();
         }
     }
@@ -204,7 +204,7 @@ public class TablexiaStorage {
 
     public Map<String, String> loadScreenState(AbstractTablexiaScreen screen, User selectedUser) {
         Map<String, String> screenState = new HashMap<String, String>();
-        if (screen.hasState() && selectedUser != null) {
+        if (selectedUser != null) {
             try {
                 PreparedStatement statement = prepareStatement(SCREEN_STATE_SELECT);
                 statement.setString(STATE_QUERY_SCREEN_INDEX, screen.getClass().getName());
@@ -227,7 +227,7 @@ public class TablexiaStorage {
     }
 
     public void saveScreenState(AbstractTablexiaScreen screen, Map<String, String> screenState, User selectedUser) {
-        if (screen.hasState() && selectedUser != null) {
+        if (selectedUser != null) {
             try {
                 connection.setAutoCommit(false);
                 resetScreenState();
diff --git a/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java b/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java
index b89a1ba82..e28d3d2be 100644
--- a/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java
+++ b/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java
@@ -138,11 +138,6 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T>
     private boolean             inGameLoading;
 
     public AbstractTablexiaGame() {
-        this(true);
-    }
-
-    public AbstractTablexiaGame(boolean screenState) {
-        super(screenState);
         inGameLoading = false;
         gamePhase = GamePhase.PREPARED;
     }
@@ -150,16 +145,36 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T>
 
 //////////////////////////// SCREEN PAUSE
 
+    @Override
     public boolean canBePaused() {
         return gamePhase.isPause();
     }
 
+    @Override
+    public boolean canStopActions () {
+        return true;
+    }
+
+    @Handler
+    public void handleMenuPauseEvent(AbstractMenu.MenuPauseEvent menuPauseEvent) {
+        if (menuPauseEvent.isPause()) {
+            performScreenPaused();
+        } else {
+            performScreenResumed();
+        }
+    }
+
 
 //////////////////////////// ABSTRACT TABLEXIA SCREEN LIFECYCLE
 
     @Override
     protected final void screenLoaded(final Map<String, String> screenState) {
-        performGameLoaded(screenState);
+        try {
+            performGameLoaded(screenState);
+        } catch (Throwable t) {
+            Log.err(getClass(), "Cannot resume screen state!", t);
+            TablexiaStorage.getInstance().resetScreenState(this);
+        }
         if(inGameLoading) {
             performShowTransaction(new Runnable() {
                 @Override
@@ -208,6 +223,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T>
     @Override
     protected final void screenPaused(Map<String, String> screenState) {
         if (gamePhase == GamePhase.STARTED) {
+            ApplicationBus.getInstance().post(new MenuControlEvent(AbstractMenu.MenuAction.OPEN, true)).asynchronously();
             performGamePaused(screenState);
             screenState.put(GAME_STATE_GAME_ID, String.valueOf(game.getId()));
             Log.info(getClass(), "[DB] Stored game object to screen state: " + game);
@@ -241,7 +257,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T>
         game = null;
 
         //load game db object from screen state
-        if (screenState != null) {
+        if (screenState.size() > 0) {
             // restore from game state
             String gameIdStr = screenState.get(GAME_STATE_GAME_ID);
             game = gameIdStr != null ? Game.getGameForId(Long.valueOf(gameIdStr)) : null;
diff --git a/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java b/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java
index 0e07347d6..0f0283ecf 100644
--- a/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java
+++ b/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java
@@ -15,7 +15,6 @@ public abstract class AbstractRobberyScreen extends AbstractTablexiaScreen<GameR
 	private RobberyGame robberyGame;
 
 	public AbstractRobberyScreen(RobberyGame robberyGame) {
-        super(false);
 		this.robberyGame = robberyGame;
 	}
 
@@ -37,8 +36,9 @@ public abstract class AbstractRobberyScreen extends AbstractTablexiaScreen<GameR
 
 //////////////////////////// SCREEN PAUSE
 
-    public boolean canBePaused() {
-        return true;
+    @Override
+    public boolean isScreenPaused() {
+        return robberyGame.isScreenPaused();
     }
 
 
diff --git a/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java b/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java
index af090f5ae..cf184cc61 100644
--- a/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java
+++ b/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java
@@ -196,7 +196,6 @@ public class RobberyGame extends AbstractTablexiaGame<GameRule> {
 
 //////////////////////////// ABSTRACT TABLEXIA GAME
 
-
 	@Override
 	protected List<SummaryMessage> getSummaryMessageForGameResult(Game game) {
 		String identification = game.getUser().getGender() == User.Gender.MALE ? getText(SUMMARY_IDENTIFICATION_MALE_TEXT_KEY) : getText(SUMMARY_IDENTIFICATION_FEMALE_TEXT_KEY);
diff --git a/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java b/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java
index f1314d603..5162e91c4 100644
--- a/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java
+++ b/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java
@@ -16,8 +16,6 @@ import com.badlogic.gdx.utils.Disposable;
 import com.badlogic.gdx.utils.I18NBundle;
 import com.badlogic.gdx.utils.async.AsyncTask;
 
-import net.engio.mbassy.listener.Handler;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -35,14 +33,12 @@ import cz.nic.tablexia.TablexiaSettings;
 import cz.nic.tablexia.TablexiaStorage;
 import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.bus.ApplicationBus.ApplicationEvent;
-import cz.nic.tablexia.bus.event.MenuControlEvent;
 import cz.nic.tablexia.loader.TablexiaAbstractFileManager;
 import cz.nic.tablexia.loader.TablexiaAtlasManager;
 import cz.nic.tablexia.loader.TablexiaDataManager;
 import cz.nic.tablexia.loader.TablexiaSoundManager;
 import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
 import cz.nic.tablexia.loader.application.ApplicationFontManager;
-import cz.nic.tablexia.menu.AbstractMenu;
 import cz.nic.tablexia.model.User;
 import cz.nic.tablexia.util.Log;
 import cz.nic.tablexia.util.Utility;
@@ -162,7 +158,6 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
     private boolean                                       loadingComplete;
     private boolean                                       loadingStarted;
     private boolean                                       loadAsync;
-    private boolean                                       hasState;
     private TablexiaAbstractFileManager.AssetsStorageType storageType;
 
     private Map<String, Music> notDisposedMusics;
@@ -249,16 +244,11 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
 
 
     public AbstractTablexiaScreen() {
-        this(true, true, TablexiaAbstractFileManager.AssetsStorageType.EXTERNAL);
-    }
-
-    public AbstractTablexiaScreen(boolean hasState) {
-        this(hasState, true, TablexiaAbstractFileManager.AssetsStorageType.EXTERNAL);
+        this(true, TablexiaAbstractFileManager.AssetsStorageType.EXTERNAL);
     }
 
-    public AbstractTablexiaScreen(boolean hasState, boolean loadAsync, TablexiaAbstractFileManager.AssetsStorageType storageType) {
+    public AbstractTablexiaScreen(boolean loadAsync, TablexiaAbstractFileManager.AssetsStorageType storageType) {
         stage = prepareStage();
-        this.hasState = hasState;
         this.loadAsync = loadAsync;
         this.storageType = storageType;
         atlasManager = new TablexiaAtlasManager(storageType);
@@ -281,27 +271,23 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
         dataManager.setInitialState(initialState);
     }
 
-    public boolean hasState() {
-        return hasState;
-    }
 
 //////////////////////////// SCREEN PAUSE
 
     public boolean canBePaused() {
+        return true;
+    }
+
+    public boolean canStopActions () {
         return false;
     }
 
-    protected boolean isScreenPaused() {
-        return canBePaused() && isScreenPaused;
+    public boolean canResetState () {
+        return true;
     }
 
-    @Handler
-    public void handleMenuPauseEvent(AbstractMenu.MenuPauseEvent menuPauseEvent) {
-        if (menuPauseEvent.isPause()) {
-            performScreenPaused();
-        } else {
-            performScreenResumed();
-        }
+    public boolean isScreenPaused() {
+        return canBePaused() && isScreenPaused && canStopActions();
     }
 
 
@@ -412,7 +398,6 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
     public void pause() {
         if (loadingComplete && canBePaused() && !isScreenPaused()) {
             performScreenPaused();
-            ApplicationBus.getInstance().post(new MenuControlEvent(AbstractMenu.MenuAction.OPEN, true)).asynchronously();
         }
     }
 
@@ -464,7 +449,7 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
         screenResized(width, height);
     }
 
-    private final void performScreenPaused() {
+    protected final void performScreenPaused() {
         if (!isScreenPaused) {
             isScreenPaused = true;
             Log.info(getClass(), "[ ------- Screen Paused ------- ]");
@@ -475,7 +460,7 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
         }
     }
 
-    private final void performScreenResumed() {
+    protected final void performScreenResumed() {
         if (isScreenPaused) {
             isScreenPaused = false;
             Log.info(getClass(), "[ ------- Screen Resumed ------- ]");
diff --git a/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java b/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java
index 639331154..929cb0430 100644
--- a/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java
+++ b/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java
@@ -57,6 +57,11 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
     private String mugshot;
 //    private User user = new User();
 
+    @Override
+    public boolean canBePaused() {
+        return false;
+    }
+
     @Override
     protected void screenLoaded(Map<String, String> screenState) {
         getStage().setDebugAll(TablexiaSettings.getInstance().isShowBoundingBoxes());
diff --git a/core/src/cz/nic/tablexia/screen/createuser/PanoramaScreen.java b/core/src/cz/nic/tablexia/screen/createuser/PanoramaScreen.java
index dc9cc8922..a31f82215 100644
--- a/core/src/cz/nic/tablexia/screen/createuser/PanoramaScreen.java
+++ b/core/src/cz/nic/tablexia/screen/createuser/PanoramaScreen.java
@@ -63,6 +63,11 @@ public class PanoramaScreen extends AbstractTablexiaScreen<int[][]> {
 
     private TextureRegion clickmap;
 
+    @Override
+    public boolean canBePaused() {
+        return false;
+    }
+
     @Override
     protected int[][] prepareScreenData(Map<String, String> screenState) {
         clickmap = getScreenTextureRegion(GFX_PATH + "newspaper/clickmap");
diff --git a/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java b/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java
index c98a4d4c8..5fad63d40 100644
--- a/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java
+++ b/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java
@@ -18,8 +18,14 @@ public class LoaderScreen extends AbstractTablexiaScreen<Void> {
     private static final String LOADER_SMALL_HAND   = BASE_PATH + "screen_loader_smallhand.png";
     private static final String LOADER_BIG_HAND     = BASE_PATH + "screen_loader_bighand.png";
 
-    public LoaderScreen() {
-        super(false);
+    @Override
+    public boolean canBePaused() {
+        return false;
+    }
+
+    @Override
+    public boolean canResetState() {
+        return false;
     }
 
     @Override
diff --git a/core/src/cz/nic/tablexia/screen/viewport/FullscreenImageDebugScreen.java b/core/src/cz/nic/tablexia/screen/viewport/FullscreenImageDebugScreen.java
index 33ba9b3ed..d1c1e6b7f 100644
--- a/core/src/cz/nic/tablexia/screen/viewport/FullscreenImageDebugScreen.java
+++ b/core/src/cz/nic/tablexia/screen/viewport/FullscreenImageDebugScreen.java
@@ -16,8 +16,9 @@ public class FullscreenImageDebugScreen extends AbstractTablexiaScreen<Void> {
     private static final String LOADER_SMALL_HAND   = BASE_PATH + "screen_loader_smallhand.png";
     private static final String LOADER_BIG_HAND     = BASE_PATH + "screen_loader_bighand.png";
 
-    public FullscreenImageDebugScreen() {
-        super(false);
+    @Override
+    public boolean canBePaused() {
+        return false;
     }
 
     @Override
-- 
GitLab