diff --git a/vassal-app/src/main/java/VASSAL/build/module/BasicLogger.java b/vassal-app/src/main/java/VASSAL/build/module/BasicLogger.java index 6f7299082a..2a3bbebd0f 100644 --- a/vassal-app/src/main/java/VASSAL/build/module/BasicLogger.java +++ b/vassal-app/src/main/java/VASSAL/build/module/BasicLogger.java @@ -82,6 +82,7 @@ public class BasicLogger implements Logger, Buildable, GameComponent, CommandEnc public static final String BEGIN = "begin_log"; //$NON-NLS-1$ public static final String END = "end_log"; //$NON-NLS-1$ public static final String LOG = "LOG\t"; //$NON-NLS-1$ + public static final String UNDO = "UNDO\t"; //$NON-NLS-1$ public static final String PROMPT_NEW_LOG = "PromptNewLog"; //$NON-NLS-1$ public static final String PROMPT_NEW_LOG_START = "PromptNewLogAtStart"; //$NON-NLS-1$ public static final String PROMPT_NEW_LOG_END = "PromptNewLogEnd"; //$NON-NLS-1$ @@ -102,6 +103,8 @@ public class BasicLogger implements Logger, Buildable, GameComponent, CommandEnc private NamedHotKeyConfigurer stepKeyConfig; private NamedHotKeyConfigurer undoKeyConfig; + private boolean undoInProgress = false; + public BasicLogger() { super(); stepAction.setEnabled(false); @@ -545,12 +548,20 @@ protected void undo() { } undoAction.setEnabled(nextUndo >= dontUndoPast); - final Command undo = lastOutput.getUndoCommand(); + final Command undo = new UndoCommand(true).append(lastOutput.getUndoCommand()).append(new UndoCommand(false)); undo.execute(); GameModule.getGameModule().getServer().sendToOthers(undo); logOutput.add(undo); } + public boolean isUndoInProgress() { + return undoInProgress; + } + + public void setUndoInProgress(boolean undoInProgress) { + this.undoInProgress = undoInProgress; + } + /** * Logs a Command to output * @param c Command to be logged @@ -579,24 +590,32 @@ public boolean hasMoreCommands() { */ @Override public String encode(Command c) { - if (!(c instanceof LogCommand)) { - return null; + if (c instanceof LogCommand) { + return LOG + GameModule.getGameModule().encode(((LogCommand) c).getLoggedCommand()); } - return LOG + GameModule.getGameModule().encode(((LogCommand) c).getLoggedCommand()); + else if (c instanceof UndoCommand) { + return UNDO + ((UndoCommand) c).isInProgress(); + } + + return null; } @Override public Command decode(String command) { - if (!command.startsWith(LOG)) { - return null; - } + if (command.startsWith(LOG)) { + final Command logged = GameModule.getGameModule().decode(command.substring(LOG.length())); + if (logged == null) { + return null; + } - final Command logged = GameModule.getGameModule().decode(command.substring(LOG.length())); - if (logged == null) { - return null; + return new LogCommand(logged, logInput, stepAction); + } + else if (command.startsWith(UNDO)) { + final String inProgress = command.substring(UNDO.length()); + return new UndoCommand("true".equals(inProgress)); } - return new LogCommand(logged, logInput, stepAction); + return null; } protected Action undoAction = new UndoAction(); @@ -718,4 +737,31 @@ public void actionPerformed(ActionEvent e) { undo(); } } + + /** + * A Command that records whether or not an Undo is in progress. + * NOTE: Older clients will just ignore this Command if they see it + */ + public static class UndoCommand extends Command { + + private final boolean inProgress; + + public UndoCommand(boolean inProgress) { + this.inProgress = inProgress; + } + + public boolean isInProgress() { + return inProgress; + } + + @Override + protected void executeCommand() { + GameModule.getGameModule().getBasicLogger().setUndoInProgress(inProgress); + } + + @Override + protected Command myUndoCommand() { + return null; + } + } } diff --git a/vassal-app/src/main/java/VASSAL/counters/Deck.java b/vassal-app/src/main/java/VASSAL/counters/Deck.java index 6c98612e94..bf92231d20 100644 --- a/vassal-app/src/main/java/VASSAL/counters/Deck.java +++ b/vassal-app/src/main/java/VASSAL/counters/Deck.java @@ -467,7 +467,8 @@ protected void removePieceAt(int index, boolean suppressDeckCounts) { super.removePieceAt(index, suppressDeckCounts); if (!suppressDeckCounts) { fireNumCardsProperty(); - if (hotkeyOnEmpty && emptyKey != null && startCount > 0 && pieceCount == 0) { + // Do NOT fire a Deck Empty key if it has been caused by an Undo Command + if (hotkeyOnEmpty && emptyKey != null && startCount > 0 && pieceCount == 0 && ! GameModule.getGameModule().getBasicLogger().isUndoInProgress()) { gameModule.fireKeyStroke(emptyKey); } }