diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java index b0b9d11c3..18ff03e97 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java @@ -19,6 +19,8 @@ public class EventSerializer { eventElem.setAttribute("cardId", gameEvent.getCardId().toString()); if (gameEvent.getIndex() != null) eventElem.setAttribute("index", gameEvent.getIndex().toString()); + if (gameEvent.getDate() != null) + eventElem.setAttribute("date", String.valueOf(gameEvent.getDate().getTime())); if (gameEvent.getControllerId() != null) eventElem.setAttribute("controllerId", gameEvent.getControllerId()); if (gameEvent.getParticipantId() != null) diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java index 870dc3883..bcb7094bd 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java @@ -7,6 +7,7 @@ import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.timing.GameStats; +import java.util.Date; import java.util.List; public class GameEvent { @@ -18,10 +19,11 @@ public class GameEvent { AT, RT, M, W, GS, - CAC, EP, CA, D + CAC, EP, CA, D, CH } private String _message; + private Date _date; private String _side; private Type _type; private Zone _zone; @@ -52,6 +54,15 @@ public class GameEvent { return this; } + public Date getDate() { + return _date; + } + + public GameEvent date(Date date) { + _date = date; + return this; + } + public Type getType() { return _type; } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java index 75dbd7de7..3f73a78e0 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java @@ -3,7 +3,6 @@ package com.gempukku.lotro.game; import com.gempukku.lotro.common.ApplicationConfiguration; import com.gempukku.lotro.game.state.EventSerializer; import com.gempukku.lotro.game.state.GameEvent; -import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel; import org.w3c.dom.Document; import org.w3c.dom.Element; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringParticipantCommunicationChannel.java similarity index 90% rename from gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java rename to gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringParticipantCommunicationChannel.java index bcdf9a818..e3fdd83ee 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GatheringParticipantCommunicationChannel.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GatheringParticipantCommunicationChannel.java @@ -1,8 +1,10 @@ -package com.gempukku.lotro.game.state; +package com.gempukku.lotro.game; +import com.gempukku.lotro.chat.ChatMessage; +import com.gempukku.lotro.chat.ChatRoomListener; import com.gempukku.lotro.common.Token; import com.gempukku.lotro.communication.GameStateListener; -import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.GameEvent; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.timing.GameStats; @@ -10,7 +12,7 @@ import java.util.*; import static com.gempukku.lotro.game.state.GameEvent.Type.*; -public class GatheringParticipantCommunicationChannel implements GameStateListener { +public class GatheringParticipantCommunicationChannel implements GameStateListener, ChatRoomListener { private List _events = new LinkedList(); private String _self; private Date _lastConsumed = new Date(); @@ -43,6 +45,11 @@ public class GatheringParticipantCommunicationChannel implements GameStateListen return result; } + @Override + public void messageReceived(ChatMessage message) { + _events.add(new GameEvent(CH).participantId(message.getFrom()).message(message.getMessage()).date(message.getWhen())); + } + @Override public void addAssignment(PhysicalCard freePeople, Set minions) { _events.add(new GameEvent(AA).cardId(freePeople.getCardId()).otherCardIds(getCardIds(minions))); 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 2a60be2c1..afacbfdea 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 @@ -3,11 +3,11 @@ package com.gempukku.lotro.game; import com.gempukku.lotro.PrivateInformationException; import com.gempukku.lotro.SubscriptionConflictException; import com.gempukku.lotro.SubscriptionExpiredException; +import com.gempukku.lotro.chat.ChatRoom; import com.gempukku.lotro.common.*; import com.gempukku.lotro.communication.GameStateListener; import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.state.GameEvent; -import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel; import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -40,6 +40,7 @@ public class LotroGameMediator { private ReentrantReadWriteLock.ReadLock _readLock = _lock.readLock(); private ReentrantReadWriteLock.WriteLock _writeLock = _lock.writeLock(); private int _channelNextIndex = 0; + private ChatRoom _chatRoom; public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, int maxSecondsForGamePerPlayer, boolean allowSpectators, boolean cancellable) { @@ -61,6 +62,7 @@ public class LotroGameMediator { _userFeedback = new DefaultUserFeedback(); _lotroGame = new DefaultLotroGame(lotroFormat, decks, _userFeedback, library); _userFeedback.setGame(_lotroGame); + _chatRoom = new ChatRoom(false); } public boolean isAllowSpectators() { @@ -77,6 +79,14 @@ public class LotroGameMediator { _lotroGame.getGameState().sendMessage(message); } + public void sendMessage(Player player, String message) throws PrivateInformationException { + String playerName = player.getName(); + if (!player.getType().contains("a") && !_allowSpectators && !_playersPlaying.contains(playerName)) + throw new PrivateInformationException(); + + _chatRoom.postMessage(playerName, message); + } + public void addGameStateListener(String playerId, GameStateListener listener) { _lotroGame.addGameStateListener(playerId, listener); } @@ -239,6 +249,7 @@ public class LotroGameMediator { if (currentTime > channel.getLastConsumed().getTime() + _playerDecisionTimeoutPeriod) { _lotroGame.removeGameStateListener(channel); _communicationChannels.remove(playerId); + _chatRoom.partChatRoom(playerId); } } @@ -404,6 +415,7 @@ public class LotroGameMediator { _communicationChannels.put(playerName, participantCommunicationChannel); _lotroGame.addGameStateListener(playerName, participantCommunicationChannel); + _chatRoom.joinChatRoom(playerName, participantCommunicationChannel); visitor.visitChannelNumber(number); diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java index cbabe231f..2db72b542 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/GameResource.java @@ -142,6 +142,26 @@ public class GameResource extends AbstractResource { gameMediator.cancel(resourceOwner); } + @Path("/{gameId}/chat") + @POST + public void sendMessage( + @PathParam("gameId") String gameId, + @FormParam("message") String message, + @FormParam("participantId") String participantId, + @Context HttpServletRequest request) throws ParserConfigurationException { + Player resourceOwner = getResourceOwnerSafely(request, participantId); + + LotroGameMediator gameMediator = _lotroServer.getGameById(gameId); + if (gameMediator == null) + throw new WebApplicationException(Response.Status.NOT_FOUND); + + try { + gameMediator.sendMessage(resourceOwner, message); + } catch (PrivateInformationException e) { + throw new WebApplicationException(Response.Status.FORBIDDEN); + } + } + @Path("/{gameId}") @POST @Produces(MediaType.APPLICATION_XML) @@ -174,7 +194,7 @@ public class GameResource extends AbstractResource { // Use long polling long start = System.currentTimeMillis(); - while (System.currentTimeMillis()< start+_longPollingLength && !gameMediator.hasAnyNewMessages(resourceOwner, channelNumber)) { + while (System.currentTimeMillis() < start + _longPollingLength && !gameMediator.hasAnyNewMessages(resourceOwner, channelNumber)) { try { Thread.sleep(_longPollingInterval); } catch (InterruptedException exp) { diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/chat.js b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/chat.js index 01c8af08d..2c69bfa9f 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/chat.js +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/chat.js @@ -21,8 +21,9 @@ var ChatBoxUI = Class.extend({ lockChat:false, stopUpdates: false, + sendMessageFunc: null, - init:function (name, div, url, showList, playerListener, showHideSystemButton, showLockButton) { + init:function (name, div, url, showList, playerListener, showHideSystemButton, showLockButton, startChat) { var that = this; this.hiddenClasses = new Array(); this.playerListener = playerListener; @@ -40,37 +41,37 @@ var ChatBoxUI = Class.extend({ if (showHideSystemButton) { this.hideSystemButton = $("").button( - {icons:{ - primary:"ui-icon-zoomin" - }, text:false}); + {icons:{ + primary:"ui-icon-zoomin" + }, text:false}); this.hideSystemButton.click( - function () { - if (that.isShowingMessageClass("systemMessage")) { - $('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomin'}); - that.hideMessageClass("systemMessage"); - } else { - $('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomout'}); - that.showMessageClass("systemMessage"); - } - }); + function () { + if (that.isShowingMessageClass("systemMessage")) { + $('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomin'}); + that.hideMessageClass("systemMessage"); + } else { + $('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomout'}); + that.showMessageClass("systemMessage"); + } + }); this.hideMessageClass("systemMessage"); } if (showLockButton) { this.lockButton = $("").button( - {icons:{ - primary:"ui-icon-locked" - }, text:false}); + {icons:{ + primary:"ui-icon-locked" + }, text:false}); this.lockButton.click( - function () { - if (that.lockChat) { - $('#lockChatButton').button("option", "icons", {primary:'ui-icon-locked'}); - that.lockChat = false; - } else { - $('#lockChatButton').button("option", "icons", {primary:'ui-icon-unlocked'}); - that.lockChat = true; - } - }); + function () { + if (that.lockChat) { + $('#lockChatButton').button("option", "icons", {primary:'ui-icon-locked'}); + that.lockChat = false; + } else { + $('#lockChatButton').button("option", "icons", {primary:'ui-icon-unlocked'}); + that.lockChat = true; + } + }); } if (showList) { @@ -83,10 +84,12 @@ var ChatBoxUI = Class.extend({ this.div.append(this.lockButton); this.div.append(this.chatTalkDiv); - this.communication.startChat(this.name, + if (startChat) { + this.communication.startChat(this.name, function (xml) { that.processMessages(xml, true); }, this.chatErrorMap()); + } this.chatTalkDiv.bind("keypress", function (e) { var code = (e.keyCode ? e.keyCode : e.which); @@ -150,6 +153,19 @@ var ChatBoxUI = Class.extend({ } }, + appendChatMessage: function(from, dateObj, text) { + var msgClass = "chatMessage"; + if (from == "System") + msgClass = "systemMessage"; + if (this.showTimestamps) { + var date = new Date(parseInt(dateObj)); + var dateStr = this.monthNames[date.getMonth()] + " " + date.getDate() + " " + this.formatToTwoDigits(date.getHours()) + ":" + this.formatToTwoDigits(date.getMinutes()) + ":" + this.formatToTwoDigits(date.getSeconds()); + this.appendMessage("
[" + dateStr + "]
" + from + ": " + text, msgClass); + } else { + this.appendMessage("" + from + ": " + text, msgClass); + } + }, + appendMessage:function (message, msgClass) { if (msgClass == undefined) msgClass = "chatMessage"; @@ -187,16 +203,7 @@ var ChatBoxUI = Class.extend({ var from = message.getAttribute("from"); var text = message.childNodes[0].nodeValue; - var msgClass = "chatMessage"; - if (from == "System") - msgClass = "systemMessage"; - if (this.showTimestamps) { - var date = new Date(parseInt(message.getAttribute("date"))); - var dateStr = this.monthNames[date.getMonth()] + " " + date.getDate() + " " + this.formatToTwoDigits(date.getHours()) + ":" + this.formatToTwoDigits(date.getMinutes()) + ":" + this.formatToTwoDigits(date.getSeconds()); - this.appendMessage("
[" + dateStr + "]
" + from + ": " + text, msgClass); - } else { - this.appendMessage("" + from + ": " + text, msgClass); - } + this.appendChatMessage(from, message.getAttribute("date"), text); } var users = root.getElementsByTagName("user"); @@ -239,10 +246,14 @@ var ChatBoxUI = Class.extend({ }, sendMessage:function (message) { - var that = this; - this.communication.sendChatMessage(this.name, message, function(xml) { - that.processMessages(xml, false); - }, this.chatErrorMap()); + if (this.sendMessageFunc != null) { + this.sendMessageFunc(message); + } else { + var that = this; + this.communication.sendChatMessage(this.name, message, function(xml) { + that.processMessages(xml, false); + }, this.chatErrorMap()); + } }, chatMalfunction: function() { diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/communication.js b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/communication.js index df87b45ed..1bba6611b 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/communication.js +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/communication.js @@ -208,6 +208,20 @@ var GempLotrCommunication = Class.extend({ dataType:"xml" }); }, + sendGameMessage: function(message, callback, errorMap) { + $.ajax({ + type:"POST", + url:this.url + "/game/" + getUrlParam("gameId")+"/chat", + cache:false, + async: false, + data:{ + message: message, + participantId:getUrlParam("participantId") }, + success:this.deliveryCheck(callback), + error:this.errorCheck(errorMap), + dataType:"xml" + }); + }, getGameCardModifiers:function (cardId, callback, errorMap) { $.ajax({ type:"GET", diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameAnimations.js b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameAnimations.js index 1b7517d76..9cd272baa 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameAnimations.js +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameAnimations.js @@ -863,6 +863,21 @@ var GameAnimations = Class.extend({ }); }, + chatMessage:function (element, animate) { + var that = this; + $("#main").queue( + function (next) { + var from = element.getAttribute("participantId"); + var date = element.getAttribute("date"); + var message = element.getAttribute("message"); + + if (that.game.chatBox != null) + that.game.chatBox.appendChatMessage(form, date, message); + + next(); + }); + }, + warning:function (element, animate) { var that = this; $("#main").queue( diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameUi.js b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameUi.js index 4ee9c15d2..dcc496566 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameUi.js +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/js/gemp-015/gameUi.js @@ -474,7 +474,11 @@ var GempLotrGameUI = Class.extend({ }; var chatRoomName = (this.replayMode ? null : ("Game" + getUrlParam("gameId"))); - this.chatBox = new ChatBoxUI(chatRoomName, $("#chatBox"), this.communication.url, false, playerListener, false, true); + this.chatBox = new ChatBoxUI(chatRoomName, $("#chatBox"), this.communication.url, false, playerListener, false, true, false); + this.chatBox.sendMessageFunc = + function(message) { + this.comm.sendGameMessage(message, function() {}, this.gameErrorMap()); + }; this.chatBox.chatUpdateInterval = 3000; if (!this.spectatorMode && !this.replayMode) { @@ -1053,6 +1057,8 @@ var GempLotrGameUI = Class.extend({ this.animations.cardActivated(gameEvent, animate); } else if (eventType == "D") { this.animations.processDecision(gameEvent, animate); + } else if (eventType == "CH") { + this.animations.chatMessage(gameEvent, animate); } },