From: <ste...@us...> - 2011-07-05 17:03:29
|
Revision: 1604 http://rails.svn.sourceforge.net/rails/?rev=1604&view=rev Author: stefanfrey Date: 2011-07-05 17:03:23 +0000 (Tue, 05 Jul 2011) Log Message: ----------- Refactored the load code into a new Class GameLoader Modified Paths: -------------- trunk/18xx/LocalisedText.properties trunk/18xx/rails/game/Game.java trunk/18xx/rails/game/GameManager.java trunk/18xx/rails/util/ListAndFixSavedFiles.java Added Paths: ----------- trunk/18xx/rails/util/GameLoader.java Modified: trunk/18xx/LocalisedText.properties =================================================================== --- trunk/18xx/LocalisedText.properties 2011-07-04 23:34:57 UTC (rev 1603) +++ trunk/18xx/LocalisedText.properties 2011-07-05 17:03:23 UTC (rev 1604) @@ -354,11 +354,11 @@ LaysTileAtFor={0} lays tile #{1} at hex {2}/{3} for {4} LDIncome=LD income is LeaveAuctionOnPass=Leave private auction on pass -LoadFailed=Load failed, reason: {0} +LoadFailed=Load failed.\n\Reason = {0}\n\To improve Rails please submit save file to Rails user list at \n\ rai...@li... LoadGame=Load Game LoadRecentGame=Load Recent LOAD=Load -LoadInterrupted=Load interrupted at this point, you can continue play from here +LoadInterrupted=Load interrupted at this point, you can continue play from here.\n\To improve Rails please submit save file to Rails user list at \n\ rai...@li... LoansNotAllowed={0} may not take any loans Major=Major MAP=Map Modified: trunk/18xx/rails/game/Game.java =================================================================== --- trunk/18xx/rails/game/Game.java 2011-07-04 23:34:57 UTC (rev 1603) +++ trunk/18xx/rails/game/Game.java 2011-07-05 17:03:23 UTC (rev 1604) @@ -13,6 +13,7 @@ import rails.common.parser.GameFileParser; import rails.common.parser.GameOption; import rails.game.action.PossibleAction; +import rails.util.GameLoader; public class Game { public static final String version = "1.4.1+"; @@ -118,9 +119,32 @@ return true; } + + + public static Game load(String filepath) { + + // use GameLoader object to load game + GameLoader gameLoader = new GameLoader(); + gameLoader.loadGameData(filepath); + try{ + gameLoader.initGame(); + gameLoader.loadActionsAndComments(); + } catch (ConfigurationException e) { + log.fatal("Load failed", e); + DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); + } + try{ + gameLoader.replayGame(); + } catch (Exception e) { + log.fatal("Replay failed", e); + DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); + } + return gameLoader.getGame(); + } + @SuppressWarnings("unchecked") - public static Game load(String filepath) { + public static Game load_old(String filepath) { Game game = null; Modified: trunk/18xx/rails/game/GameManager.java =================================================================== --- trunk/18xx/rails/game/GameManager.java 2011-07-04 23:34:57 UTC (rev 1603) +++ trunk/18xx/rails/game/GameManager.java 2011-07-05 17:03:23 UTC (rev 1604) @@ -1049,8 +1049,8 @@ return true; } + /** allows callback from GameLoader */ public void finishLoading () { - guiHints.clearVisibilityHints(); } @@ -1141,72 +1141,44 @@ } return result; } - - @SuppressWarnings("unchecked") + /** + * tries to reload the current game + * executes the additional action(s) + */ protected boolean reload(GameAction reloadAction) { - + log.info("Reloading started"); + + /* Use gameLoader to load the game data */ + GameLoader gameLoader = new GameLoader(); String filepath = reloadAction.getFilepath(); - log.info("Reloading game from file " + filepath); - String filename = filepath.replaceAll(".*[/\\\\]", ""); + gameLoader.loadGameData(filepath); + + /* followed by actions and comments */ + try{ + gameLoader.loadActionsAndComments(); + } catch (ConfigurationException e) { + log.fatal("Load failed", e); + DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); + } + log.debug("Starting to compare loaded actions"); + + /* gameLoader actions get compared to the executed actions of the current game */ + List<PossibleAction> savedActions = gameLoader.getActions(); + + setReloading(true); + + // Check size + if (savedActions.size() < executedActions.size()) { + DisplayBuffer.add(LocalText.getText("LoadFailed", + "loaded file has less actions than current game")); + return true; + } + + // Check action identity + int index = 0; + PossibleAction executedAction; try { - ObjectInputStream ois = - new ObjectInputStream(new FileInputStream( - new File(filepath))); - - // See Game.load(). Here we don't do as much checking. */ - Object object = ois.readObject(); - if (object instanceof String) { - log.info("Reading Rails "+(String)object+" saved file "+filename); - object = ois.readObject(); - } else { - log.info("Reading Rails (pre-1.0.7) saved file "+filename); - } - if (object instanceof String) { - log.info("File was saved at "+(String)object); - object = ois.readObject(); - } - String name = (String) ois.readObject(); - log.debug("Saved game="+name); - Map<String, String> selectedGameOptions = - (Map<String, String>) ois.readObject(); - List<String> playerNames = (List<String>) ois.readObject(); - - log.debug("Starting to compare loaded actions"); - - List<PossibleAction> savedActions; - int numberOfActions = 0; - setReloading(true); - - Object actionObject = ois.readObject(); - if (actionObject instanceof List) { - // Old-style: one List of PossibleActions - savedActions = (List<PossibleAction>) actionObject; - numberOfActions = savedActions.size(); - } else { - // New style: separate PossibleActionsObjects, since Rails 1.3.1 - savedActions = new ArrayList<PossibleAction>(); - while (actionObject instanceof PossibleAction) { - savedActions.add((PossibleAction) actionObject); - numberOfActions++; - try { - actionObject = ois.readObject(); - } catch (EOFException e) { - break; - } - } - } - - // Check size - if (numberOfActions < executedActions.size()) { - DisplayBuffer.add(LocalText.getText("LoadFailed", - "loaded file has less actions than current game")); - return true; - } - - // Check action identity - int index = 0; - PossibleAction executedAction; for (PossibleAction savedAction : savedActions) { if (index < executedActions.size()) { executedAction = executedActions.get(index); @@ -1230,40 +1202,25 @@ } } index++; - } - - if (actionObject instanceof SortedMap) { - ReportBuffer.setCommentItems((SortedMap<Integer, String>) actionObject); - log.debug("Found sorted map"); - } else { - try { - object = ois.readObject(); - if (object instanceof SortedMap) { - ReportBuffer.setCommentItems((SortedMap<Integer, String>) object); - } - } 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; - - setReloading(false); - finishLoading(); - log.info("Reloading finished"); - + } } catch (Exception e) { log.error("Reload failed", e); DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); return true; } + + + setReloading(false); + finishLoading(); + // use new comments (without checks) + ReportBuffer.setCommentItems(gameLoader.getComments()); + + log.info("Reloading finished"); return true; } + protected boolean export(GameAction exportAction) { String filename = exportAction.getFilepath(); Added: trunk/18xx/rails/util/GameLoader.java =================================================================== --- trunk/18xx/rails/util/GameLoader.java (rev 0) +++ trunk/18xx/rails/util/GameLoader.java 2011-07-05 17:03:23 UTC (rev 1604) @@ -0,0 +1,252 @@ +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(); + } +} Property changes on: trunk/18xx/rails/util/GameLoader.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/18xx/rails/util/ListAndFixSavedFiles.java =================================================================== --- trunk/18xx/rails/util/ListAndFixSavedFiles.java 2011-07-04 23:34:57 UTC (rev 1603) +++ trunk/18xx/rails/util/ListAndFixSavedFiles.java 2011-07-05 17:03:23 UTC (rev 1604) @@ -36,6 +36,7 @@ private List<Object> savedObjects = new ArrayList<Object>(512); private List<PossibleAction> executedActions; + private SortedMap<Integer,String> userComments; private int vbarPos; @@ -156,100 +157,33 @@ JFileChooser jfc = new JFileChooser(); jfc.setCurrentDirectory(new File(saveDirectory)); - + if (jfc.showOpenDialog(getContentPane()) == JFileChooser.APPROVE_OPTION) { File selectedFile = jfc.getSelectedFile(); filepath = selectedFile.getPath(); saveDirectory = selectedFile.getParent(); + + // use GameLoader object to load game + GameLoader gameLoader = new GameLoader(); - log.debug("Loading game from file " + filepath); - String filename = filepath.replaceAll(".*[/\\\\]", ""); - - try { - ObjectInputStream ois = - new ObjectInputStream(new FileInputStream( - new File(filepath))); - - // New in 1.0.7: Rails version & save date/time. - // Allow for older saved file versions. - - Object object = ois.readObject(); - savedObjects.add(object); - if (object instanceof String) { - add((String)object+" saved file "+filename); - object = ois.readObject(); - savedObjects.add(object); - } else { - add("Reading Rails (pre-1.0.7) saved file "+filename); - } - if (object instanceof String) { - add("File was saved at "+(String)object); - object = ois.readObject(); - savedObjects.add(object); - } - - long versionID = (Long) object; - add("Saved versionID="+versionID+" (object="+object+")"); - long saveFileVersionID = GameManager.saveFileVersionID; - String name = (String) ois.readObject(); - savedObjects.add(name); - add("Saved game="+name); - - Map<String, String> selectedGameOptions = - (Map<String, String>) ois.readObject(); - savedObjects.add(selectedGameOptions); - for (String key : selectedGameOptions.keySet()) { - add("Option "+key+"="+selectedGameOptions.get(key)); - } - - List<String> playerNames = (List<String>) ois.readObject(); - savedObjects.add(playerNames); - int i=1; - for (String player : playerNames) { - add("Player "+(i++)+": "+player); - } - - Game game = new Game(name, playerNames, selectedGameOptions); - - if (!game.setup()) { - throw new ConfigurationException("Error in setting up " + name); - } - - Object firstActionObject = ois.readObject(); - if (firstActionObject instanceof List) { - // Old-style: one List of PossibleActions - executedActions = - (List<PossibleAction>) firstActionObject; - savedObjects.add(executedActions); - } else { - // New style: separate PossibleActionsObjects, since Rails 1.3.1 - executedActions = new ArrayList<PossibleAction>(); - PossibleAction action = (PossibleAction) firstActionObject; - while (true) { - savedObjects.add (action); - executedActions.add(action); - try { - action = (PossibleAction) ois.readObject(); - } catch (EOFException e) { - break; - } catch (ClassCastException e) { - log.error ("Aborting on non-action object: "+ e.getMessage()); - break; - } - } - } + gameLoader.loadGameData(filepath); + add(gameLoader.getGameData()); + try{ + gameLoader.initGame(); + gameLoader.loadActionsAndComments(); + executedActions = gameLoader.getActions(); + userComments = gameLoader.getComments(); setReportText(true); - - ois.close(); - } catch (Exception e) { - System.out.println(e.getMessage()); - e.printStackTrace(); + + } catch (ConfigurationException e) { + log.fatal("Load failed", e); + DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); } } } - + public void add (String text) { if (text.length() > 0) { headerText.append(text); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |