/**
* Copyright (C) 2013 Gundog Studios LLC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.godsandtowers;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.godsandtowers.core.GameEngine;
import com.godsandtowers.core.GameInfo;
import com.godsandtowers.core.HostGameEngine;
import com.godsandtowers.graphics.game.GameLayoutManager;
import com.godsandtowers.messaging.GLMessageProcessor;
import com.godsandtowers.messaging.LogicHandler;
import com.godsandtowers.messaging.LogicMessageProcessor;
import com.gundogstudios.modules.AssetModule;
import com.gundogstudios.modules.Modules;
public class GameStateManager {
private static final String TAG = "GameStateManager";
private ExecutorService gameEngineExecutor;
private Future<Boolean> future;
private GameEngine engine;
private Activity activity;
private GameLayoutManager gameLayoutManager;
public GameStateManager(Activity activity) {
this.activity = activity;
gameEngineExecutor = Executors.newSingleThreadExecutor();
}
private GameLayoutManager getGameLayoutManager() {
if (gameLayoutManager == null) {
gameLayoutManager = new GameLayoutManager(activity);
}
return gameLayoutManager;
}
public void clearGL() {
getGameLayoutManager().clearGL();
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
return getGameLayoutManager().onKeyUp(keyCode, event);
}
public boolean canRun() {
return engine != null;
}
public boolean isRunning() {
return future != null && !future.isDone();
}
public void init(GameEngine engine) {
this.engine = engine;
getGameLayoutManager().setPlayers(engine.getGameInfo());
getGameLayoutManager().setDefaults();
Modules.MESSENGER.register(LogicMessageProcessor.ID, new LogicHandler(engine));
AssetModule assetModule = Modules.ASSETS;
Modules.LOG.info(TAG, "Deleting previous file " + assetModule.delete("", MainActivity.SAVE_GAME_FILENAME));
}
public void tryLoad(Activity activity, Bundle savedInstanceState) {
Modules.LOG.info(TAG, "tryLoad");
GameInfo info = null;
AssetModule assetModule = Modules.ASSETS;
try {
InputStream fin = assetModule.openInput("", MainActivity.SAVE_GAME_FILENAME);
ObjectInputStream oin = new ObjectInputStream(fin);
long start = System.currentTimeMillis();
info = (GameInfo) oin.readObject();
Modules.LOG.info(TAG, "Took " + (System.currentTimeMillis() - start) + " to load the game");
fin.close();
} catch (Exception e) {
Modules.LOG.info(
TAG,
"Failed to load previous save, deleting file "
+ assetModule.delete("", MainActivity.SAVE_GAME_FILENAME));
}
if (info != null) {
HostGameEngine engine = new HostGameEngine(info, null);
init(engine);
}
}
public void saveInstanceState(Bundle outState) {
Modules.LOG.info(TAG, "onSaveInstanceState");
if (isRunning()) {
pause();
}
}
public void resume() {
Modules.LOG.info(TAG, "resume");
if (future == null || future.isDone())
future = gameEngineExecutor.submit(engine, true);
getGameLayoutManager().onResume();
}
public void pause() {
Modules.LOG.info(TAG, "pause");
getGameLayoutManager().onPause();
if (isRunning()) {
try {
synchronized (engine) {
if (!engine.hasExited() && !engine.isPaused()) {
engine.setPaused(true);
engine.wait();
}
}
} catch (InterruptedException e) {
Modules.LOG.info(TAG, "Failed to pause game due to interruption\n" + e.toString());
}
}
}
public void save() {
Modules.LOG.info(TAG, "save");
pause();
if (isRunning() && engine.isSaveable()) {
try {
AssetModule assetModule = Modules.ASSETS;
OutputStream fout = assetModule.openOutput("", MainActivity.SAVE_GAME_FILENAME);
ObjectOutputStream oout = new ObjectOutputStream(fout);
long start = System.currentTimeMillis();
oout.writeObject(engine.getGameInfo());
Modules.LOG.info(TAG, "Took " + (System.currentTimeMillis() - start) + " to save the game");
fout.close();
} catch (IOException e) {
Modules.LOG.info(TAG, "Failed to save game due to ioexception\n" + e.toString());
}
}
}
public void shutdownNow() {
getGameLayoutManager().onPause();
if (engine != null)
engine.quitGame();
if (gameEngineExecutor != null)
gameEngineExecutor.shutdownNow();
Modules.MESSENGER.submit(GLMessageProcessor.ID, GLMessageProcessor.SHUTDOWN);
}
public void shutdown() {
Modules.LOG.info(TAG, "shutdown");
getGameLayoutManager().onPause();
if (isRunning()) {
try {
synchronized (engine) {
if (!engine.hasExited()) {
engine.quitGame();
engine.wait();
}
}
} catch (InterruptedException e) {
Modules.LOG.info(TAG, "Failed to shutdown game engine due to interruption\n" + e.toString());
}
}
engine = null;
}
}