diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java index e3189ef01..069a6868e 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java @@ -30,6 +30,8 @@ public class DefaultLotroGame implements LotroGame { private UserFeedback _userFeedback; private TurnProcedure _turnProcedure; private ActionStack _actionStack; + private boolean _cancelled; + private boolean _finished; private LotroFormat _format; @@ -105,11 +107,13 @@ public class DefaultLotroGame implements LotroGame { } public void startGame() { - _turnProcedure.carryOutPendingActionsUntilDecisionNeeded(); + if (!_cancelled) + _turnProcedure.carryOutPendingActionsUntilDecisionNeeded(); } public void carryOutPendingActionsUntilDecisionNeeded() { - _turnProcedure.carryOutPendingActionsUntilDecisionNeeded(); + if (!_cancelled) + _turnProcedure.carryOutPendingActionsUntilDecisionNeeded(); } @Override @@ -117,17 +121,37 @@ public class DefaultLotroGame implements LotroGame { return _winnerPlayerId; } + public boolean isFinished() { + return _finished; + } + + public void cancelGame() { + if (!_finished) { + _cancelled = true; + for (GameResultListener gameResultListener : _gameResultListeners) + gameResultListener.gameCancelled(); + + _finished = true; + } + } + + public boolean isCancelled() { + return _cancelled; + } + @Override public void playerWon(String playerId, String reason) { - // Any remaining players have lost - Set losers = new HashSet(_allPlayers); - losers.removeAll(_losers.keySet()); - losers.remove(playerId); + if (!_finished) { + // Any remaining players have lost + Set losers = new HashSet(_allPlayers); + losers.removeAll(_losers.keySet()); + losers.remove(playerId); - for (String loser : losers) - _losers.put(loser, "Other player won"); + for (String loser : losers) + _losers.put(loser, "Other player won"); - gameWon(playerId, reason); + gameWon(playerId, reason); + } } private void gameWon(String winner, String reason) { @@ -138,20 +162,24 @@ public class DefaultLotroGame implements LotroGame { for (GameResultListener gameResultListener : _gameResultListeners) gameResultListener.gameFinished(_winnerPlayerId, reason, _losers); + + _finished = true; } @Override public void playerLost(String playerId, String reason) { - if (_losers.get(playerId) == null) { - log.debug("Player " + playerId + " lost due to: " + reason); - _losers.put(playerId, reason); - if (_gameState != null) - _gameState.sendMessage(playerId + " lost due to: " + reason); + if (!_finished) { + if (_losers.get(playerId) == null) { + log.debug("Player " + playerId + " lost due to: " + reason); + _losers.put(playerId, reason); + if (_gameState != null) + _gameState.sendMessage(playerId + " lost due to: " + reason); - if (_losers.size() + 1 == _allPlayers.size()) { - List allPlayers = new LinkedList(_allPlayers); - allPlayers.removeAll(_losers.keySet()); - gameWon(allPlayers.get(0), "Last remaining player in game"); + if (_losers.size() + 1 == _allPlayers.size()) { + List allPlayers = new LinkedList(_allPlayers); + allPlayers.removeAll(_losers.keySet()); + gameWon(allPlayers.get(0), "Last remaining player in game"); + } } } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java index 5131a82f4..be9493c5d 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java @@ -4,4 +4,6 @@ import java.util.Map; public interface GameResultListener { public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons); + + public void gameCancelled(); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java index 072ca5fcf..9c308802d 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java @@ -11,6 +11,7 @@ import com.gempukku.lotro.logic.modifiers.Modifier; import com.gempukku.lotro.logic.timing.DefaultLotroGame; import com.gempukku.lotro.logic.timing.GameResultListener; import com.gempukku.lotro.logic.vo.LotroDeck; +import org.apache.log4j.Logger; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -18,6 +19,8 @@ import java.util.*; import java.util.concurrent.locks.ReentrantReadWriteLock; public class LotroGameMediator { + private static final Logger LOG = Logger.getLogger(LotroGameMediator.class); + private Map _communicationChannels = new HashMap(); private DefaultUserFeedback _userFeedback; private DefaultLotroGame _lotroGame; @@ -96,7 +99,9 @@ public class LotroGameMediator { } public String getGameStatus() { - if (_lotroGame.getWinnerPlayerId() != null) + if (_lotroGame.isCancelled()) + return "Cancelled"; + if (_lotroGame.isFinished()) return "Finished"; final Phase currentPhase = _lotroGame.getGameState().getCurrentPhase(); if (currentPhase == Phase.PLAY_STARTING_FELLOWSHIP || currentPhase == Phase.PUT_RING_BEARER) @@ -270,7 +275,7 @@ public class LotroGameMediator { if (communicationChannel.getChannelNumber() == channelNumber) { AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(playerName); if (awaitingDecision != null) { - if (awaitingDecision.getAwaitingDecisionId() == decisionId) { + if (awaitingDecision.getAwaitingDecisionId() == decisionId && !_lotroGame.isFinished()) { try { _userFeedback.participantDecided(playerName); awaitingDecision.decisionMade(answer); @@ -285,6 +290,9 @@ public class LotroGameMediator { // Participant provided wrong answer - send a warning message, and ask again for the same decision _userFeedback.sendWarning(playerName, decisionResultInvalidException.getWarningMessage()); _userFeedback.sendAwaitingDecision(playerName, awaitingDecision); + } catch (RuntimeException runtimeException) { + LOG.error("Error processing game decision", runtimeException); + _lotroGame.cancelGame(); } } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java index e75fb1333..a03c642d7 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java @@ -123,7 +123,7 @@ public class LotroServer extends AbstractServer { return "Game" + gameId; } - public synchronized String createNewGame(LotroFormat lotroFormat, String tournament, LotroGameParticipant[] participants, boolean competetive) { + public synchronized String createNewGame(LotroFormat lotroFormat, String tournament, final LotroGameParticipant[] participants, boolean competetive) { if (participants.length < 2) throw new IllegalArgumentException("There has to be at least two players"); final String gameId = String.valueOf(_nextGameId); @@ -149,6 +149,13 @@ public class LotroServer extends AbstractServer { _finishedGamesTime.put(gameId, new Date()); } } + + @Override + public void gameCancelled() { + synchronized (_finishedGamesTime) { + _finishedGamesTime.put(gameId, new Date()); + } + } }); lotroGameMediator.sendMessageToPlayers("You're starting a game of " + lotroFormat.getName()); @@ -172,6 +179,11 @@ public class LotroServer extends AbstractServer { gameRecordingInProgress.finishRecording(winnerPlayerId, winReason, loserEntry.getKey(), loserEntry.getValue()); } + + @Override + public void gameCancelled() { + gameRecordingInProgress.finishRecording(participants[0].getPlayerId(), "Game cancelled due to error", participants[1].getPlayerId(), "Game cancelled due to error"); + } } ); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java index 86e9f42e2..59da819b2 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java @@ -308,6 +308,11 @@ public class HallServer extends AbstractServer { public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { _leagueService.reportLeagueGameResult(league, leagueSerie, winnerPlayerId, loserPlayerIdsWithReasons.keySet().iterator().next()); } + + @Override + public void gameCancelled() { + // Do nothing... + } }); } lotroGameMediator.startGame(); diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java index 8a1d7c5f8..470350091 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java @@ -9,7 +9,6 @@ import com.gempukku.lotro.game.state.EventSerializer; import com.gempukku.lotro.game.state.GameEvent; import com.gempukku.lotro.logic.modifiers.LoggingThreadLocal; import com.sun.jersey.spi.resource.Singleton; -import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -32,7 +31,6 @@ import java.util.Set; @Singleton @Path("/game") public class GameResource extends AbstractResource { - private static final Logger _logger = Logger.getLogger(GameResource.class); @Context private LotroServer _lotroServer; @@ -143,14 +141,8 @@ public class GameResource extends AbstractResource { gameMediator.setPlayerAutoPassSettings(resourceOwner.getName(), getAutoPassPhases(request)); - if (decisionId != null) { - try { - gameMediator.playerAnswered(resourceOwner, channelNumber, decisionId, decisionValue); - } catch (RuntimeException exp) { - _logger.error("Error while sending decision", exp); - throw exp; - } - } + if (decisionId != null) + gameMediator.playerAnswered(resourceOwner, channelNumber, decisionId, decisionValue); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/resources/log4j.xml b/gemp-lotr/gemp-lotr-web-server/src/main/resources/log4j.xml index 221b607fc..30da15fa4 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/resources/log4j.xml +++ b/gemp-lotr/gemp-lotr-web-server/src/main/resources/log4j.xml @@ -15,18 +15,6 @@ - - - - - - - - - - - -