Chat messages are now part of the game.

This commit is contained in:
marcins78
2013-01-08 17:13:59 +00:00
parent 68933856d8
commit 3accb1ffa7
10 changed files with 145 additions and 48 deletions

View File

@@ -19,6 +19,8 @@ public class EventSerializer {
eventElem.setAttribute("cardId", gameEvent.getCardId().toString()); eventElem.setAttribute("cardId", gameEvent.getCardId().toString());
if (gameEvent.getIndex() != null) if (gameEvent.getIndex() != null)
eventElem.setAttribute("index", gameEvent.getIndex().toString()); eventElem.setAttribute("index", gameEvent.getIndex().toString());
if (gameEvent.getDate() != null)
eventElem.setAttribute("date", String.valueOf(gameEvent.getDate().getTime()));
if (gameEvent.getControllerId() != null) if (gameEvent.getControllerId() != null)
eventElem.setAttribute("controllerId", gameEvent.getControllerId()); eventElem.setAttribute("controllerId", gameEvent.getControllerId());
if (gameEvent.getParticipantId() != null) if (gameEvent.getParticipantId() != null)

View File

@@ -7,6 +7,7 @@ import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.AwaitingDecision;
import com.gempukku.lotro.logic.timing.GameStats; import com.gempukku.lotro.logic.timing.GameStats;
import java.util.Date;
import java.util.List; import java.util.List;
public class GameEvent { public class GameEvent {
@@ -18,10 +19,11 @@ public class GameEvent {
AT, RT, AT, RT,
M, W, M, W,
GS, GS,
CAC, EP, CA, D CAC, EP, CA, D, CH
} }
private String _message; private String _message;
private Date _date;
private String _side; private String _side;
private Type _type; private Type _type;
private Zone _zone; private Zone _zone;
@@ -52,6 +54,15 @@ public class GameEvent {
return this; return this;
} }
public Date getDate() {
return _date;
}
public GameEvent date(Date date) {
_date = date;
return this;
}
public Type getType() { public Type getType() {
return _type; return _type;
} }

View File

@@ -3,7 +3,6 @@ package com.gempukku.lotro.game;
import com.gempukku.lotro.common.ApplicationConfiguration; import com.gempukku.lotro.common.ApplicationConfiguration;
import com.gempukku.lotro.game.state.EventSerializer; import com.gempukku.lotro.game.state.EventSerializer;
import com.gempukku.lotro.game.state.GameEvent; import com.gempukku.lotro.game.state.GameEvent;
import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;

View File

@@ -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.common.Token;
import com.gempukku.lotro.communication.GameStateListener; 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.decisions.AwaitingDecision;
import com.gempukku.lotro.logic.timing.GameStats; import com.gempukku.lotro.logic.timing.GameStats;
@@ -10,7 +12,7 @@ import java.util.*;
import static com.gempukku.lotro.game.state.GameEvent.Type.*; import static com.gempukku.lotro.game.state.GameEvent.Type.*;
public class GatheringParticipantCommunicationChannel implements GameStateListener { public class GatheringParticipantCommunicationChannel implements GameStateListener, ChatRoomListener {
private List<GameEvent> _events = new LinkedList<GameEvent>(); private List<GameEvent> _events = new LinkedList<GameEvent>();
private String _self; private String _self;
private Date _lastConsumed = new Date(); private Date _lastConsumed = new Date();
@@ -43,6 +45,11 @@ public class GatheringParticipantCommunicationChannel implements GameStateListen
return result; return result;
} }
@Override
public void messageReceived(ChatMessage message) {
_events.add(new GameEvent(CH).participantId(message.getFrom()).message(message.getMessage()).date(message.getWhen()));
}
@Override @Override
public void addAssignment(PhysicalCard freePeople, Set<PhysicalCard> minions) { public void addAssignment(PhysicalCard freePeople, Set<PhysicalCard> minions) {
_events.add(new GameEvent(AA).cardId(freePeople.getCardId()).otherCardIds(getCardIds(minions))); _events.add(new GameEvent(AA).cardId(freePeople.getCardId()).otherCardIds(getCardIds(minions)));

View File

@@ -3,11 +3,11 @@ package com.gempukku.lotro.game;
import com.gempukku.lotro.PrivateInformationException; import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionConflictException; import com.gempukku.lotro.SubscriptionConflictException;
import com.gempukku.lotro.SubscriptionExpiredException; import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.chat.ChatRoom;
import com.gempukku.lotro.common.*; import com.gempukku.lotro.common.*;
import com.gempukku.lotro.communication.GameStateListener; import com.gempukku.lotro.communication.GameStateListener;
import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.state.GameEvent; 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.GameUtils;
import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.AwaitingDecision;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
@@ -40,6 +40,7 @@ public class LotroGameMediator {
private ReentrantReadWriteLock.ReadLock _readLock = _lock.readLock(); private ReentrantReadWriteLock.ReadLock _readLock = _lock.readLock();
private ReentrantReadWriteLock.WriteLock _writeLock = _lock.writeLock(); private ReentrantReadWriteLock.WriteLock _writeLock = _lock.writeLock();
private int _channelNextIndex = 0; private int _channelNextIndex = 0;
private ChatRoom _chatRoom;
public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, int maxSecondsForGamePerPlayer, public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, int maxSecondsForGamePerPlayer,
boolean allowSpectators, boolean cancellable) { boolean allowSpectators, boolean cancellable) {
@@ -61,6 +62,7 @@ public class LotroGameMediator {
_userFeedback = new DefaultUserFeedback(); _userFeedback = new DefaultUserFeedback();
_lotroGame = new DefaultLotroGame(lotroFormat, decks, _userFeedback, library); _lotroGame = new DefaultLotroGame(lotroFormat, decks, _userFeedback, library);
_userFeedback.setGame(_lotroGame); _userFeedback.setGame(_lotroGame);
_chatRoom = new ChatRoom(false);
} }
public boolean isAllowSpectators() { public boolean isAllowSpectators() {
@@ -77,6 +79,14 @@ public class LotroGameMediator {
_lotroGame.getGameState().sendMessage(message); _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) { public void addGameStateListener(String playerId, GameStateListener listener) {
_lotroGame.addGameStateListener(playerId, listener); _lotroGame.addGameStateListener(playerId, listener);
} }
@@ -239,6 +249,7 @@ public class LotroGameMediator {
if (currentTime > channel.getLastConsumed().getTime() + _playerDecisionTimeoutPeriod) { if (currentTime > channel.getLastConsumed().getTime() + _playerDecisionTimeoutPeriod) {
_lotroGame.removeGameStateListener(channel); _lotroGame.removeGameStateListener(channel);
_communicationChannels.remove(playerId); _communicationChannels.remove(playerId);
_chatRoom.partChatRoom(playerId);
} }
} }
@@ -404,6 +415,7 @@ public class LotroGameMediator {
_communicationChannels.put(playerName, participantCommunicationChannel); _communicationChannels.put(playerName, participantCommunicationChannel);
_lotroGame.addGameStateListener(playerName, participantCommunicationChannel); _lotroGame.addGameStateListener(playerName, participantCommunicationChannel);
_chatRoom.joinChatRoom(playerName, participantCommunicationChannel);
visitor.visitChannelNumber(number); visitor.visitChannelNumber(number);

View File

@@ -142,6 +142,26 @@ public class GameResource extends AbstractResource {
gameMediator.cancel(resourceOwner); 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}") @Path("/{gameId}")
@POST @POST
@Produces(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML)
@@ -174,7 +194,7 @@ public class GameResource extends AbstractResource {
// Use long polling // Use long polling
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
while (System.currentTimeMillis()< start+_longPollingLength && !gameMediator.hasAnyNewMessages(resourceOwner, channelNumber)) { while (System.currentTimeMillis() < start + _longPollingLength && !gameMediator.hasAnyNewMessages(resourceOwner, channelNumber)) {
try { try {
Thread.sleep(_longPollingInterval); Thread.sleep(_longPollingInterval);
} catch (InterruptedException exp) { } catch (InterruptedException exp) {

View File

@@ -21,8 +21,9 @@ var ChatBoxUI = Class.extend({
lockChat:false, lockChat:false,
stopUpdates: 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; var that = this;
this.hiddenClasses = new Array(); this.hiddenClasses = new Array();
this.playerListener = playerListener; this.playerListener = playerListener;
@@ -40,37 +41,37 @@ var ChatBoxUI = Class.extend({
if (showHideSystemButton) { if (showHideSystemButton) {
this.hideSystemButton = $("<button id='showSystemMessages'>Toggle system messages</button>").button( this.hideSystemButton = $("<button id='showSystemMessages'>Toggle system messages</button>").button(
{icons:{ {icons:{
primary:"ui-icon-zoomin" primary:"ui-icon-zoomin"
}, text:false}); }, text:false});
this.hideSystemButton.click( this.hideSystemButton.click(
function () { function () {
if (that.isShowingMessageClass("systemMessage")) { if (that.isShowingMessageClass("systemMessage")) {
$('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomin'}); $('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomin'});
that.hideMessageClass("systemMessage"); that.hideMessageClass("systemMessage");
} else { } else {
$('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomout'}); $('#showSystemMessages').button("option", "icons", {primary:'ui-icon-zoomout'});
that.showMessageClass("systemMessage"); that.showMessageClass("systemMessage");
} }
}); });
this.hideMessageClass("systemMessage"); this.hideMessageClass("systemMessage");
} }
if (showLockButton) { if (showLockButton) {
this.lockButton = $("<button id='lockChatButton'>Toggle lock chat</button>").button( this.lockButton = $("<button id='lockChatButton'>Toggle lock chat</button>").button(
{icons:{ {icons:{
primary:"ui-icon-locked" primary:"ui-icon-locked"
}, text:false}); }, text:false});
this.lockButton.click( this.lockButton.click(
function () { function () {
if (that.lockChat) { if (that.lockChat) {
$('#lockChatButton').button("option", "icons", {primary:'ui-icon-locked'}); $('#lockChatButton').button("option", "icons", {primary:'ui-icon-locked'});
that.lockChat = false; that.lockChat = false;
} else { } else {
$('#lockChatButton').button("option", "icons", {primary:'ui-icon-unlocked'}); $('#lockChatButton').button("option", "icons", {primary:'ui-icon-unlocked'});
that.lockChat = true; that.lockChat = true;
} }
}); });
} }
if (showList) { if (showList) {
@@ -83,10 +84,12 @@ var ChatBoxUI = Class.extend({
this.div.append(this.lockButton); this.div.append(this.lockButton);
this.div.append(this.chatTalkDiv); this.div.append(this.chatTalkDiv);
this.communication.startChat(this.name, if (startChat) {
this.communication.startChat(this.name,
function (xml) { function (xml) {
that.processMessages(xml, true); that.processMessages(xml, true);
}, this.chatErrorMap()); }, this.chatErrorMap());
}
this.chatTalkDiv.bind("keypress", function (e) { this.chatTalkDiv.bind("keypress", function (e) {
var code = (e.keyCode ? e.keyCode : e.which); 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("<div class='timestamp'>[" + dateStr + "]</div> <b>" + from + ":</b> " + text, msgClass);
} else {
this.appendMessage("<b>" + from + ":</b> " + text, msgClass);
}
},
appendMessage:function (message, msgClass) { appendMessage:function (message, msgClass) {
if (msgClass == undefined) if (msgClass == undefined)
msgClass = "chatMessage"; msgClass = "chatMessage";
@@ -187,16 +203,7 @@ var ChatBoxUI = Class.extend({
var from = message.getAttribute("from"); var from = message.getAttribute("from");
var text = message.childNodes[0].nodeValue; var text = message.childNodes[0].nodeValue;
var msgClass = "chatMessage"; this.appendChatMessage(from, message.getAttribute("date"), text);
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("<div class='timestamp'>[" + dateStr + "]</div> <b>" + from + ":</b> " + text, msgClass);
} else {
this.appendMessage("<b>" + from + ":</b> " + text, msgClass);
}
} }
var users = root.getElementsByTagName("user"); var users = root.getElementsByTagName("user");
@@ -239,10 +246,14 @@ var ChatBoxUI = Class.extend({
}, },
sendMessage:function (message) { sendMessage:function (message) {
var that = this; if (this.sendMessageFunc != null) {
this.communication.sendChatMessage(this.name, message, function(xml) { this.sendMessageFunc(message);
that.processMessages(xml, false); } else {
}, this.chatErrorMap()); var that = this;
this.communication.sendChatMessage(this.name, message, function(xml) {
that.processMessages(xml, false);
}, this.chatErrorMap());
}
}, },
chatMalfunction: function() { chatMalfunction: function() {

View File

@@ -208,6 +208,20 @@ var GempLotrCommunication = Class.extend({
dataType:"xml" 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) { getGameCardModifiers:function (cardId, callback, errorMap) {
$.ajax({ $.ajax({
type:"GET", type:"GET",

View File

@@ -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) { warning:function (element, animate) {
var that = this; var that = this;
$("#main").queue( $("#main").queue(

View File

@@ -474,7 +474,11 @@ var GempLotrGameUI = Class.extend({
}; };
var chatRoomName = (this.replayMode ? null : ("Game" + getUrlParam("gameId"))); 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; this.chatBox.chatUpdateInterval = 3000;
if (!this.spectatorMode && !this.replayMode) { if (!this.spectatorMode && !this.replayMode) {
@@ -1053,6 +1057,8 @@ var GempLotrGameUI = Class.extend({
this.animations.cardActivated(gameEvent, animate); this.animations.cardActivated(gameEvent, animate);
} else if (eventType == "D") { } else if (eventType == "D") {
this.animations.processDecision(gameEvent, animate); this.animations.processDecision(gameEvent, animate);
} else if (eventType == "CH") {
this.animations.chatMessage(gameEvent, animate);
} }
}, },