From: <ste...@us...> - 2010-07-05 18:02:20
|
Revision: 1333 http://rails.svn.sourceforge.net/rails/?rev=1333&view=rev Author: stefanfrey Date: 2010-07-05 18:02:13 +0000 (Mon, 05 Jul 2010) Log Message: ----------- Added autosave for game recovery Modified Paths: -------------- trunk/18xx/LocalisedText.properties trunk/18xx/my.properties trunk/18xx/rails/game/DisplayBuffer.java trunk/18xx/rails/game/GameManager.java trunk/18xx/rails/ui/swing/GameSetupWindow.java Modified: trunk/18xx/LocalisedText.properties =================================================================== --- trunk/18xx/LocalisedText.properties 2010-07-04 20:51:33 UTC (rev 1332) +++ trunk/18xx/LocalisedText.properties 2010-07-05 18:02:13 UTC (rev 1333) @@ -416,6 +416,9 @@ Pullman=Pullman-Car QUIT=Quit RandomizePlayers=Randomize Order +RecoverGame=Recover Previous Game +RecoverySaveFailed=Recovery save failed, reason: {0} +RecoverySaveSuccessAgain=Recovery save succeeded REDO=Redo ReleasedFromEscrow={0} receives {1} released from bank escrow ReleasesTrains=Makes {0}-trains available for purchasing Modified: trunk/18xx/my.properties =================================================================== --- trunk/18xx/my.properties 2010-07-04 20:51:33 UTC (rev 1332) +++ trunk/18xx/my.properties 2010-07-05 18:02:13 UTC (rev 1333) @@ -58,6 +58,12 @@ # The default extension is .rails #save.filename.extension=rails +### AutoSave for game recovery +# Activation of autosave (default is yes) +# save.recovery.active=yes +# Filepath for autosave (default is 18xx_autosave.rails in current working directory +# save.recovery.filepath=18xx_autosave.rails + ### Game report directory # If the below entry exists, is not empty, and specifies an existing # directory, a copy of the Game Report (as displayed in the Report Window) Modified: trunk/18xx/rails/game/DisplayBuffer.java =================================================================== --- trunk/18xx/rails/game/DisplayBuffer.java 2010-07-04 20:51:33 UTC (rev 1332) +++ trunk/18xx/rails/game/DisplayBuffer.java 2010-07-05 18:02:13 UTC (rev 1333) @@ -73,13 +73,26 @@ } private static DisplayBuffer getInstance() { - return GameManager.getInstance().getDisplayBuffer(); + GameManagerI gm = GameManager.getInstance(); + if (gm == null) { + return null; + } else { + return gm.getDisplayBuffer(); + } } /** Get the current message buffer, and clear it */ public static String[] get() { DisplayBuffer instance = getInstance(); - if (instance.displayBuffer.size() > 0) { + if (instance == null) { + if (initialQueue.isEmpty()) { + return null; + } else { + String[] message = initialQueue.toArray(new String[0]); + initialQueue.clear(); + return message; + } + } else if (instance.displayBuffer.size() > 0) { String[] message = instance.displayBuffer.toArray(new String[0]); instance.displayBuffer.clear(); return message; Modified: trunk/18xx/rails/game/GameManager.java =================================================================== --- trunk/18xx/rails/game/GameManager.java 2010-07-04 20:51:33 UTC (rev 1332) +++ trunk/18xx/rails/game/GameManager.java 2010-07-05 18:02:13 UTC (rev 1333) @@ -187,6 +187,9 @@ /** A List of available game options */ protected List<GameOption> availableGameOptions = new ArrayList<GameOption>(); + + /** indicates that the recoverySave already issued a warning, avoids displaying several warnings */ + protected boolean recoverySaveWarning = true; protected static Logger log = Logger.getLogger(GameManager.class.getPackage().getName()); @@ -810,6 +813,7 @@ if (action != null) { if (result && !(action instanceof GameAction) && action.hasActed()) { if (moveStack.isOpen()) moveStack.finish(); + recoverySave(); } else { if (moveStack.isOpen()) moveStack.cancel(); } @@ -929,15 +933,72 @@ return true; } + /** recoverySave method + * Uses filePath defined in save.recovery.filepath + * */ + protected void recoverySave() { + if (Config.get("save.recovery.active", "yes").equalsIgnoreCase("no")) return; + + String filePath = Config.get("save.recovery.filepath", "18xx_autosave.rails"); + // create temporary new save file + File tempFile = null; + tempFile = new File(filePath + ".tmp"); + if (!save(tempFile, recoverySaveWarning, "RecoverySaveFailed")) { + recoverySaveWarning = false; + return; + } + + // rename the temp file to the recover file + File recoveryFile = null; + boolean result; + try { + log.debug("Created temporary recovery file, path = " + tempFile.getAbsolutePath()); + // check if previous save file exists + recoveryFile = new File(filePath); + log.debug("Potential recovery filePath = " + recoveryFile.getAbsolutePath()); + if (recoveryFile.exists()) { + log.debug("Potential recovery filePath = " + recoveryFile.getAbsolutePath()); + File backupFile = new File(filePath + ".bak"); + if (recoveryFile.renameTo(backupFile)) { + result = tempFile.renameTo(recoveryFile); + } else { + result = backupFile.renameTo(recoveryFile); + } + } else { + log.debug("Tries to rename temporary file"); + result = tempFile.renameTo(recoveryFile); + } + } catch (Exception e) { + DisplayBuffer.add(LocalText.getText("RecoverySaveFailed", e.getMessage())); + recoverySaveWarning = false; + return; + } + + if (result) { + log.debug("Renamed to recovery file, path = " + recoveryFile.getAbsolutePath()); + if (!recoverySaveWarning) { + DisplayBuffer.add(LocalText.getText("RecoverySaveSuccessAgain")); + recoverySaveWarning = true; + } + } else { + if (recoverySaveWarning) { + DisplayBuffer.add(LocalText.getText("RecoverySaveFailed", "file renaming not possible")); + recoverySaveWarning = false; + } + } + } + protected boolean save(GameAction saveAction) { - - String filepath = saveAction.getFilepath(); + File file = new File(saveAction.getFilepath()); + return save(file, true, "SaveFailed"); + } + + protected boolean save(File file, boolean displayErrorMessage, String errorMessageKey) { boolean result = false; try { ObjectOutputStream oos = - new ObjectOutputStream(new FileOutputStream(new File( - filepath))); + 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); @@ -949,10 +1010,11 @@ result = true; } catch (IOException e) { - log.error("Save failed", e); - DisplayBuffer.add(LocalText.getText("SaveFailed", e.getMessage())); + log.error(errorMessageKey, e); + if (displayErrorMessage) { + DisplayBuffer.add(LocalText.getText("SaveFailed", e.getMessage())); + } } - return result; } Modified: trunk/18xx/rails/ui/swing/GameSetupWindow.java =================================================================== --- trunk/18xx/rails/ui/swing/GameSetupWindow.java 2010-07-04 20:51:33 UTC (rev 1332) +++ trunk/18xx/rails/ui/swing/GameSetupWindow.java 2010-07-05 18:02:13 UTC (rev 1333) @@ -25,7 +25,7 @@ private static final long serialVersionUID = 1L; GridBagConstraints gc; JPanel gameListPane, playersPane, buttonPane, optionsPane; - JButton newButton, loadButton, quitButton, optionButton, infoButton; + JButton newButton, loadButton, recoveryButton, quitButton, optionButton, infoButton; JButton creditsButton, randomizeButton; JComboBox gameNameBox = new JComboBox(); JComboBox[] playerBoxes = new JComboBox[Player.MAX_PLAYERS]; @@ -66,6 +66,7 @@ newButton = new JButton(LocalText.getText("NewGame")); loadButton = new JButton(LocalText.getText("LoadGame")); + recoveryButton = new JButton(LocalText.getText("RecoverGame")); quitButton = new JButton(LocalText.getText("QUIT")); optionButton = new JButton(LocalText.getText("OPTIONS")); infoButton = new JButton(LocalText.getText("INFO")); @@ -73,6 +74,7 @@ newButton.setMnemonic(KeyEvent.VK_N); loadButton.setMnemonic(KeyEvent.VK_L); + recoveryButton.setMnemonic(KeyEvent.VK_R); quitButton.setMnemonic(KeyEvent.VK_Q); optionButton.setMnemonic(KeyEvent.VK_O); infoButton.setMnemonic(KeyEvent.VK_G); @@ -85,12 +87,15 @@ populateGameList(GamesInfo.getGameNames(), gameNameBox); gameListPane.add(new JLabel("Available Games:")); + gameListPane.add(new JLabel("")); // empty slot gameListPane.add(gameNameBox); + gameListPane.add(optionButton); gameListPane.setLayout(new GridLayout(2, 2)); gameListPane.setBorder(BorderFactory.createLoweredBevelBorder()); newButton.addActionListener(this); loadButton.addActionListener(this); + recoveryButton.addActionListener(this); quitButton.addActionListener(this); optionButton.addActionListener(this); infoButton.addActionListener(this); @@ -99,7 +104,9 @@ buttonPane.add(newButton); buttonPane.add(loadButton); - buttonPane.add(optionButton); + if (!Config.get("save.recovery.active", "yes").equalsIgnoreCase("no")) { + buttonPane.add(recoveryButton); + } buttonPane.add(infoButton); buttonPane.add(quitButton); buttonPane.add(creditsButton); @@ -187,6 +194,26 @@ } } + /* + * loads and start the game given a filename + */ + private void loadAndStartGame(String filePath, String saveDirectory) { + if ((game = Game.load(filePath)) == null) { + JOptionPane.showMessageDialog(this, + DisplayBuffer.get(), "", JOptionPane.ERROR_MESSAGE); + return; + } else if (DisplayBuffer.getSize() > 0) { + JOptionPane.showMessageDialog(this, + DisplayBuffer.get(), "", JOptionPane.ERROR_MESSAGE); + } + startGameUIManager(game); + if (saveDirectory != null) { + gameUIManager.setSaveDirectory (saveDirectory); + } + gameUIManager.startLoadedGame(); + setVisible(false); + } + public void actionPerformed(ActionEvent arg0) { if (arg0.getSource().equals(newButton)) { startNewGame(); @@ -200,24 +227,13 @@ if (jfc.showOpenDialog(getContentPane()) == JFileChooser.APPROVE_OPTION) { File selectedFile = jfc.getSelectedFile(); - String filepath = selectedFile.getPath(); - saveDirectory = selectedFile.getParent(); - if ((game = Game.load(filepath)) == null) { - JOptionPane.showMessageDialog(this, - DisplayBuffer.get(), "", JOptionPane.ERROR_MESSAGE); - return; - } else if (DisplayBuffer.getSize() > 0) { - JOptionPane.showMessageDialog(this, - DisplayBuffer.get(), "", JOptionPane.ERROR_MESSAGE); - } + loadAndStartGame(selectedFile.getPath(), selectedFile.getParent()); } else { // cancel pressed return; } - - startGameUIManager(game); - gameUIManager.setSaveDirectory (saveDirectory); - gameUIManager.startLoadedGame(); - setVisible(false); + } else if (arg0.getSource().equals(recoveryButton)) { + String filePath = Config.get("save.recovery.filepath", "18xx_autosave.rails"); + loadAndStartGame(filePath, null); } else if (arg0.getSource().equals(infoButton)) { JOptionPane.showMessageDialog(this, GamesInfo.getDescription(gameName), "Information about " This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |