Fixing spectator mode UI weights and also fixing discard and dead pile cards after reload.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user