Fixing problems with concurrency and decision timeouts during preparation of the game.
This commit is contained in:
@@ -39,17 +39,13 @@ public class GameState {
|
||||
|
||||
private Map<String, GameStateListener> _gameStateListeners = new HashMap<String, GameStateListener>();
|
||||
|
||||
private String _winnerPlayerId;
|
||||
private String _winReason;
|
||||
private Map<String, String> _losers = new HashMap<String, String>();
|
||||
|
||||
private int _nextCardId = 0;
|
||||
|
||||
private int nextCardId() {
|
||||
return _nextCardId++;
|
||||
}
|
||||
|
||||
public GameState(PlayerOrder playerOrder, String firstPlayer, Map<String, List<String>> cards, LotroCardBlueprintLibrary library) {
|
||||
public void init(PlayerOrder playerOrder, String firstPlayer, Map<String, List<String>> cards, LotroCardBlueprintLibrary library) {
|
||||
_playerOrder = playerOrder;
|
||||
_currentPlayerId = firstPlayer;
|
||||
for (Map.Entry<String, List<String>> stringListEntry : cards.entrySet()) {
|
||||
@@ -63,31 +59,9 @@ public class GameState {
|
||||
|
||||
addPlayerCards(stringListEntry.getKey(), stringListEntry.getValue(), library);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWinnerPlayerId(String winnerPlayerId, String reason) {
|
||||
_winnerPlayerId = winnerPlayerId;
|
||||
_winReason = reason;
|
||||
for (GameStateListener listener : getAllGameStateListeners())
|
||||
listener.sendMessage(winnerPlayerId + " is the winner due to: " + reason);
|
||||
}
|
||||
|
||||
public String setLoserPlayerId(String loserPlayerId, String reason) {
|
||||
_losers.put(loserPlayerId, reason);
|
||||
for (GameStateListener listener : getAllGameStateListeners())
|
||||
listener.sendMessage(loserPlayerId + " lost due to: " + reason);
|
||||
|
||||
if (_losers.size() + 1 == _playerOrder.getAllPlayers().size()) {
|
||||
List<String> allPlayers = new LinkedList<String>(_playerOrder.getAllPlayers());
|
||||
allPlayers.removeAll(_losers.keySet());
|
||||
setWinnerPlayerId(allPlayers.get(0), "Last remaining player in game");
|
||||
return allPlayers.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getWinnerPlayerId() {
|
||||
return _winnerPlayerId;
|
||||
for (String playerId : _gameStateListeners.keySet())
|
||||
sendStateToPlayer(playerId);
|
||||
}
|
||||
|
||||
private void addPlayerCards(String playerId, List<String> cards, LotroCardBlueprintLibrary library) {
|
||||
@@ -143,43 +117,39 @@ public class GameState {
|
||||
}
|
||||
|
||||
private void sendStateToPlayer(String playerId) {
|
||||
GameStateListener listener = _gameStateListeners.get(playerId);
|
||||
listener.setPlayerOrder(_playerOrder.getAllPlayers());
|
||||
if (_currentPlayerId != null)
|
||||
listener.setCurrentPlayerId(_currentPlayerId);
|
||||
if (_currentPhase != null)
|
||||
listener.setCurrentPhase(_currentPhase);
|
||||
listener.setTwilight(_twilightPool);
|
||||
for (Map.Entry<String, Integer> stringIntegerEntry : _playerPosition.entrySet())
|
||||
listener.setPlayerPosition(stringIntegerEntry.getKey(), stringIntegerEntry.getValue());
|
||||
if (_playerOrder != null) {
|
||||
GameStateListener listener = _gameStateListeners.get(playerId);
|
||||
listener.setPlayerOrder(_playerOrder.getAllPlayers());
|
||||
if (_currentPlayerId != null)
|
||||
listener.setCurrentPlayerId(_currentPlayerId);
|
||||
if (_currentPhase != null)
|
||||
listener.setCurrentPhase(_currentPhase);
|
||||
listener.setTwilight(_twilightPool);
|
||||
for (Map.Entry<String, Integer> stringIntegerEntry : _playerPosition.entrySet())
|
||||
listener.setPlayerPosition(stringIntegerEntry.getKey(), stringIntegerEntry.getValue());
|
||||
|
||||
for (List<PhysicalCardImpl> physicalCards : _inPlay.values())
|
||||
for (PhysicalCardImpl physicalCard : physicalCards)
|
||||
listener.cardCreated(physicalCard);
|
||||
for (List<PhysicalCardImpl> physicalCards : _inPlay.values())
|
||||
for (PhysicalCardImpl physicalCard : physicalCards)
|
||||
listener.cardCreated(physicalCard);
|
||||
|
||||
List<PhysicalCardImpl> hand = _hands.get(playerId);
|
||||
if (hand != null) {
|
||||
for (PhysicalCardImpl physicalCard : hand)
|
||||
listener.cardCreated(physicalCard);
|
||||
List<PhysicalCardImpl> hand = _hands.get(playerId);
|
||||
if (hand != null) {
|
||||
for (PhysicalCardImpl physicalCard : hand)
|
||||
listener.cardCreated(physicalCard);
|
||||
}
|
||||
|
||||
for (Skirmish assignment : _assignments)
|
||||
listener.addAssignment(assignment.getFellowshipCharacter(), assignment.getShadowCharacters());
|
||||
|
||||
if (_skirmish != null)
|
||||
listener.startSkirmish(_skirmish.getFellowshipCharacter(), _skirmish.getShadowCharacters());
|
||||
|
||||
for (Map.Entry<PhysicalCard, Map<Token, Integer>> physicalCardMapEntry : _cardTokens.entrySet()) {
|
||||
PhysicalCard card = physicalCardMapEntry.getKey();
|
||||
for (Map.Entry<Token, Integer> tokenIntegerEntry : physicalCardMapEntry.getValue().entrySet())
|
||||
listener.addTokens(card, tokenIntegerEntry.getKey(), tokenIntegerEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (Skirmish assignment : _assignments)
|
||||
listener.addAssignment(assignment.getFellowshipCharacter(), assignment.getShadowCharacters());
|
||||
|
||||
if (_skirmish != null)
|
||||
listener.startSkirmish(_skirmish.getFellowshipCharacter(), _skirmish.getShadowCharacters());
|
||||
|
||||
for (Map.Entry<PhysicalCard, Map<Token, Integer>> physicalCardMapEntry : _cardTokens.entrySet()) {
|
||||
PhysicalCard card = physicalCardMapEntry.getKey();
|
||||
for (Map.Entry<Token, Integer> tokenIntegerEntry : physicalCardMapEntry.getValue().entrySet())
|
||||
listener.addTokens(card, tokenIntegerEntry.getKey(), tokenIntegerEntry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> playerLoseReason : _losers.entrySet())
|
||||
listener.sendMessage(playerLoseReason.getKey() + " lost due to: " + playerLoseReason.getValue());
|
||||
|
||||
if (_winnerPlayerId != null)
|
||||
listener.sendMessage(_winnerPlayerId + " is the winner due to: " + _winReason);
|
||||
}
|
||||
|
||||
private boolean isZonePublic(Zone zone) {
|
||||
|
||||
@@ -21,4 +21,6 @@ public interface LotroGame {
|
||||
public void playerWon(String currentPlayerId, String reason);
|
||||
|
||||
public void playerLost(String currentPlayerId, String reason);
|
||||
|
||||
public String getWinnerPlayerId();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ import com.gempukku.lotro.logic.timing.UnrespondableEffect;
|
||||
public class CorruptRingBearerEffect extends UnrespondableEffect {
|
||||
@Override
|
||||
public void doPlayEffect(LotroGame game) {
|
||||
game.getGameState().setLoserPlayerId(game.getGameState().getCurrentPlayerId(), "The Ring-Bearer is corrupted by a card effect");
|
||||
game.playerLost(game.getGameState().getCurrentPlayerId(), "The Ring-Bearer is corrupted by a card effect");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,18 @@ public class DefaultLotroGame implements LotroGame {
|
||||
private Map<String, GameStateListener> _gameStateListeners = new HashMap<String, GameStateListener>();
|
||||
private GameResultListener _gameResultListener;
|
||||
|
||||
private Set<String> _allPlayers;
|
||||
|
||||
private String _winnerPlayerId;
|
||||
private String _winReason;
|
||||
private Map<String, String> _losers = new HashMap<String, String>();
|
||||
|
||||
public DefaultLotroGame(Map<String, LotroDeck> decks, UserFeedback userFeedback, GameResultListener gameResultListener, final LotroCardBlueprintLibrary library) {
|
||||
_gameResultListener = gameResultListener;
|
||||
_actionStack = new ActionStack();
|
||||
|
||||
_allPlayers = decks.keySet();
|
||||
|
||||
_actionsEnvironment = new DefaultActionsEnvironment(this, _actionStack);
|
||||
|
||||
final Map<String, List<String>> cards = new HashMap<String, List<String>>();
|
||||
@@ -49,11 +57,13 @@ public class DefaultLotroGame implements LotroGame {
|
||||
cards.put(playerId, deck);
|
||||
}
|
||||
|
||||
_gameState = new GameState();
|
||||
|
||||
_turnProcedure = new TurnProcedure(this, decks.keySet(), userFeedback, _actionStack,
|
||||
new PlayerOrderFeedback() {
|
||||
@Override
|
||||
public void setPlayerOrder(PlayerOrder playerOrder, String firstPlayer) {
|
||||
_gameState = new GameState(playerOrder, firstPlayer, cards, library);
|
||||
_gameState.init(playerOrder, firstPlayer, cards, library);
|
||||
for (Map.Entry<String, GameStateListener> stringGameStateListenerEntry : _gameStateListeners.entrySet())
|
||||
_gameState.addGameStateListener(stringGameStateListenerEntry.getKey(), stringGameStateListenerEntry.getValue());
|
||||
_gameStateListeners = null;
|
||||
@@ -76,22 +86,33 @@ public class DefaultLotroGame implements LotroGame {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerWon(String currentPlayerId, String reason) {
|
||||
_gameState.setWinnerPlayerId(currentPlayerId, reason);
|
||||
public String getWinnerPlayerId() {
|
||||
return _winnerPlayerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerWon(String playerId, String reason) {
|
||||
_winnerPlayerId = playerId;
|
||||
_winReason = reason;
|
||||
if (_gameState != null)
|
||||
_gameState.sendMessage(_winnerPlayerId + " is the winner due to: " + reason);
|
||||
if (_gameResultListener != null) {
|
||||
Set<String> losers = new HashSet<String>(_gameState.getPlayerOrder().getAllPlayers());
|
||||
losers.remove(currentPlayerId);
|
||||
_gameResultListener.gameFinished(currentPlayerId, losers);
|
||||
Set<String> losers = new HashSet<String>(_allPlayers);
|
||||
losers.remove(_winnerPlayerId);
|
||||
_gameResultListener.gameFinished(_winnerPlayerId, losers, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerLost(String currentPlayerId, String reason) {
|
||||
String winner = _gameState.setLoserPlayerId(currentPlayerId, reason);
|
||||
if (winner != null && _gameResultListener != null) {
|
||||
Set<String> losers = new HashSet<String>(_gameState.getPlayerOrder().getAllPlayers());
|
||||
losers.remove(winner);
|
||||
_gameResultListener.gameFinished(winner, losers);
|
||||
public void playerLost(String playerId, String reason) {
|
||||
_losers.put(playerId, reason);
|
||||
if (_gameState != null)
|
||||
_gameState.sendMessage(playerId + " lst due to: " + reason);
|
||||
|
||||
if (_losers.size() + 1 == _allPlayers.size()) {
|
||||
List<String> allPlayers = new LinkedList<String>(_allPlayers);
|
||||
allPlayers.removeAll(_losers.keySet());
|
||||
playerWon(allPlayers.get(0), "Last remaining player in game");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,5 +3,5 @@ package com.gempukku.lotro.logic.timing;
|
||||
import java.util.Set;
|
||||
|
||||
public interface GameResultListener {
|
||||
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds);
|
||||
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds, String reason);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TurnProcedure {
|
||||
}
|
||||
|
||||
public void carryOutPendingActionsUntilDecisionNeeded() {
|
||||
while (!_userFeedback.hasPendingDecisions() && (_game.getGameState() == null || _game.getGameState().getWinnerPlayerId() == null)) {
|
||||
while (!_userFeedback.hasPendingDecisions() && _game.getWinnerPlayerId() == null) {
|
||||
if (_actionStack.isEmpty()) {
|
||||
if (_playedGameProcess) {
|
||||
_gameProcess = _gameProcess.getNextProcess();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gempukku.lotro.game;
|
||||
|
||||
import com.gempukku.lotro.common.CardType;
|
||||
import com.gempukku.lotro.common.Phase;
|
||||
import com.gempukku.lotro.game.formats.LotroFormat;
|
||||
import com.gempukku.lotro.game.state.GameState;
|
||||
import com.gempukku.lotro.game.state.Skirmish;
|
||||
@@ -46,17 +47,16 @@ public class LotroGameMediator {
|
||||
}
|
||||
|
||||
public String getGameStatus() {
|
||||
if (_lotroGame.getGameState() == null)
|
||||
return "Preparation";
|
||||
if (_lotroGame.getGameState().getWinnerPlayerId() != null)
|
||||
if (_lotroGame.getWinnerPlayerId() != null)
|
||||
return "Finished";
|
||||
if (_lotroGame.getGameState().getCurrentPhase() == Phase.GAME_SETUP)
|
||||
return "Preparation";
|
||||
return "Playing";
|
||||
}
|
||||
|
||||
public synchronized String produceCardInfo(String participantId, int cardId) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
||||
PhysicalCard card = _lotroGame.getGameState().findCardById(cardId);
|
||||
if (card == null)
|
||||
return null;
|
||||
@@ -104,7 +104,7 @@ public class LotroGameMediator {
|
||||
}
|
||||
}
|
||||
|
||||
if (_lotroGame.getGameState() != null && _lotroGame.getGameState().getWinnerPlayerId() == null) {
|
||||
if (_lotroGame.getGameState() != null && _lotroGame.getWinnerPlayerId() == null) {
|
||||
for (Map.Entry<String, Long> playerDecision : _decisionQuerySentTimes.entrySet()) {
|
||||
String playerId = playerDecision.getKey();
|
||||
long decisionSent = playerDecision.getValue();
|
||||
|
||||
@@ -111,8 +111,8 @@ public class LotroServer extends AbstractServer {
|
||||
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
|
||||
new GameResultListener() {
|
||||
@Override
|
||||
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds) {
|
||||
log.debug("Game finished, winner is: " + winnerPlayerId);
|
||||
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds, String reason) {
|
||||
log.debug("Game finished, winner is - " + winnerPlayerId + " due to: " + reason);
|
||||
synchronized (_finishedGamesTime) {
|
||||
_finishedGamesTime.put(gameId, new Date());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user