Fixing spectator mode UI weights and also fixing discard and dead pile cards after reload.

This commit is contained in:
marcins78@gmail.com
2011-09-19 22:05:49 +00:00
parent d34274b251
commit 5900bb7a68
2 changed files with 160 additions and 121 deletions

View File

@@ -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<String, GatheringParticipantCommunicationChannel> _communicationChannels = new HashMap<String, GatheringParticipantCommunicationChannel>();
@@ -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("<b>Affecting card:</b>");
Collection<Modifier> modifiers = _lotroGame.getModifiersQuerying().getModifiersAffecting(_lotroGame.getGameState(), card);
for (Modifier modifier : modifiers) {
PhysicalCard source = modifier.getSource();
if (source != null)
sb.append("<br><b>" + source.getBlueprint().getName() + ":</b> " + modifier.getText());
else
sb.append("<br><b><i>System</i>:</b> " + modifier.getText());
}
if (modifiers.size() == 0)
sb.append("<br><i>nothing</i>");
CardType type = card.getBlueprint().getCardType();
if (type == CardType.COMPANION || type == CardType.ALLY || type == CardType.MINION) {
sb.append("<br><br><b>Effective stats:</b>");
sb.append("<br><b>Strength:</b> " + _lotroGame.getModifiersQuerying().getStrength(_lotroGame.getGameState(), card));
sb.append("<br><b>Vitality:</b> " + _lotroGame.getModifiersQuerying().getVitality(_lotroGame.getGameState(), card));
if (type == CardType.MINION)
sb.append("<br><b>Twilight cost:</b> " + _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<String, GatheringParticipantCommunicationChannel> channelsCopy = new HashMap<String, GatheringParticipantCommunicationChannel>(_communicationChannels);
for (Map.Entry<String, GatheringParticipantCommunicationChannel> 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("<b>Affecting card:</b>");
Collection<Modifier> modifiers = _lotroGame.getModifiersQuerying().getModifiersAffecting(_lotroGame.getGameState(), card);
for (Modifier modifier : modifiers) {
PhysicalCard source = modifier.getSource();
if (source != null)
sb.append("<br><b>" + source.getBlueprint().getName() + ":</b> " + modifier.getText());
else
sb.append("<br><b><i>System</i>:</b> " + modifier.getText());
}
}
if (modifiers.size() == 0)
sb.append("<br><i>nothing</i>");
if (_lotroGame.getGameState() != null && _lotroGame.getWinnerPlayerId() == null) {
for (Map.Entry<String, Long> 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("<br><br><b>Effective stats:</b>");
sb.append("<br><b>Strength:</b> " + _lotroGame.getModifiersQuerying().getStrength(_lotroGame.getGameState(), card));
sb.append("<br><b>Vitality:</b> " + _lotroGame.getModifiersQuerying().getVitality(_lotroGame.getGameState(), card));
if (type == CardType.MINION)
sb.append("<br><b>Twilight cost:</b> " + _lotroGame.getModifiersQuerying().getTwilightCost(_lotroGame.getGameState(), card));
}
}
for (Map.Entry<String, Integer> 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<String, GatheringParticipantCommunicationChannel> channelsCopy = new HashMap<String, GatheringParticipantCommunicationChannel>(_communicationChannels);
for (Map.Entry<String, GatheringParticipantCommunicationChannel> 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<String, Long> 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<String, Integer> 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<String, Integer> secondsLeft = new HashMap<String, Integer>();
for (Map.Entry<String, Integer> 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<String, Integer> secondsLeft = new HashMap<String, Integer>();
for (Map.Entry<String, Integer> 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<String> users = _userFeedback.getUsersPendingDecision();

View File

@@ -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;