From 5900bb7a686b3679855bc821ba7807137b8dc352 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Mon, 19 Sep 2011 22:05:49 +0000 Subject: [PATCH] Fixing spectator mode UI weights and also fixing discard and dead pile cards after reload. --- .../lotro/game/LotroGameMediator.java | 271 ++++++++++-------- .../src/main/webapp/js/gameUi.js | 10 +- 2 files changed, 160 insertions(+), 121 deletions(-) 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 1522e45ad..779c82fe3 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 @@ -13,6 +13,7 @@ import com.gempukku.lotro.logic.timing.GameResultListener; import com.gempukku.lotro.logic.vo.LotroDeck; import java.util.*; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class LotroGameMediator { private Map _communicationChannels = new HashMap(); @@ -26,6 +27,10 @@ public class LotroGameMediator { private final int _channelInactivityTimeoutPeriod = 1000 * 60 * 5; // 5 minutes private final int _playerDecisionTimeoutPeriod = 1000 * 60 * 10; // 10 minutes + private ReentrantReadWriteLock _lock = new ReentrantReadWriteLock(true); + private ReentrantReadWriteLock.ReadLock _readLock = _lock.readLock(); + private ReentrantReadWriteLock.WriteLock _writeLock = _lock.writeLock(); + public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, GameResultListener gameResultListener) { if (participants.length < 1) throw new IllegalArgumentException("Game can't have less than one participant"); @@ -54,100 +59,168 @@ public class LotroGameMediator { return "Playing"; } - public synchronized String produceCardInfo(String participantId, int cardId) { - StringBuilder sb = new StringBuilder(); + public String produceCardInfo(String participantId, int cardId) { + _readLock.lock(); + try { + StringBuilder sb = new StringBuilder(); - PhysicalCard card = _lotroGame.getGameState().findCardById(cardId); - if (card == null) - return null; + PhysicalCard card = _lotroGame.getGameState().findCardById(cardId); + if (card == null) + return null; - sb.append("Affecting card:"); - Collection modifiers = _lotroGame.getModifiersQuerying().getModifiersAffecting(_lotroGame.getGameState(), card); - for (Modifier modifier : modifiers) { - PhysicalCard source = modifier.getSource(); - if (source != null) - sb.append("
" + source.getBlueprint().getName() + ": " + modifier.getText()); - else - sb.append("
System: " + modifier.getText()); - } - if (modifiers.size() == 0) - sb.append("
nothing"); - - CardType type = card.getBlueprint().getCardType(); - if (type == CardType.COMPANION || type == CardType.ALLY || type == CardType.MINION) { - sb.append("

Effective stats:"); - sb.append("
Strength: " + _lotroGame.getModifiersQuerying().getStrength(_lotroGame.getGameState(), card)); - sb.append("
Vitality: " + _lotroGame.getModifiersQuerying().getVitality(_lotroGame.getGameState(), card)); - if (type == CardType.MINION) - sb.append("
Twilight cost: " + _lotroGame.getModifiersQuerying().getTwilightCost(_lotroGame.getGameState(), card)); - } - - return sb.toString(); - } - - public synchronized void startGame() { - _lotroGame.startGame(); - startClocksForUsersPendingDecision(); - } - - public synchronized void cleanup() { - long currentTime = System.currentTimeMillis(); - Map channelsCopy = new HashMap(_communicationChannels); - for (Map.Entry playerChannels : channelsCopy.entrySet()) { - String playerId = playerChannels.getKey(); - // Channel is stale (user no longer connected to game, to save memory, we remove the channel - // User can always reconnect and establish a new channel - GatheringParticipantCommunicationChannel channel = playerChannels.getValue(); - if (currentTime > channel.getLastConsumed().getTime() + _channelInactivityTimeoutPeriod) { - _lotroGame.removeGameStateListener(playerId, channel); - _communicationChannels.remove(playerId); + sb.append("Affecting card:"); + Collection modifiers = _lotroGame.getModifiersQuerying().getModifiersAffecting(_lotroGame.getGameState(), card); + for (Modifier modifier : modifiers) { + PhysicalCard source = modifier.getSource(); + if (source != null) + sb.append("
" + source.getBlueprint().getName() + ": " + modifier.getText()); + else + sb.append("
System: " + modifier.getText()); } - } + if (modifiers.size() == 0) + sb.append("
nothing"); - if (_lotroGame.getGameState() != null && _lotroGame.getWinnerPlayerId() == null) { - for (Map.Entry playerDecision : _decisionQuerySentTimes.entrySet()) { - String playerId = playerDecision.getKey(); - long decisionSent = playerDecision.getValue(); - if (currentTime > decisionSent + _playerDecisionTimeoutPeriod) - _lotroGame.playerLost(playerId, "Player decision timed-out"); + CardType type = card.getBlueprint().getCardType(); + if (type == CardType.COMPANION || type == CardType.ALLY || type == CardType.MINION) { + sb.append("

Effective stats:"); + sb.append("
Strength: " + _lotroGame.getModifiersQuerying().getStrength(_lotroGame.getGameState(), card)); + sb.append("
Vitality: " + _lotroGame.getModifiersQuerying().getVitality(_lotroGame.getGameState(), card)); + if (type == CardType.MINION) + sb.append("
Twilight cost: " + _lotroGame.getModifiersQuerying().getTwilightCost(_lotroGame.getGameState(), card)); } - } - for (Map.Entry playerClock : _playerClocks.entrySet()) { - String player = playerClock.getKey(); - if (_maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(player) < 0) - _lotroGame.playerLost(player, "Player run out of time"); + return sb.toString(); + } finally { + _readLock.unlock(); } } - public synchronized void playerAnswered(String lotroGameParticipant, int decisionId, String answer) { - AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(lotroGameParticipant); - if (awaitingDecision != null) { - if (awaitingDecision.getAwaitingDecisionId() == decisionId) { - try { - _userFeedback.participantDecided(lotroGameParticipant); - awaitingDecision.decisionMade(answer); + public void startGame() { + _writeLock.lock(); + try { + _lotroGame.startGame(); + startClocksForUsersPendingDecision(); + } finally { + _writeLock.unlock(); + } + } - // Decision successfully made, add the time to user clock - addTimeSpentOnDecisionToUserClock(lotroGameParticipant); - - _lotroGame.carryOutPendingActionsUntilDecisionNeeded(); - startClocksForUsersPendingDecision(); - - } catch (DecisionResultInvalidException decisionResultInvalidException) { - // Participant provided wrong answer - send a warning message, and ask again for the same decision -// _userCommunication.sendWarning(lotroGameParticipant, decisionResultInvalidException.getWarningMessage()); - _userFeedback.sendAwaitingDecision(lotroGameParticipant, awaitingDecision); + public void cleanup() { + _writeLock.lock(); + try { + long currentTime = System.currentTimeMillis(); + Map channelsCopy = new HashMap(_communicationChannels); + for (Map.Entry playerChannels : channelsCopy.entrySet()) { + String playerId = playerChannels.getKey(); + // Channel is stale (user no longer connected to game, to save memory, we remove the channel + // User can always reconnect and establish a new channel + GatheringParticipantCommunicationChannel channel = playerChannels.getValue(); + if (currentTime > channel.getLastConsumed().getTime() + _channelInactivityTimeoutPeriod) { + _lotroGame.removeGameStateListener(playerId, channel); + _communicationChannels.remove(playerId); } } + + if (_lotroGame.getGameState() != null && _lotroGame.getWinnerPlayerId() == null) { + for (Map.Entry playerDecision : _decisionQuerySentTimes.entrySet()) { + String playerId = playerDecision.getKey(); + long decisionSent = playerDecision.getValue(); + if (currentTime > decisionSent + _playerDecisionTimeoutPeriod) + _lotroGame.playerLost(playerId, "Player decision timed-out"); + } + } + + for (Map.Entry playerClock : _playerClocks.entrySet()) { + String player = playerClock.getKey(); + if (_maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(player) < 0) + _lotroGame.playerLost(player, "Player run out of time"); + } + } finally { + _writeLock.unlock(); } } - public synchronized void processCommunicationChannel(String participantId, ParticipantCommunicationVisitor visitor) { - GatheringParticipantCommunicationChannel communicationChannel = _communicationChannels.get(participantId); - if (communicationChannel != null) { - for (GameEvent gameEvent : communicationChannel.consumeGameEvents()) + public void playerAnswered(String lotroGameParticipant, int decisionId, String answer) { + _writeLock.lock(); + try { + AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(lotroGameParticipant); + if (awaitingDecision != null) { + if (awaitingDecision.getAwaitingDecisionId() == decisionId) { + try { + _userFeedback.participantDecided(lotroGameParticipant); + awaitingDecision.decisionMade(answer); + + // Decision successfully made, add the time to user clock + addTimeSpentOnDecisionToUserClock(lotroGameParticipant); + + _lotroGame.carryOutPendingActionsUntilDecisionNeeded(); + startClocksForUsersPendingDecision(); + + } catch (DecisionResultInvalidException decisionResultInvalidException) { + // Participant provided wrong answer - send a warning message, and ask again for the same decision +// _userCommunication.sendWarning(lotroGameParticipant, decisionResultInvalidException.getWarningMessage()); + _userFeedback.sendAwaitingDecision(lotroGameParticipant, awaitingDecision); + } + } + } + } finally { + _writeLock.unlock(); + } + } + + public void processCommunicationChannel(String participantId, ParticipantCommunicationVisitor visitor) { + _readLock.lock(); + try { + GatheringParticipantCommunicationChannel communicationChannel = _communicationChannels.get(participantId); + if (communicationChannel != null) { + for (GameEvent gameEvent : communicationChannel.consumeGameEvents()) + visitor.visitGameEvent(gameEvent); + AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(participantId); + if (awaitingDecision != null) + visitor.visitAwaitingDecision(awaitingDecision); + + Map secondsLeft = new HashMap(); + for (Map.Entry playerClock : _playerClocks.entrySet()) { + String player = playerClock.getKey(); + secondsLeft.put(player, _maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(player)); + } + visitor.visitClock(secondsLeft); + + GameState gameState = _lotroGame.getGameState(); + if (gameState != null) { + Skirmish skirmish = gameState.getSkirmish(); + if (skirmish != null) { + int fpStrength = 0; + PhysicalCard fpChar = skirmish.getFellowshipCharacter(); + if (fpChar != null) + fpStrength = _lotroGame.getModifiersQuerying().getStrength(gameState, fpChar); + + int minionStrength = 0; + for (PhysicalCard minion : skirmish.getShadowCharacters()) + minionStrength += _lotroGame.getModifiersQuerying().getStrength(gameState, minion); + + visitor.visitSkirmishStats(fpStrength, minionStrength); + } + } + } else { + visitor.visitGameEvent(new GameEvent(GameEvent.Type.WARNING).message("Your browser was inactive for too long, please refresh your browser window to continue playing")); + } + } finally { + _readLock.unlock(); + } + } + + public void singupUserForGame(String participantId, ParticipantCommunicationVisitor visitor) { + _readLock.lock(); + try { + GatheringParticipantCommunicationChannel participantCommunicationChannel = new GatheringParticipantCommunicationChannel(participantId); + _communicationChannels.put(participantId, participantCommunicationChannel); + + _lotroGame.addGameStateListener(participantId, participantCommunicationChannel); + + for (GameEvent gameEvent : participantCommunicationChannel.consumeGameEvents()) visitor.visitGameEvent(gameEvent); + AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(participantId); if (awaitingDecision != null) visitor.visitAwaitingDecision(awaitingDecision); @@ -158,49 +231,11 @@ public class LotroGameMediator { secondsLeft.put(player, _maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(player)); } visitor.visitClock(secondsLeft); - - GameState gameState = _lotroGame.getGameState(); - if (gameState != null) { - Skirmish skirmish = gameState.getSkirmish(); - if (skirmish != null) { - int fpStrength = 0; - PhysicalCard fpChar = skirmish.getFellowshipCharacter(); - if (fpChar != null) - fpStrength = _lotroGame.getModifiersQuerying().getStrength(gameState, fpChar); - - int minionStrength = 0; - for (PhysicalCard minion : skirmish.getShadowCharacters()) - minionStrength += _lotroGame.getModifiersQuerying().getStrength(gameState, minion); - - visitor.visitSkirmishStats(fpStrength, minionStrength); - } - } - } else { - visitor.visitGameEvent(new GameEvent(GameEvent.Type.WARNING).message("Your browser was inactive for too long, please refresh your browser window to continue playing")); + } finally { + _readLock.unlock(); } } - public synchronized void singupUserForGame(String participantId, ParticipantCommunicationVisitor visitor) { - GatheringParticipantCommunicationChannel participantCommunicationChannel = new GatheringParticipantCommunicationChannel(participantId); - _communicationChannels.put(participantId, participantCommunicationChannel); - - _lotroGame.addGameStateListener(participantId, participantCommunicationChannel); - - for (GameEvent gameEvent : participantCommunicationChannel.consumeGameEvents()) - visitor.visitGameEvent(gameEvent); - - AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(participantId); - if (awaitingDecision != null) - visitor.visitAwaitingDecision(awaitingDecision); - - Map secondsLeft = new HashMap(); - for (Map.Entry playerClock : _playerClocks.entrySet()) { - String player = playerClock.getKey(); - secondsLeft.put(player, _maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(player)); - } - visitor.visitClock(secondsLeft); - } - private void startClocksForUsersPendingDecision() { long currentTime = System.currentTimeMillis(); Set users = _userFeedback.getUsersPendingDecision(); diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gameUi.js b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gameUi.js index ae4687a0f..8e87f02a2 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gameUi.js +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gameUi.js @@ -305,15 +305,19 @@ var GempLotrGameUI = Class.extend({ this.windowHeight = height; } - var heightScales = [5, 9, 9, 10, 6, 10]; + var heightScales; + if (this.spectatorMode) + heightScales = [6, 10, 10, 10, 6]; + else + heightScales = [5, 9, 9, 10, 6, 10]; var yScales = new Array(); var scaleTotal = 0; - for (var i = 0; i < (this.spectatorMode ? (heightScales.length - 1) : heightScales.length); i++) { + for (var i = 0; i < heightScales.length; i++) { yScales[i] = scaleTotal; scaleTotal += heightScales[i]; } - var heightPerScale = (height - (padding * 7)) / scaleTotal; + var heightPerScale = (height - (padding * (heightScales.length + 1))) / scaleTotal; var advPathWidth = Math.min(150, width * 0.1); var specialUiWidth = 150;