diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java index 0481be20b..352f772fc 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java @@ -3,19 +3,26 @@ package com.gempukku.lotro.game.state; import com.gempukku.lotro.common.Token; import com.gempukku.lotro.communication.GameStateListener; import com.gempukku.lotro.game.PhysicalCard; -import static com.gempukku.lotro.game.state.GameEvent.Type.*; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.timing.GameStats; import java.util.*; +import static com.gempukku.lotro.game.state.GameEvent.Type.*; + public class GatheringParticipantCommunicationChannel implements GameStateListener { private List _events = new LinkedList(); private String _self; private Date _lastConsumed = new Date(); + private int _channelNumber; - public GatheringParticipantCommunicationChannel(String self) { + public GatheringParticipantCommunicationChannel(String self, int channelNumber) { _self = self; + _channelNumber = channelNumber; + } + + public int getChannelNumber() { + return _channelNumber; } @Override 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 605ab1fa7..8e8a2cc88 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 @@ -32,6 +32,7 @@ public class LotroGameMediator { private ReentrantReadWriteLock _lock = new ReentrantReadWriteLock(true); private ReentrantReadWriteLock.ReadLock _readLock = _lock.readLock(); private ReentrantReadWriteLock.WriteLock _writeLock = _lock.writeLock(); + private int _channelNextIndex = 0; public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, int maxSecondsForGamePerPlayer, boolean noSpectators) { @@ -287,7 +288,7 @@ public class LotroGameMediator { } } - public boolean processCommunicationChannel(Player player, ParticipantCommunicationVisitor visitor) { + public boolean processCommunicationChannel(Player player, int channelNumber, ParticipantCommunicationVisitor visitor) { String playerName = player.getName(); if (_noSpectators && !_playersPlaying.contains(playerName)) return false; @@ -296,19 +297,24 @@ public class LotroGameMediator { try { GatheringParticipantCommunicationChannel communicationChannel = _communicationChannels.get(playerName); if (communicationChannel != null) { - for (GameEvent gameEvent : communicationChannel.consumeGameEvents()) - visitor.visitGameEvent(gameEvent); + if (communicationChannel.getChannelNumber() == channelNumber) { + visitor.visitChannelNumber(channelNumber); + for (GameEvent gameEvent : communicationChannel.consumeGameEvents()) + visitor.visitGameEvent(gameEvent); - String warning = _userFeedback.consumeWarning(playerName); - if (warning != null) - visitor.visitGameEvent(new GameEvent(GameEvent.Type.W).message(warning)); + String warning = _userFeedback.consumeWarning(playerName); + if (warning != null) + visitor.visitGameEvent(new GameEvent(GameEvent.Type.W).message(warning)); - Map secondsLeft = new HashMap(); - for (Map.Entry playerClock : _playerClocks.entrySet()) { - String playerClockName = playerClock.getKey(); - secondsLeft.put(playerClockName, _maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(playerClockName)); + Map secondsLeft = new HashMap(); + for (Map.Entry playerClock : _playerClocks.entrySet()) { + String playerClockName = playerClock.getKey(); + secondsLeft.put(playerClockName, _maxSecondsForGamePerPlayer - playerClock.getValue() - getCurrentUserPendingTime(playerClockName)); + } + visitor.visitClock(secondsLeft); + } else { + visitor.visitGameEvent(new GameEvent(GameEvent.Type.W).message("You have joined this game in another window, please refresh your browser window (press F5) if you wish to continue playing in this window")); } - visitor.visitClock(secondsLeft); } else { visitor.visitGameEvent(new GameEvent(GameEvent.Type.W).message("Your browser was inactive for too long, please refresh your browser window to continue playing")); } @@ -325,11 +331,16 @@ public class LotroGameMediator { _readLock.lock(); try { - GatheringParticipantCommunicationChannel participantCommunicationChannel = new GatheringParticipantCommunicationChannel(playerName); + int number = _channelNextIndex; + _channelNextIndex++; + + GatheringParticipantCommunicationChannel participantCommunicationChannel = new GatheringParticipantCommunicationChannel(playerName, number); _communicationChannels.put(playerName, participantCommunicationChannel); _lotroGame.addGameStateListener(playerName, participantCommunicationChannel); + visitor.visitChannelNumber(number); + for (GameEvent gameEvent : participantCommunicationChannel.consumeGameEvents()) visitor.visitGameEvent(gameEvent); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/ParticipantCommunicationVisitor.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/ParticipantCommunicationVisitor.java index 40fd1187a..ac419c814 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/ParticipantCommunicationVisitor.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/ParticipantCommunicationVisitor.java @@ -5,6 +5,8 @@ import com.gempukku.lotro.game.state.GameEvent; import java.util.Map; public interface ParticipantCommunicationVisitor { + public void visitChannelNumber(int channelNumber); + public void visitClock(Map secondsLeft); public void visitGameEvent(GameEvent gameEvent); diff --git a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/GameResource.java b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/GameResource.java index 0b434cff1..9c71f3bf2 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/GameResource.java +++ b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/GameResource.java @@ -131,6 +131,7 @@ public class GameResource extends AbstractResource { @FormParam("participantId") String participantId, @FormParam("decisionId") Integer decisionId, @FormParam("decisionValue") String decisionValue, + @FormParam("channelNumber") int channelNumber, @Context HttpServletRequest request, @Context HttpServletResponse response) throws ParserConfigurationException { Player resourceOwner = getResourceOwnerSafely(request, participantId); @@ -158,7 +159,7 @@ public class GameResource extends AbstractResource { Document doc = documentBuilder.newDocument(); Element update = doc.createElement("update"); - if (!gameMediator.processCommunicationChannel(resourceOwner, new SerializationVisitor(doc, update))) + if (!gameMediator.processCommunicationChannel(resourceOwner, channelNumber, new SerializationVisitor(doc, update))) sendError(Response.Status.FORBIDDEN); doc.appendChild(update); @@ -182,6 +183,11 @@ public class GameResource extends AbstractResource { _element = element; } + @Override + public void visitChannelNumber(int channelNumber) { + _element.setAttribute("cn", String.valueOf(channelNumber)); + } + @Override public void visitGameEvent(GameEvent gameEvent) { _element.appendChild(_eventSerializer.serializeEvent(_doc, gameEvent)); diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/communication.js b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/communication.js index 825229d38..513ccc4a6 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/communication.js +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/communication.js @@ -103,12 +103,14 @@ var GempLotrCommunication = Class.extend({ dataType: "xml" }); }, - updateGameState: function(callback, errorMap) { + updateGameState: function(channelNumber, callback, errorMap) { $.ajax({ type: "POST", url: this.url + "/game/" + getUrlParam("gameId"), cache: false, - data: { participantId: getUrlParam("participantId") }, + data: { + channelNumber: channelNumber, + participantId: getUrlParam("participantId") }, success: this.deliveryCheck(callback), error: this.errorCheck(errorMap), dataType: "xml" @@ -119,22 +121,24 @@ var GempLotrCommunication = Class.extend({ type: "GET", url: this.url + "/game/" + getUrlParam("gameId") + "/cardInfo", cache: false, - data: { cardId: cardId, + data: { + cardId: cardId, participantId: getUrlParam("participantId") }, success: this.deliveryCheck(callback), error: this.errorCheck(errorMap), dataType: "html" }); }, - gameDecisionMade: function(decisionId, response, callback, errorMap) { + gameDecisionMade: function(decisionId, response, channelNumber, callback, errorMap) { $.ajax({ type: "POST", url: this.url + "/game/" + getUrlParam("gameId"), cache: false, data: { + channelNumber: channelNumber, participantId: getUrlParam("participantId"), decisionId: decisionId, - decisionValue: response}, + decisionValue: response }, success: this.deliveryCheck(callback), error: this.errorCheck(errorMap), dataType: "xml" @@ -158,7 +162,7 @@ var GempLotrCommunication = Class.extend({ cache: false, data: { participantId: getUrlParam("participantId"), - deckName: deckName}, + deckName: deckName }, success: this.deliveryCheck(callback), error: this.errorCheck(errorMap), dataType: "xml" 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 41431ed1d..cebb8391d 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 @@ -54,6 +54,7 @@ var GempLotrGameUI = Class.extend({ chatBoxDiv: null, chatBox: null, communication: null, + channelNumber: null, settingsAutoPass: false, settingsAutoAccept: false, @@ -658,21 +659,21 @@ var GempLotrGameUI = Class.extend({ initializeDialogs: function() { this.smallDialog = $("
") .dialog({ - autoOpen: false, - closeOnEscape: false, - resizable: false, - width: 400, - height: 200 - }); + autoOpen: false, + closeOnEscape: false, + resizable: false, + width: 400, + height: 200 + }); this.cardActionDialog = $("
") .dialog({ - autoOpen: false, - closeOnEscape: false, - resizable: true, - width: 600, - height: 300 - }); + autoOpen: false, + closeOnEscape: false, + resizable: true, + width: 600, + height: 300 + }); var that = this; @@ -687,11 +688,11 @@ var GempLotrGameUI = Class.extend({ this.infoDialog = $("
") .dialog({ - autoOpen: false, - closeOnEscape: true, - resizable: false, - title: "Card information" - }); + autoOpen: false, + closeOnEscape: true, + resizable: false, + title: "Card information" + }); var swipeOptions = { threshold: 20, @@ -857,6 +858,7 @@ var GempLotrGameUI = Class.extend({ updateGameState: function() { var that = this; this.communication.updateGameState( + this.channelNumber, function(xml) { that.processXml(xml, true); }); @@ -865,6 +867,7 @@ var GempLotrGameUI = Class.extend({ decisionFunction: function(decisionId, result) { var that = this; this.communication.gameDecisionMade(decisionId, result, + this.channelNumber, function(xml) { that.processXml(xml, true); }); @@ -984,6 +987,8 @@ var GempLotrGameUI = Class.extend({ }, processGameEventsXml: function(element, animate) { + this.channelNumber = element.getAttribute("cn"); + var gameEvents = element.getElementsByTagName("ge"); var hasDecision = false; @@ -1198,12 +1203,12 @@ var GempLotrGameUI = Class.extend({ if (!this.replayMode) { this.smallDialog.dialog("option", "buttons", - { - "OK": function() { - $(this).dialog("close"); - that.decisionFunction(id, $("#integerDecision").val()); - } - }); + { + "OK": function() { + $(this).dialog("close"); + that.decisionFunction(id, $("#integerDecision").val()); + } + }); } $("#integerDecision").SpinnerControl({ type: 'range', @@ -1241,12 +1246,12 @@ var GempLotrGameUI = Class.extend({ if (!this.replayMode) { this.smallDialog.dialog("option", "buttons", - { - "OK": function() { - that.smallDialog.dialog("close"); - that.decisionFunction(id, $("#multipleChoiceDecision").val()); - } - }); + { + "OK": function() { + that.smallDialog.dialog("close"); + that.decisionFunction(id, $("#multipleChoiceDecision").val()); + } + }); } } else { this.smallDialog.append("
"); @@ -1639,8 +1644,8 @@ var GempLotrGameUI = Class.extend({ $(div).find('LI.hover').removeClass('hover'); $(this).parent().addClass('hover'); }).mouseout(function() { - $(div).find('LI.hover').removeClass('hover'); - }); + $(div).find('LI.hover').removeClass('hover'); + }); var getRidOfContextMenu = function() { $(div).remove();