Adding chat to the server.

This commit is contained in:
marcins78@gmail.com
2011-09-12 15:18:45 +00:00
parent d39e7c81dd
commit 95fa5a3c3f
9 changed files with 280 additions and 12 deletions

View File

@@ -11,13 +11,14 @@ import java.util.List;
public class GameEvent {
public enum Type {
PARTICIPANT, GAME_PHASE_CHANGE, TURN_CHANGE, PLAYER_POSITION, TWILIGHT_POOL,
PUT_CARD_IN_PLAY, MOVE_CARD_IN_PLAY, REMOVE_CARD_FROM_PLAY, ATTACH_CARD,
PUT_CARD_IN_PLAY, MOVE_CARD_IN_PLAY, REMOVE_CARD_FROM_PLAY,
ADD_ASSIGNMENT, REMOVE_ASSIGNMENT,
START_SKIRMISH, END_SKIRMISH,
ADD_TOKENS, REMOVE_TOKENS
ADD_TOKENS, REMOVE_TOKENS,
MESSAGE
}
private String _warning;
private String _message;
private Type _type;
private Zone _zone;
private String _participantId;
@@ -66,6 +67,15 @@ public class GameEvent {
return this;
}
public String getMessage() {
return _message;
}
public GameEvent message(String message) {
_message = message;
return this;
}
public Integer getCount() {
return _count;
}
@@ -84,15 +94,6 @@ public class GameEvent {
return this;
}
public String getWarning() {
return _warning;
}
public GameEvent warning(String warning) {
_warning = warning;
return this;
}
public String getParticipantId() {
return _participantId;
}

View File

@@ -0,0 +1,22 @@
package com.gempukku.lotro;
import com.gempukku.lotro.chat.ChatMessage;
import com.gempukku.lotro.chat.ChatRoomListener;
import java.util.LinkedList;
import java.util.List;
public class GatheringChatRoomListener implements ChatRoomListener {
private List<ChatMessage> _messages = new LinkedList<ChatMessage>();
@Override
public void messageReceived(ChatMessage message) {
_messages.add(message);
}
public List<ChatMessage> consumeMessages() {
List<ChatMessage> messages = _messages;
_messages = new LinkedList<ChatMessage>();
return messages;
}
}

View File

@@ -98,6 +98,10 @@ public class GatheringParticipantCommunicationChannel implements GameStateListen
_events.add(new GameEvent(REMOVE_TOKENS).card(card).token(token).count(count));
}
public void sendMessage(String message) {
_events.add(new GameEvent(MESSAGE).message(message));
}
public List<GameEvent> consumeGameEvents() {
List<GameEvent> result = _events;
_events = new LinkedList<GameEvent>();

View File

@@ -0,0 +1,27 @@
package com.gempukku.lotro.chat;
import java.util.Date;
public class ChatMessage {
private Date _when;
private String _from;
private String _message;
public ChatMessage(Date when, String from, String message) {
_when = when;
_from = from;
_message = message;
}
public String getFrom() {
return _from;
}
public String getMessage() {
return _message;
}
public Date getWhen() {
return _when;
}
}

View File

@@ -0,0 +1,37 @@
package com.gempukku.lotro.chat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
public class ChatRoom {
private int _maxMessageCount = 10;
private LinkedList<ChatMessage> _lastMessages = new LinkedList<ChatMessage>();
private Map<String, ChatRoomListener> _chatRoomListeners = new HashMap<String, ChatRoomListener>();
public void postMessage(String from, String message) {
ChatMessage chatMessage = new ChatMessage(new Date(), from, message);
_lastMessages.add(chatMessage);
shrinkLastMessages();
for (Map.Entry<String, ChatRoomListener> listeners : _chatRoomListeners.entrySet())
if (!listeners.getKey().equals(from))
listeners.getValue().messageReceived(chatMessage);
}
public void joinChatRoom(String playerId, ChatRoomListener listener) {
_chatRoomListeners.put(playerId, listener);
for (ChatMessage lastMessage : _lastMessages)
listener.messageReceived(lastMessage);
}
public void partChatRoom(String playerId) {
_chatRoomListeners.remove(playerId);
}
private void shrinkLastMessages() {
while (_lastMessages.size() > _maxMessageCount) {
_lastMessages.removeFirst();
}
}
}

View File

@@ -0,0 +1,5 @@
package com.gempukku.lotro.chat;
public interface ChatRoomListener {
public void messageReceived(ChatMessage message);
}

View File

@@ -0,0 +1,36 @@
package com.gempukku.lotro.chat;
import com.gempukku.lotro.GatheringChatRoomListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChatRoomMediator {
private ChatRoom _chatRoom = new ChatRoom();
private Map<String, GatheringChatRoomListener> _listeners = new HashMap<String, GatheringChatRoomListener>();
public synchronized List<ChatMessage> joinUser(String playerId) {
GatheringChatRoomListener value = new GatheringChatRoomListener();
_listeners.put(playerId, value);
_chatRoom.joinChatRoom(playerId, value);
return value.consumeMessages();
}
public synchronized List<ChatMessage> getPendingMessages(String playerId) {
GatheringChatRoomListener gatheringChatRoomListener = _listeners.get(playerId);
if (gatheringChatRoomListener == null)
return null;
return gatheringChatRoomListener.consumeMessages();
}
public synchronized void partUser(String playerId) {
_chatRoom.partChatRoom(playerId);
_listeners.remove(playerId);
}
public synchronized void sendMessage(String playerId, String message) {
_chatRoom.postMessage(playerId, message);
}
}

View File

@@ -0,0 +1,61 @@
package com.gempukku.lotro.chat;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ChatServer {
private Map<String, ChatRoomMediator> _chatRooms = new ConcurrentHashMap<String, ChatRoomMediator>();
private boolean _started;
private CleaningTask _cleaningTask;
public void createChatRoom(String name) {
_chatRooms.put(name, new ChatRoomMediator());
}
public ChatRoomMediator getChatRoom(String name) {
return _chatRooms.get(name);
}
public void destroyChatRoom(String name) {
_chatRooms.remove(name);
}
public synchronized void startServer() {
if (!_started) {
_cleaningTask = new CleaningTask();
new Thread(_cleaningTask).start();
_started = true;
}
}
public synchronized void stopServer() {
if (_started) {
_cleaningTask.stop();
_started = false;
}
}
private void cleanup() {
// TODO cleanup server
}
private class CleaningTask implements Runnable {
private boolean _running = true;
public void run() {
while (_running) {
cleanup();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// Ignore
}
}
}
public void stop() {
_running = false;
}
}
}

View File

@@ -4,6 +4,9 @@ import com.gempukku.lotro.GameEvent;
import com.gempukku.lotro.LotroGameMediator;
import com.gempukku.lotro.LotroGameParticipant;
import com.gempukku.lotro.LotroServer;
import com.gempukku.lotro.chat.ChatMessage;
import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.db.DeckDAO;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.db.vo.Deck;
@@ -27,6 +30,7 @@ import javax.ws.rs.core.Response;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.util.List;
import java.util.Map;
@Singleton
@@ -35,6 +39,7 @@ public class ServerResource {
private static final Logger _logger = Logger.getLogger(ServerResource.class);
private LotroServer _lotroServer;
private ChatServer _chatServer;
public ServerResource() {
_logger.debug("starting resource");
@@ -42,6 +47,10 @@ public class ServerResource {
try {
_lotroServer = new LotroServer();
_lotroServer.startServer();
_chatServer = new ChatServer();
_chatServer.startServer();
_chatServer.createChatRoom("default");
} catch (RuntimeException exp) {
_logger.error("Error while creating resource", exp);
exp.printStackTrace();
@@ -316,6 +325,72 @@ public class ServerResource {
return doc;
}
@Path("/chat/{room}")
@GET
@Produces(MediaType.APPLICATION_XML)
public Document getMessages(
@PathParam("room") String room,
@QueryParam("participantId") String participantId) throws ParserConfigurationException {
ChatRoomMediator chatRoom = _chatServer.getChatRoom(room);
if (chatRoom == null)
sendError(Response.Status.NOT_FOUND);
List<ChatMessage> chatMessages = chatRoom.joinUser(participantId);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.newDocument();
Element chatElem = doc.createElement("chat");
chatElem.setAttribute("roomName", room);
doc.appendChild(chatElem);
for (ChatMessage chatMessage : chatMessages) {
Element message = doc.createElement("message");
message.setAttribute("from", chatMessage.getFrom());
message.setAttribute("date", String.valueOf(chatMessage.getWhen().getTime()));
message.appendChild(doc.createTextNode(chatMessage.getMessage()));
chatElem.appendChild(message);
}
return doc;
}
@Path("/chat/{room}")
@POST
@Produces(MediaType.APPLICATION_XML)
public Document postMessage(
@PathParam("room") String room,
@FormParam("participantId") String participantId,
@FormParam("message") String message) throws ParserConfigurationException {
ChatRoomMediator chatRoom = _chatServer.getChatRoom(room);
if (chatRoom == null)
sendError(Response.Status.NOT_FOUND);
chatRoom.sendMessage(participantId, message);
List<ChatMessage> chatMessages = chatRoom.getPendingMessages(participantId);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.newDocument();
Element chatElem = doc.createElement("chat");
chatElem.setAttribute("roomName", room);
doc.appendChild(chatElem);
for (ChatMessage chatMessage : chatMessages) {
Element messageElem = doc.createElement("message");
messageElem.setAttribute("from", chatMessage.getFrom());
messageElem.setAttribute("date", String.valueOf(chatMessage.getWhen().getTime()));
messageElem.appendChild(doc.createTextNode(chatMessage.getMessage()));
chatElem.appendChild(messageElem);
}
return doc;
}
private class SerializationVisitor implements ParticipantCommunicationVisitor {
private Document _doc;
private Element _element;