From: <ste...@us...> - 2011-07-06 05:39:23
|
Revision: 1605 http://rails.svn.sourceforge.net/rails/?rev=1605&view=rev Author: stefanfrey Date: 2011-07-06 05:39:16 +0000 (Wed, 06 Jul 2011) Log Message: ----------- Refactored save and load code into GameFileIO and GameData classes Modified Paths: -------------- trunk/18xx/rails/game/Game.java trunk/18xx/rails/game/GameManager.java trunk/18xx/rails/util/ListAndFixSavedFiles.java Added Paths: ----------- trunk/18xx/rails/util/GameData.java trunk/18xx/rails/util/GameFileIO.java Removed Paths: ------------- trunk/18xx/rails/util/GameLoader.java Modified: trunk/18xx/rails/game/Game.java =================================================================== --- trunk/18xx/rails/game/Game.java 2011-07-05 17:03:23 UTC (rev 1604) +++ trunk/18xx/rails/game/Game.java 2011-07-06 05:39:16 UTC (rev 1605) @@ -13,7 +13,7 @@ import rails.common.parser.GameFileParser; import rails.common.parser.GameOption; import rails.game.action.PossibleAction; -import rails.util.GameLoader; +import rails.util.GameFileIO; public class Game { public static final String version = "1.4.1+"; @@ -124,7 +124,7 @@ public static Game load(String filepath) { // use GameLoader object to load game - GameLoader gameLoader = new GameLoader(); + GameFileIO gameLoader = new GameFileIO(); gameLoader.loadGameData(filepath); try{ gameLoader.initGame(); Modified: trunk/18xx/rails/game/GameManager.java =================================================================== --- trunk/18xx/rails/game/GameManager.java 2011-07-05 17:03:23 UTC (rev 1604) +++ trunk/18xx/rails/game/GameManager.java 2011-07-06 05:39:16 UTC (rev 1605) @@ -1115,31 +1115,11 @@ } protected boolean save(File file, boolean displayErrorMessage, String errorMessageKey) { - boolean result = false; - - try { - ObjectOutputStream oos = - new ObjectOutputStream(new FileOutputStream(file)); - oos.writeObject(Game.version+" "+BuildInfo.buildDate); - oos.writeObject(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); - oos.writeObject(saveFileVersionID); - oos.writeObject(gameName); - oos.writeObject(gameOptions); - oos.writeObject(playerNames); - for (PossibleAction action : executedActions) { - oos.writeObject(action); - } - oos.writeObject(ReportBuffer.getCommentItems()); - oos.close(); - - result = true; - } catch (IOException e) { - log.error(errorMessageKey, e); - if (displayErrorMessage) { - DisplayBuffer.add(LocalText.getText("SaveFailed", e.getMessage())); - } - } - return result; + GameFileIO gameSaver = new GameFileIO(); + gameSaver.initSave(saveFileVersionID, gameName, gameOptions, playerNames); + gameSaver.setActions(executedActions); + gameSaver.setComments(ReportBuffer.getCommentItems()); + return gameSaver.saveGame(file, displayErrorMessage, errorMessageKey); } /** * tries to reload the current game @@ -1149,7 +1129,7 @@ log.info("Reloading started"); /* Use gameLoader to load the game data */ - GameLoader gameLoader = new GameLoader(); + GameFileIO gameLoader = new GameFileIO(); String filepath = reloadAction.getFilepath(); gameLoader.loadGameData(filepath); Added: trunk/18xx/rails/util/GameData.java =================================================================== --- trunk/18xx/rails/util/GameData.java (rev 0) +++ trunk/18xx/rails/util/GameData.java 2011-07-06 05:39:16 UTC (rev 1605) @@ -0,0 +1,57 @@ +package rails.util; + +import java.util.List; +import java.util.Map; +import java.util.SortedMap; + +import rails.game.action.PossibleAction; + +/** + * Combines all fields required for game IO + * Defines the complete game + * + * @author freystef + * */ + + +class GameData { + class MetaData { + String version; + String date; + Long fileVersionID; + String gameName; + }; + + MetaData meta = new MetaData(); + Map<String, String> gameOptions; + List<String> playerNames; + List<PossibleAction> actions; + SortedMap<Integer, String> userComments; + + String metaDataAsText() { + StringBuilder s = new StringBuilder(); + s.append("Rails saveVersion = " + meta.version + "\n"); + s.append("File was saved at " + meta.date + "\n"); + s.append("Saved versionID=" + meta.fileVersionID + "\n"); + s.append("Save game=" + meta.gameName + "\n"); + return s.toString(); + } + + String gameOptionsAsText() { + StringBuilder s = new StringBuilder(); + for (String key : gameOptions.keySet()) { + s.append("Option "+key+"="+gameOptions.get(key)+ "\n"); + } + return s.toString(); + } + String playerNamesAsText() { + StringBuilder s = new StringBuilder(); + int i=1; + for (String player : playerNames) { + s.append("Player "+(i++)+": "+player + "\n"); + } + return s.toString(); + } + + +} Property changes on: trunk/18xx/rails/util/GameData.java ___________________________________________________________________ Added: svn:mime-type + text/plain Copied: trunk/18xx/rails/util/GameFileIO.java (from rev 1604, trunk/18xx/rails/util/GameLoader.java) =================================================================== --- trunk/18xx/rails/util/GameFileIO.java (rev 0) +++ trunk/18xx/rails/util/GameFileIO.java 2011-07-06 05:39:16 UTC (rev 1605) @@ -0,0 +1,296 @@ +package rails.util; + +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +import rails.common.DisplayBuffer; +import rails.common.LocalText; +import rails.common.parser.ConfigurationException; +import rails.game.Game; +import rails.game.GameManager; +import rails.game.GameManagerI; +import rails.game.ReportBuffer; +import rails.game.action.PossibleAction; + +/** + * Functions to load and save games from/to file + * + * @author freystef + * + */ +public class GameFileIO { + + protected static Logger log = + Logger.getLogger(Game.class.getPackage().getName()); + + private GameData gameData = new GameData(); + + // fields for data load + private ObjectInputStream ois = null; + private Game loadedGame = null; + private boolean dataLoadDone = false; + private boolean initialized = false; + + // fields for data save + private boolean initSave = false; + + public String getGameDataAsText() { + return gameData.metaDataAsText() + gameData.gameOptionsAsText() + gameData.playerNamesAsText(); + } + + public Game getGame() { + return loadedGame; + } + + public List<PossibleAction> getActions() { + return gameData.actions; + } + + public void setActions(List<PossibleAction> actions) { + gameData.actions = actions; + } + + public SortedMap<Integer, String> getComments() { + return gameData.userComments; + } + + public void setComments(SortedMap<Integer, String> comments) { + gameData.userComments = comments; + } + + @SuppressWarnings("unchecked") + public void loadGameData(String filepath) { + + dataLoadDone = true; + + log.info("Loading game from file " + filepath); + String filename = filepath.replaceAll(".*[/\\\\]", ""); + + try { + ois = new ObjectInputStream(new FileInputStream( + new File(filepath))); + + Object object = ois.readObject(); + if (object instanceof String) { + // New in 1.0.7: Rails version & save date/time. + gameData.meta.version = (String)object; + object = ois.readObject(); + } else { + // Allow for older saved file versions. + gameData.meta.version = "pre-1.0.7"; + } + + log.info("Reading Rails " + gameData.meta.version +" saved file "+filename); + + if (object instanceof String) { + gameData.meta.date = (String)object; + log.info("File was saved at "+ gameData.meta.date); + object = ois.readObject(); + } + + // read versionID for serialization compatibility + gameData.meta.fileVersionID = (Long) object; + log.debug("Saved versionID="+gameData.meta.fileVersionID+" (object="+object+")"); + long GMsaveFileVersionID = GameManager.saveFileVersionID; + + if (gameData.meta.fileVersionID != GMsaveFileVersionID) { + throw new Exception("Save version " + gameData.meta.fileVersionID + + " is incompatible with current version " + + GMsaveFileVersionID); + } + + // read name of saved game + gameData.meta.gameName = (String) ois.readObject(); + log.debug("Saved game="+ gameData.meta.gameName); + + // read selected game options and player names + gameData.gameOptions = (Map<String, String>) ois.readObject(); + log.debug("Selected game options = " + gameData.gameOptions); + gameData.playerNames = (List<String>) ois.readObject(); + log.debug("Player names = " + gameData.playerNames); + + } catch (Exception e) { + dataLoadDone = false; + log.fatal("Load failed", e); + DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); + } + } + + public Game initGame() throws ConfigurationException { + + // check if initial load was done + if (!dataLoadDone) { + throw new ConfigurationException("No game was loaded"); + } + + // initialize loadedGame + loadedGame = new Game(gameData.meta.gameName, gameData.playerNames, gameData.gameOptions); + + if (!loadedGame.setup()) { + loadedGame = null; + throw new ConfigurationException("Error in setting up " + gameData.meta.gameName); + } + + String startError = loadedGame.start(); + if (startError != null) { + DisplayBuffer.add(startError); + } + + return loadedGame; + } + + + @SuppressWarnings("unchecked") + public boolean loadActionsAndComments() throws ConfigurationException { + if (!dataLoadDone) { + throw new ConfigurationException("No game was loaded"); + } + // Read game actions into gameData.listOfActions + try { + // read next object in stream + Object actionObject = null; + while (true) { // Single-pass loop. + try { + actionObject = ois.readObject(); + } catch (EOFException e) { + // Allow saved file at start of game (with no actions). + break; + + } + if (actionObject instanceof List) { + // Until Rails 1.3: one List of PossibleAction + gameData.actions = (List<PossibleAction>) actionObject; + } else if (actionObject instanceof PossibleAction) { + gameData.actions = new ArrayList<PossibleAction>(); + // Since Rails 1.3.1: separate PossibleActionsObjects + while (actionObject instanceof PossibleAction) { + gameData.actions.add((PossibleAction)actionObject); + try { + actionObject = ois.readObject(); + } catch (EOFException e) { + break; + } + } + } + break; + } + /** + todo: the code below is far from perfect, but robust + */ + + // init user comments to have a defined object in any case + gameData.userComments = new TreeMap<Integer,String>(); + + // at the end of file user comments are added as SortedMap + if (actionObject instanceof SortedMap) { + gameData.userComments = (SortedMap<Integer, String>) actionObject; + log.debug("file load: found user comments"); + } else { + try { + Object object = ois.readObject(); + if (object instanceof SortedMap) { + gameData.userComments = (SortedMap<Integer, String>) actionObject; + log.debug("file load: found user comments"); + } + } catch (IOException e) { + // continue without comments, if any IOException occurs + // sometimes not only the EOF Exception is raised + // but also the java.io.StreamCorruptedException: invalid type code + } + } + ois.close(); + ois = null; + initialized = true; + } catch (Exception e) { + log.fatal("Load failed", e); + DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); + initialized = false; + } + return initialized; + } + + public void replayGame() throws Exception { + if (!initialized) { + throw new ConfigurationException("No game was loaded/initialized"); + } + + GameManagerI gameManager = loadedGame.getGameManager(); + log.debug("Starting to execute loaded actions"); + gameManager.setReloading(true); + + for (PossibleAction action : gameData.actions) { + if (!gameManager.processOnReload(action)) { + log.error ("Load interrupted"); + DisplayBuffer.add(LocalText.getText("LoadInterrupted")); + break; + } + } + + gameManager.setReloading(false); + ReportBuffer.setCommentItems(gameData.userComments); + + // callback to GameManager + gameManager.finishLoading(); + } + + /** + * sets the meta data required for a game save + */ + public void initSave(Long saveFileVersionID, String gameName, Map<String, String> gameOptions, List<String> playerNames) { + gameData.meta.version = Game.version+" "+BuildInfo.buildDate; + gameData.meta.date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); + gameData.meta.fileVersionID = saveFileVersionID; + gameData.meta.gameName = gameName; + gameData.gameOptions = gameOptions; + gameData.playerNames = playerNames; + initSave = true; + } + + /** + * Stores the game to a file + * requires initSave and setting actions and comments + */ + public boolean saveGame(File file, boolean displayErrorMessage, String errorMessageKey) { + if (!initSave || gameData.actions == null) return false; + boolean result = false; + + try { + ObjectOutputStream oos = + new ObjectOutputStream(new FileOutputStream(file)); + oos.writeObject(gameData.meta.version); + oos.writeObject(gameData.meta.date); + oos.writeObject(gameData.meta.fileVersionID); + oos.writeObject(gameData.meta.gameName); + oos.writeObject(gameData.gameOptions); + oos.writeObject(gameData.playerNames); + for (PossibleAction action : gameData.actions) { + oos.writeObject(action); + } + oos.writeObject(gameData.userComments); + oos.close(); + + result = true; + } catch (IOException e) { + log.error(errorMessageKey, e); + if (displayErrorMessage) { + DisplayBuffer.add(LocalText.getText("SaveFailed", e.getMessage())); + } + } + return result; + } + +} Property changes on: trunk/18xx/rails/util/GameFileIO.java ___________________________________________________________________ Added: svn:mime-type + text/plain Deleted: trunk/18xx/rails/util/GameLoader.java =================================================================== --- trunk/18xx/rails/util/GameLoader.java 2011-07-05 17:03:23 UTC (rev 1604) +++ trunk/18xx/rails/util/GameLoader.java 2011-07-06 05:39:16 UTC (rev 1605) @@ -1,252 +0,0 @@ -package rails.util; - -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -import rails.common.DisplayBuffer; -import rails.common.LocalText; -import rails.common.parser.ConfigurationException; -import rails.game.Game; -import rails.game.GameManager; -import rails.game.GameManagerI; -import rails.game.ReportBuffer; -import rails.game.action.PossibleAction; - -/** - * @author freystef - * - */ -public class GameLoader { - - protected static Logger log = - Logger.getLogger(Game.class.getPackage().getName()); - - private boolean dataLoadDone; - private boolean initialized; - - private ObjectInputStream ois; - - private String saveVersion; - private String saveDate; - private Long saveFileVersionID; - private String saveGameName; - private Map<String, String> selectedGameOptions; - private List<String> playerNames; - private List<PossibleAction> listOfActions; - private SortedMap<Integer, String> userComments; - - private Game loadedGame; - - public String getGameData() { - StringBuilder s = new StringBuilder(); - s.append("Rails saveVersion = " + saveVersion + "\n"); - s.append("File was saved at " + saveDate + "\n"); - s.append("Saved versionID=" + saveFileVersionID + "\n"); - s.append("Save game=" + saveGameName + "\n"); - for (String key : selectedGameOptions.keySet()) { - s.append("Option "+key+"="+selectedGameOptions.get(key)+ "\n"); - } - int i=1; - for (String player : playerNames) { - s.append("Player "+(i++)+": "+player + "\n"); - } - return s.toString(); - } - - public Game getGame() { - return loadedGame; - } - - public List<PossibleAction> getActions() { - return listOfActions; - } - - public SortedMap<Integer, String> getComments() { - return userComments; - } - - @SuppressWarnings("unchecked") - public void loadGameData(String filepath) { - - dataLoadDone = true; - log.info("Loading game from file " + filepath); - String filename = filepath.replaceAll(".*[/\\\\]", ""); - - try { - ois = new ObjectInputStream(new FileInputStream( - new File(filepath))); - - Object object = ois.readObject(); - if (object instanceof String) { - // New in 1.0.7: Rails version & save date/time. - saveVersion = (String)object; - object = ois.readObject(); - } else { - // Allow for older saved file versions. - saveVersion = "pre-1.0.7"; - } - - log.info("Reading Rails " + saveVersion +" saved file "+filename); - - if (object instanceof String) { - saveDate = (String)object; - log.info("File was saved at "+ saveDate); - object = ois.readObject(); - } - - // read versionID for serialization compatibility - saveFileVersionID = (Long) object; - log.debug("Saved versionID="+saveFileVersionID+" (object="+object+")"); - long GMsaveFileVersionID = GameManager.saveFileVersionID; - - if (saveFileVersionID != GMsaveFileVersionID) { - throw new Exception("Save version " + saveFileVersionID - + " is incompatible with current version " - + GMsaveFileVersionID); - } - - // read name of saved game - saveGameName = (String) ois.readObject(); - log.debug("Saved game="+ saveGameName); - - // read selected game options and player names - selectedGameOptions = (Map<String, String>) ois.readObject(); - log.debug("Selected game options = " + selectedGameOptions); - playerNames = (List<String>) ois.readObject(); - log.debug("Player names = " + playerNames); - - } catch (Exception e) { - log.fatal("Load failed", e); - DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); - } - - - } - - public Game initGame() throws ConfigurationException { - - // check if initial load was done - if (!dataLoadDone) { - throw new ConfigurationException("No game was loaded"); - } - - // initialize loadedGame - loadedGame = new Game(saveGameName, playerNames, selectedGameOptions); - - if (!loadedGame.setup()) { - loadedGame = null; - throw new ConfigurationException("Error in setting up " + saveGameName); - } - - String startError = loadedGame.start(); - if (startError != null) { - DisplayBuffer.add(startError); - } - - return loadedGame; - } - - - @SuppressWarnings("unchecked") - public boolean loadActionsAndComments() throws ConfigurationException { - if (!dataLoadDone) { - throw new ConfigurationException("No game was loaded"); - } - // Read game actions into listOfActions - try { - // read next object in stream - Object actionObject = null; - while (true) { // Single-pass loop. - try { - actionObject = ois.readObject(); - } catch (EOFException e) { - // Allow saved file at start of game (with no actions). - break; - - } - if (actionObject instanceof List) { - // Until Rails 1.3: one List of PossibleAction - listOfActions = (List<PossibleAction>) actionObject; - } else if (actionObject instanceof PossibleAction) { - listOfActions = new ArrayList<PossibleAction>(); - // Since Rails 1.3.1: separate PossibleActionsObjects - while (actionObject instanceof PossibleAction) { - listOfActions.add((PossibleAction)actionObject); - try { - actionObject = ois.readObject(); - } catch (EOFException e) { - break; - } - } - } - break; - } - /** - todo: the code below is far from perfect, but robust - */ - - // init user comments to have a defined object in any case - userComments = new TreeMap<Integer,String>(); - - // at the end of file user comments are added as SortedMap - if (actionObject instanceof SortedMap) { - userComments = (SortedMap<Integer, String>) actionObject; - log.debug("file load: found user comments"); - } else { - try { - Object object = ois.readObject(); - if (object instanceof SortedMap) { - userComments = (SortedMap<Integer, String>) actionObject; - log.debug("file load: found user comments"); - } - } catch (IOException e) { - // continue without comments, if any IOException occurs - // sometimes not only the EOF Exception is raised - // but also the java.io.StreamCorruptedException: invalid type code - } - } - ois.close(); - ois = null; - initialized = true; - } catch (Exception e) { - log.fatal("Load failed", e); - DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); - initialized = false; - } - return initialized; - } - - public void replayGame() throws Exception { - if (!initialized) { - throw new ConfigurationException("No game was loaded/initialized"); - } - - GameManagerI gameManager = loadedGame.getGameManager(); - log.debug("Starting to execute loaded actions"); - gameManager.setReloading(true); - - for (PossibleAction action : listOfActions) { - if (!gameManager.processOnReload(action)) { - log.error ("Load interrupted"); - DisplayBuffer.add(LocalText.getText("LoadInterrupted")); - break; - } - } - - gameManager.setReloading(false); - ReportBuffer.setCommentItems(userComments); - - // callback to GameManager - gameManager.finishLoading(); - } -} Modified: trunk/18xx/rails/util/ListAndFixSavedFiles.java =================================================================== --- trunk/18xx/rails/util/ListAndFixSavedFiles.java 2011-07-05 17:03:23 UTC (rev 1604) +++ trunk/18xx/rails/util/ListAndFixSavedFiles.java 2011-07-06 05:39:16 UTC (rev 1605) @@ -165,10 +165,10 @@ saveDirectory = selectedFile.getParent(); // use GameLoader object to load game - GameLoader gameLoader = new GameLoader(); + GameFileIO gameLoader = new GameFileIO(); gameLoader.loadGameData(filepath); - add(gameLoader.getGameData()); + add(gameLoader.getGameDataAsText()); try{ gameLoader.initGame(); gameLoader.loadActionsAndComments(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |