diff --git a/Mage.Client/sounds/OnPlayerWhispered.wav b/Mage.Client/sounds/OnPlayerWhispered.wav new file mode 100644 index 0000000000..ad26c3a9d4 Binary files /dev/null and b/Mage.Client/sounds/OnPlayerWhispered.wav differ diff --git a/Mage.Client/src/main/java/mage/client/chat/ChatPanel.java b/Mage.Client/src/main/java/mage/client/chat/ChatPanel.java index b952114ac7..99b696adcd 100644 --- a/Mage.Client/src/main/java/mage/client/chat/ChatPanel.java +++ b/Mage.Client/src/main/java/mage/client/chat/ChatPanel.java @@ -1,56 +1,58 @@ /* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ /* * ChatPanel.java * * Created on 15-Dec-2009, 11:04:31 PM */ - package mage.client.chat; import java.awt.Color; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.UUID; +import javax.print.attribute.standard.MediaSize; import javax.swing.JTextField; import javax.swing.table.AbstractTableModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import mage.client.MageFrame; +import mage.remote.MageRemoteException; import mage.remote.Session; import mage.view.ChatMessage.MessageColor; +import mage.view.ChatMessage.MessageType; +import mage.view.UsersView; /** * @@ -60,51 +62,52 @@ public class ChatPanel extends javax.swing.JPanel { private UUID chatId; private Session session; - private List players = new ArrayList(); private final TableModel tableModel; - /** * Chat message color for opponents. */ - private static final Color OPPONENT_COLOR = new Color(0, 230, 64); - + private static final Color OPPONENT_COLOR = new Color(238, 230, 133); /** * Chat message color for client player. */ private static final Color MY_COLOR = new Color(0, 230, 64); - /** * Chat message color for timestamps. */ private static final Color TIMESTAMP_COLOR = new Color(255, 255, 0, 120); - /** * Chat message color for messages. */ private static final Color MESSAGE_COLOR = Color.white; - /** - * This will be a chat that will be connected to {this} and will handle redirected messages; - * Mostly used to redirect user messages to another window. + * Chat message color for personal infos. + */ + private static final Color USER_INFO_COLOR = Color.YELLOW; + /** + * Chat message color for status infos. + */ + private static final Color STATUS_COLOR = Color.CYAN; + /** + * This will be a chat that will be connected to {this} and will handle + * redirected messages; Mostly used to redirect user messages to another + * window. */ private ChatPanel connectedChat; - /** - * Parent chat this chat connected to. - * Used to send messages using parent chat as it is the only one connected to server. + * Parent chat this chat connected to. Used to send messages using parent + * chat as it is the only one connected to server. */ private ChatPanel parentChatRef; - /** * Selected extended view mode. */ private VIEW_MODE extendedViewMode = VIEW_MODE.NONE; public enum VIEW_MODE { + NONE, GAME, CHAT } - /** * Controls the output start messages as the chat panel is created * @@ -112,11 +115,10 @@ public class ChatPanel extends javax.swing.JPanel { private ChatType chatType = ChatType.DEFAULT; public enum ChatType { + DEFAULT, GAME, TABLES, TOURNAMENT } - private boolean startMessageDone = false; - /** * Maps message colors to {@link Color}. */ @@ -128,9 +130,12 @@ public class ChatPanel extends javax.swing.JPanel { colorMap.put(MessageColor.ORANGE, Color.orange); colorMap.put(MessageColor.BLUE, Color.blue); colorMap.put(MessageColor.RED, Color.red); + colorMap.put(MessageColor.YELLOW, Color.YELLOW); } - /** Creates new form ChatPanel */ + /** + * Creates new form ChatPanel + */ public ChatPanel() { this(false); } @@ -138,7 +143,9 @@ public class ChatPanel extends javax.swing.JPanel { /** * @param addPlayersTab if true, adds chat/players tabs */ - /** Creates new form ChatPanel */ + /** + * Creates new form ChatPanel + */ public ChatPanel(boolean addPlayersTab) { tableModel = new TableModel(); initComponents(); @@ -174,7 +181,6 @@ public class ChatPanel extends javax.swing.JPanel { this.startMessageDone = startMessageDone; } - public void connect(UUID chatId) { session = MageFrame.getSession(); this.chatId = chatId; @@ -190,38 +196,50 @@ public class ChatPanel extends javax.swing.JPanel { } /** - * Display message in the chat. - * Use different colors for timestamp, username and message. + * Display message in the chat. Use different colors for timestamp, username + * and message. * * @param username message sender * @param message message itself * @param time timestamp * @param color Preferred color. Not used. */ - public void receiveMessage(String username, String message, String time, MessageColor color) { - if (extendedViewMode.equals(VIEW_MODE.GAME)) { + public void receiveMessage(String username, String message, String time, MessageType messageType, MessageColor color) { + if (time != null) { this.txtConversation.append(TIMESTAMP_COLOR, time + " "); - Color textColor = MESSAGE_COLOR; - if (color.equals(MessageColor.ORANGE)) { - textColor = Color.ORANGE; - } - this.txtConversation.append(textColor, (username.isEmpty() ? "" : username + ":") + message + "\n"); - } else { - this.txtConversation.append(TIMESTAMP_COLOR, time + " "); - Color userColor; - Color textColor = MESSAGE_COLOR; - if (parentChatRef != null) { - userColor = parentChatRef.session.getUserName().equals(username) ? MY_COLOR : OPPONENT_COLOR; - } else { - userColor = session.getUserName().equals(username) ? MY_COLOR : OPPONENT_COLOR; - if (color.equals(MessageColor.ORANGE)) { - userColor = Color.ORANGE; - textColor = userColor; - } - } - this.txtConversation.append(userColor, username + ": "); - this.txtConversation.append(textColor, message + "\n"); } + Color userColor; + Color textColor; + String userSeparator = " "; + switch (messageType) { + case STATUS: // a message to all chat user + textColor = STATUS_COLOR; + userColor = STATUS_COLOR; + break; + case USER_INFO: // a personal message + textColor = USER_INFO_COLOR; + userColor = USER_INFO_COLOR; + break; + default: + if (parentChatRef != null) { + userColor = parentChatRef.session.getUserName().equals(username) ? MY_COLOR : OPPONENT_COLOR; + } else { + userColor = session.getUserName().equals(username) ? MY_COLOR : OPPONENT_COLOR; + } + textColor = MESSAGE_COLOR; + userSeparator = ": "; + } + if (color.equals(MessageColor.ORANGE)) { + textColor = Color.ORANGE; + } + if (color.equals(MessageColor.YELLOW)) { + textColor = Color.YELLOW; + } + if (username != null && !username.isEmpty()) { + this.txtConversation.append(userColor, username); + this.txtConversation.append(userColor, userSeparator); + } + this.txtConversation.append(textColor, message + "\n"); } public String getText() { @@ -258,16 +276,16 @@ public class ChatPanel extends javax.swing.JPanel { public void useExtendedView(VIEW_MODE extendedViewMode) { this.extendedViewMode = extendedViewMode; - this.txtConversation.setExtBackgroundColor(new Color(0,0,0,100)); - this.txtConversation.setBackground(new Color(0,0,0,0)); - this.txtConversation.setForeground(new Color(255,255,255)); + this.txtConversation.setExtBackgroundColor(new Color(0, 0, 0, 100)); + this.txtConversation.setBackground(new Color(0, 0, 0, 0)); + this.txtConversation.setForeground(new Color(255, 255, 255)); this.jScrollPaneTxt.setOpaque(false); this.jScrollPaneTxt.getViewport().setOpaque(false); } public void setSplitDividerLocation(int location) { if (jSplitPane1 != null) { - jSplitPane1.setDividerLocation(location); + jSplitPane1.setDividerLocation(location); } } @@ -278,66 +296,74 @@ public class ChatPanel extends javax.swing.JPanel { return this.jSplitPane1.getDividerLocation(); } -class TableModel extends AbstractTableModel { - private String[] columnNames = new String[]{"Players"}; - private List players = new ArrayList(0); + class TableModel extends AbstractTableModel { - public void loadData(List players) { - this.players = players; - JTableHeader th = jTablePlayers.getTableHeader(); - TableColumnModel tcm = th.getColumnModel(); - TableColumn tc = tcm.getColumn(0); - tc.setHeaderValue(new StringBuilder("Players").append(" (").append(this.players.size()).append(")").toString()); - th.repaint(); - this.fireTableDataChanged(); - } + private String[] columnNames = new String[]{"Players", "Info", "Games"}; + private UsersView[] players = new UsersView[0]; - @Override - public int getRowCount() { - return players.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int arg0, int arg1) { - return players.get(arg0); - } - - @Override - public String getColumnName(int columnIndex) { - String colName = ""; - - if (columnIndex <= getColumnCount()) { - colName = columnNames[columnIndex]; + public void loadData(Collection players) throws MageRemoteException { + this.players = players.toArray(new UsersView[0]); + JTableHeader th = jTablePlayers.getTableHeader(); + TableColumnModel tcm = th.getColumnModel(); + TableColumn tc = tcm.getColumn(0); + tc.setHeaderValue(new StringBuilder("Players").append(" (").append(this.players.length).append(")").toString()); + th.repaint(); + this.fireTableDataChanged(); } - return colName; - } + @Override + public int getRowCount() { + return players.length; + } - @Override - public Class getColumnClass(int columnIndex){ - return String.class; - } + @Override + public int getColumnCount() { + return columnNames.length; + } - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return false; - } + @Override + public Object getValueAt(int arg0, int arg1) { + switch (arg1) { + case 0: + return players[arg0].getUserName(); + case 1: + return players[arg0].getInfoState(); + case 2: + return players[arg0].getInfoGames(); + } + return ""; + } -} + @Override + public String getColumnName(int columnIndex) { + String colName = ""; + + if (columnIndex <= getColumnCount()) { + colName = columnNames[columnIndex]; + } + + return colName; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + } public void clear() { this.txtConversation.setText(""); } - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents @@ -395,17 +421,15 @@ class TableModel extends AbstractTableModel { javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE) - .addComponent(jScrollPaneTxt, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE) - ); + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE) + .addComponent(jScrollPaneTxt, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)); layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jScrollPaneTxt, javax.swing.GroupLayout.DEFAULT_SIZE, 294, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); + .addComponent(txtMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))); jTablePlayers = null; jScrollPanePlayers = null; } @@ -422,35 +446,42 @@ class TableModel extends AbstractTableModel { } }//GEN-LAST:event_txtMessageKeyTyped - public void setPlayers(Collection players) { - if (players != null) { - boolean update; - int size = players.size(); - List list = new ArrayList(players); - Collections.sort(list, String.CASE_INSENSITIVE_ORDER); - if (size != this.players.size()) { - update = true; - } else { - update = false; - for (int i = 0; i < size; i++) { - if (!list.get(i).equals(this.players.get(i))) { - update = true; - break; - } - } - } - if (update) { - synchronized (tableModel) { - this.players = list; - tableModel.loadData(this.players); - } - } - - } else { + // public void setPlayers(Collection players) { + public void setPlayers(List> view) { + try { + // TODO: sort by user name + tableModel.loadData(view.get(0)); + } catch (Exception ex) { this.players.clear(); } - } +// if (players != null) { +// boolean update; +// int size = players.size(); +// List list = new ArrayList(players); +// Collections.sort(list, String.CASE_INSENSITIVE_ORDER); +// if (size != this.players.size()) { +// update = true; +// } else { +// update = false; +// for (int i = 0; i < size; i++) { +// if (!list.get(i).equals(this.players.get(i))) { +// update = true; +// break; +// } +// } +// } +// if (update) { +// synchronized (tableModel) { +// this.players = list; +// tableModel.loadData(this.players); +// } +// } +// +// } else { +// this.players.clear(); +// } + } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane jScrollPanePlayers; private javax.swing.JScrollPane jScrollPaneTxt; @@ -459,5 +490,4 @@ class TableModel extends AbstractTableModel { private mage.client.components.ColorPane txtConversation; private javax.swing.JTextField txtMessage; // End of variables declaration//GEN-END:variables - } diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java index e96569dd15..2f39f10e58 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -1,34 +1,32 @@ /* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.client.remote; -import java.util.LinkedList; import java.util.List; import java.util.UUID; import javax.swing.JOptionPane; @@ -49,6 +47,7 @@ import mage.interfaces.callback.ClientCallback; import mage.utils.CompressUtil; import mage.view.AbilityPickerView; import mage.view.ChatMessage; +import mage.view.ChatMessage.MessageType; import mage.view.DeckView; import mage.view.DraftClientMessage; import mage.view.DraftView; @@ -58,7 +57,6 @@ import mage.view.GameView; import mage.view.TableClientMessage; import org.apache.log4j.Logger; - /** * * @author BetaSteward_at_googlemail.com @@ -66,7 +64,6 @@ import org.apache.log4j.Logger; public class CallbackClientImpl implements CallbackClient { private static final Logger logger = Logger.getLogger(CallbackClientImpl.class); - private UUID clientId; private MageFrame frame; private int messageId = 0; @@ -92,25 +89,19 @@ public class CallbackClientImpl implements CallbackClient { TableClientMessage message = (TableClientMessage) callback.getData(); GameManager.getInstance().setCurrentPlayerUUID(message.getPlayerId()); gameStarted(message.getGameId(), message.getPlayerId()); - } - else if(callback.getMethod().equals("startTournament")) { + } else if (callback.getMethod().equals("startTournament")) { TableClientMessage message = (TableClientMessage) callback.getData(); tournamentStarted(message.getGameId(), message.getPlayerId()); - } - else if(callback.getMethod().equals("startDraft")) { + } else if (callback.getMethod().equals("startDraft")) { TableClientMessage message = (TableClientMessage) callback.getData(); draftStarted(message.getGameId(), message.getPlayerId()); - } - else if (callback.getMethod().equals("replayGame")) { + } else if (callback.getMethod().equals("replayGame")) { replayGame(callback.getObjectId()); - } - else if (callback.getMethod().equals("showTournament")) { + } else if (callback.getMethod().equals("showTournament")) { showTournament((UUID) callback.getObjectId()); - } - else if (callback.getMethod().equals("watchGame")) { + } else if (callback.getMethod().equals("watchGame")) { watchGame((UUID) callback.getObjectId()); - } - else if (callback.getMethod().equals("chatMessage")) { + } else if (callback.getMethod().equals("chatMessage")) { ChatMessage message = (ChatMessage) callback.getData(); ChatPanel panel = MageFrame.getChat(callback.getObjectId()); if (panel != null) { @@ -120,22 +111,25 @@ public class CallbackClientImpl implements CallbackClient { case PlayerLeft: AudioManager.playPlayerLeft(); break; - case PlayerSubmittedDeck: + case PlayerSubmittedDeck: AudioManager.playPlayerSubmittedDeck(); break; + case PlayerWhispered: + AudioManager.playPlayerWhispered(); + break; } } - // send start message to chat if needed + // send start message to chat if not done yet if (!panel.isStartMessageDone()) { createChatStartMessage(panel); } - // send the message itself - if (message.isUserMessage() && panel.getConnectedChat() != null) { - panel.getConnectedChat().receiveMessage(message.getUsername(), message.getMessage(), message.getTime(), ChatMessage.MessageColor.BLACK); + // send the message to subchat if exists and it's not a game message + if (!message.getMessageType().equals(MessageType.GAME) && panel.getConnectedChat() != null) { + panel.getConnectedChat().receiveMessage(message.getUsername(), message.getMessage(), message.getTime(), message.getMessageType(), ChatMessage.MessageColor.BLACK); } else { - panel.receiveMessage(message.getUsername(), message.getMessage(), message.getTime(), message.getColor()); + panel.receiveMessage(message.getUsername(), message.getMessage(), message.getTime(), message.getMessageType(), message.getColor()); } - + } } else if (callback.getMethod().equals("serverMessage")) { if (callback.getData() != null) { @@ -149,119 +143,100 @@ public class CallbackClientImpl implements CallbackClient { } else if (callback.getMethod().equals("joinedTable")) { TableClientMessage message = (TableClientMessage) callback.getData(); joinedTable(message.getRoomId(), message.getTableId(), message.getFlag()); - } - else if (callback.getMethod().equals("replayInit")) { + } else if (callback.getMethod().equals("replayInit")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.init((GameView) callback.getData()); } - } - else if (callback.getMethod().equals("replayDone")) { + } else if (callback.getMethod().equals("replayDone")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.endMessage((String) callback.getData(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("replayUpdate")) { + } else if (callback.getMethod().equals("replayUpdate")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.updateGame((GameView) callback.getData()); } - } - else if (callback.getMethod().equals("gameInit")) { + } else if (callback.getMethod().equals("gameInit")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.init((GameView) callback.getData()); } - } - else if (callback.getMethod().equals("gameOver")) { + } else if (callback.getMethod().equals("gameOver")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.endMessage((String) callback.getData(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("gameError")) { + } else if (callback.getMethod().equals("gameError")) { frame.showErrorDialog("Game Error", (String) callback.getData()); - } - else if (callback.getMethod().equals("gameAsk")) { + } else if (callback.getMethod().equals("gameAsk")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.ask(message.getMessage(), message.getGameView(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("gameTarget")) { + } else if (callback.getMethod().equals("gameTarget")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.pickTarget(message.getMessage(), message.getCardsView(), message.getGameView(), message.getTargets(), message.isFlag(), message.getOptions(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("gameSelect")) { + } else if (callback.getMethod().equals("gameSelect")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.select(message.getMessage(), message.getGameView(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("gameChooseAbility")) { + } else if (callback.getMethod().equals("gameChooseAbility")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.pickAbility((AbilityPickerView) callback.getData()); } - } - else if (callback.getMethod().equals("gameChoosePile")) { + } else if (callback.getMethod().equals("gameChoosePile")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.pickPile(message.getMessage(), message.getPile1(), message.getPile2()); } - } - else if (callback.getMethod().equals("gameChoose")) { + } else if (callback.getMethod().equals("gameChoose")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.getChoice(message.getMessage(), message.getStrings()); } - } - else if (callback.getMethod().equals("gamePlayMana")) { + } else if (callback.getMethod().equals("gamePlayMana")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.playMana(message.getMessage(), message.getGameView(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("gamePlayXMana")) { + } else if (callback.getMethod().equals("gamePlayXMana")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.playXMana(message.getMessage(), message.getGameView(), callback.getMessageId()); } - } - else if (callback.getMethod().equals("gameSelectAmount")) { + } else if (callback.getMethod().equals("gameSelectAmount")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.getAmount(message.getMin(), message.getMax(), message.getMessage()); } - } - else if (callback.getMethod().equals("gameUpdate")) { + } else if (callback.getMethod().equals("gameUpdate")) { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { panel.updateGame((GameView) callback.getData()); } - } - else if (callback.getMethod().equals("endGameInfo")) { + } else if (callback.getMethod().equals("endGameInfo")) { MageFrame.getInstance().showGameEndDialog((GameEndView) callback.getData()); - } - else if (callback.getMethod().equals("showUserMessage")) { + } else if (callback.getMethod().equals("showUserMessage")) { List messageData = (List) callback.getData(); if (messageData.size() == 2) { JOptionPane.showMessageDialog(null, messageData.get(1), messageData.get(0), JOptionPane.WARNING_MESSAGE); } - } - else if (callback.getMethod().equals("gameInform")) { + } else if (callback.getMethod().equals("gameInform")) { if (callback.getMessageId() > messageId) { GameClientMessage message = (GameClientMessage) callback.getData(); @@ -269,76 +244,62 @@ public class CallbackClientImpl implements CallbackClient { if (panel != null) { panel.inform(message.getMessage(), message.getGameView(), callback.getMessageId()); } - } - else { + } else { logger.warn("message out of sequence - ignoring"); } - } - else if (callback.getMethod().equals("gameInformPersonal")) { + } else if (callback.getMethod().equals("gameInformPersonal")) { GameClientMessage message = (GameClientMessage) callback.getData(); GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { JOptionPane.showMessageDialog(panel, message.getMessage(), "Game message", JOptionPane.INFORMATION_MESSAGE); } - } - else if (callback.getMethod().equals("sideboard")) { + } else if (callback.getMethod().equals("sideboard")) { TableClientMessage message = (TableClientMessage) callback.getData(); DeckView deckView = message.getDeck(); Deck deck = DeckUtil.construct(deckView); if (message.getFlag()) { construct(deck, message.getTableId(), message.getTime()); - } - else { + } else { sideboard(deck, message.getTableId(), message.getTime()); } - } - else if (callback.getMethod().equals("construct")) { + } else if (callback.getMethod().equals("construct")) { TableClientMessage message = (TableClientMessage) callback.getData(); DeckView deckView = message.getDeck(); Deck deck = DeckUtil.construct(deckView); construct(deck, message.getTableId(), message.getTime()); - } - else if (callback.getMethod().equals("draftOver")) { + } else if (callback.getMethod().equals("draftOver")) { DraftPanel panel = MageFrame.getDraft(callback.getObjectId()); if (panel != null) { panel.hideDraft(); } - } - else if (callback.getMethod().equals("draftPick")) { + } else if (callback.getMethod().equals("draftPick")) { DraftClientMessage message = (DraftClientMessage) callback.getData(); DraftPanel panel = MageFrame.getDraft(callback.getObjectId()); if (panel != null) { panel.loadBooster(message.getDraftPickView()); } - } - else if (callback.getMethod().equals("draftUpdate")) { + } else if (callback.getMethod().equals("draftUpdate")) { DraftPanel panel = MageFrame.getDraft(callback.getObjectId()); if (panel != null) { panel.updateDraft((DraftView) callback.getData()); } - } - else if (callback.getMethod().equals("draftInform")) { + } else if (callback.getMethod().equals("draftInform")) { if (callback.getMessageId() > messageId) { DraftClientMessage message = (DraftClientMessage) callback.getData(); - } - else { + } else { logger.warn("message out of sequence - ignoring"); } - } - else if (callback.getMethod().equals("draftInit")) { + } else if (callback.getMethod().equals("draftInit")) { DraftClientMessage message = (DraftClientMessage) callback.getData(); DraftPanel panel = MageFrame.getDraft(callback.getObjectId()); if (panel != null) { panel.loadBooster(message.getDraftPickView()); } - } - else if (callback.getMethod().equals("tournamentInit")) { - + } else if (callback.getMethod().equals("tournamentInit")) { } messageId = callback.getMessageId(); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } } @@ -353,24 +314,26 @@ public class CallbackClientImpl implements CallbackClient { } switch (usedPanel.getChatType()) { case GAME: - usedPanel.receiveMessage("", "You may use hot keys to play faster: " + "" + - "\nTurn Mousewheel - Show big image of card your mousepointer hovers over" + - "\nF2 - Confirm \"Ok\", \"Yes\" or \"Done\" button" + - "\nF4 - Skip current turn but stop on declare attackers" + - "\nF9 - Skip everything until your next turn" + - "\nF3 - Undo F4/F9", "", ChatMessage.MessageColor.ORANGE); + usedPanel.receiveMessage("", new StringBuilder("You may use hot keys to play faster:") + .append("\nTurn Mousewheel - Show big image of card your mousepointer hovers over") + .append("\nF2 - Confirm \"Ok\", \"Yes\" or \"Done\" button") + .append("\nF4 - Skip current turn but stop on declare attackers/blockers and something on the stack") + .append("\nF9 - Skip everything until your next turn") + .append("\nF3 - Undo F4/F9").toString(), + null, MessageType.USER_INFO, ChatMessage.MessageColor.ORANGE); break; case TOURNAMENT: - usedPanel.receiveMessage("", "On this panel you can see the players, their state and the results of the games of the tournament. Also you can chat with the competitors of the tournament.", "", ChatMessage.MessageColor.ORANGE); + usedPanel.receiveMessage("", new StringBuilder("On this panel you can see the players, their state and the results of the games of the tournament. Also you can chat with the competitors of the tournament.").toString(), + null, MessageType.USER_INFO, ChatMessage.MessageColor.ORANGE); break; case TABLES: - usedPanel.receiveMessage("", - "Download card images by using the \"Images\" menu to the top right ." + - "\nDownload icons and symbols by using the \"Symbols\" menu to the top right.", - "", ChatMessage.MessageColor.ORANGE); + usedPanel.receiveMessage("", new StringBuilder("Download card images by using the \"Images\" menu to the top right .") + .append("\nDownload icons and symbols by using the \"Symbols\" menu to the top right.") + .append("\n\\list - Show a list of available chat commands.").toString(), + null, MessageType.USER_INFO, ChatMessage.MessageColor.ORANGE); break; - } + } } public UUID getId() { @@ -380,18 +343,16 @@ public class CallbackClientImpl implements CallbackClient { private void joinedTable(UUID roomId, UUID tableId, boolean isTournament) { try { frame.showTableWaitingDialog(roomId, tableId, isTournament); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } - } + } protected void gameStarted(final UUID gameId, final UUID playerId) { try { frame.showGame(gameId, playerId); logger.info("Game " + gameId + " started for player " + playerId); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } @@ -404,8 +365,7 @@ public class CallbackClientImpl implements CallbackClient { try { frame.showDraft(draftId); logger.info("Draft " + draftId + " started for player " + playerId); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } } @@ -414,23 +374,21 @@ public class CallbackClientImpl implements CallbackClient { try { frame.showTournament(tournamentId); logger.info("Tournament " + tournamentId + " started for player " + playerId); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } } /** * Shows the tournament info panel for a tournament - * + * * @param tournamentId */ protected void showTournament(UUID tournamentId) { try { frame.showTournament(tournamentId); logger.info("Showing tournament " + tournamentId); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } } @@ -439,17 +397,16 @@ public class CallbackClientImpl implements CallbackClient { try { frame.watchGame(gameId); logger.info("Watching game " + gameId); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } } + protected void replayGame(UUID gameId) { try { frame.replayGame(gameId); logger.info("Replaying game"); - } - catch (Exception ex) { + } catch (Exception ex) { handleException(ex); } } @@ -466,5 +423,4 @@ public class CallbackClientImpl implements CallbackClient { logger.fatal("Client error\n", ex); frame.showError("Error: " + ex.getMessage()); } - } diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.form b/Mage.Client/src/main/java/mage/client/table/TablesPanel.form index 15a2afcdc5..2b595ba00c 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.form +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.form @@ -28,12 +28,12 @@ - + - + @@ -128,7 +128,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index a0643ceda4..f2bd481bbc 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -79,6 +79,7 @@ import mage.remote.MageRemoteException; import mage.remote.Session; import mage.view.MatchView; import mage.view.TableView; +import mage.view.UsersView; import org.apache.log4j.Logger; /** @@ -827,7 +828,7 @@ class UpdateTablesTask extends SwingWorker> { } -class UpdatePlayersTask extends SwingWorker> { +class UpdatePlayersTask extends SwingWorker> { private Session session; private UUID roomId; @@ -851,8 +852,8 @@ class UpdatePlayersTask extends SwingWorker> { } @Override - protected void process(List> players) { - chat.setPlayers(players.get(0)); + protected void process(List> players) { + chat.setPlayers(players); } @Override diff --git a/Mage.Client/src/main/java/mage/client/util/AudioManager.java b/Mage.Client/src/main/java/mage/client/util/AudioManager.java index afa3515182..ad1417e53d 100644 --- a/Mage.Client/src/main/java/mage/client/util/AudioManager.java +++ b/Mage.Client/src/main/java/mage/client/util/AudioManager.java @@ -48,6 +48,7 @@ public class AudioManager { audioManager.playerJoinedTable = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerJoinedTable.wav"); audioManager.playerSubmittedDeck = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerSubmittedDeck.wav"); + audioManager.playerWhispered = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerWhispered.wav"); audioManager.playerLeft = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerLeft.wav"); audioManager.playerWon = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerWon.wav"); audioManager.playerLost = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerLost.wav"); @@ -127,6 +128,10 @@ public class AudioManager { checkAndPlayClip(getManager().playerJoinedTable); } + public static void playPlayerWhispered() { + checkAndPlayClip(getManager().playerWhispered); + } + public static void playPlayerSubmittedDeck() { checkAndPlayClip(getManager().playerSubmittedDeck); } @@ -207,6 +212,7 @@ public class AudioManager { private Clip playerJoinedTable = null; private Clip playerSubmittedDeck = null; + private Clip playerWhispered = null; private Clip playerLeft = null; private Clip playerWon = null; private Clip playerLost = null; diff --git a/Mage.Common/src/mage/interfaces/MageServer.java b/Mage.Common/src/mage/interfaces/MageServer.java index 1eec04c50e..fb36a5d965 100644 --- a/Mage.Common/src/mage/interfaces/MageServer.java +++ b/Mage.Common/src/mage/interfaces/MageServer.java @@ -62,7 +62,7 @@ public interface MageServer { // server state methods ServerState getServerState() throws MageException; - List getConnectedPlayers(UUID roomId) throws MageException; + List getConnectedPlayers(UUID roomId) throws MageException; List getFinishedMatches(UUID roomId) throws MageException; Object getServerMessagesCompressed(String sessionId) throws MageException; // messages of the day diff --git a/Mage.Common/src/mage/remote/interfaces/ServerState.java b/Mage.Common/src/mage/remote/interfaces/ServerState.java index eb82685fa2..06f9ad3825 100644 --- a/Mage.Common/src/mage/remote/interfaces/ServerState.java +++ b/Mage.Common/src/mage/remote/interfaces/ServerState.java @@ -35,6 +35,7 @@ import mage.view.UserView; import java.util.Collection; import java.util.List; import java.util.UUID; +import mage.view.UsersView; /** * @author noxx @@ -45,7 +46,7 @@ public interface ServerState { List getUsers(); - Collection getConnectedPlayers(UUID roomId) throws MageRemoteException; + Collection getConnectedPlayers(UUID roomId) throws MageRemoteException; List getServerMessages(); diff --git a/Mage.Common/src/mage/view/ChatMessage.java b/Mage.Common/src/mage/view/ChatMessage.java index ef6536f500..873ebce28d 100644 --- a/Mage.Common/src/mage/view/ChatMessage.java +++ b/Mage.Common/src/mage/view/ChatMessage.java @@ -42,13 +42,18 @@ public class ChatMessage implements Serializable { private String message; private MessageColor color; private SoundToPlay soundToPlay; + private MessageType messageType; public enum MessageColor { - BLACK, RED, GREEN, BLUE, ORANGE; + BLACK, RED, GREEN, BLUE, ORANGE, YELLOW; + } + + public enum MessageType { + USER_INFO, STATUS, GAME, TALK, WHISPER; } public enum SoundToPlay { - PlayerLeft, PlayerSubmittedDeck; + PlayerLeft, PlayerSubmittedDeck, PlayerWhispered; } public ChatMessage(String username, String message, String time, MessageColor color) { @@ -56,10 +61,15 @@ public class ChatMessage implements Serializable { } public ChatMessage(String username, String message, String time, MessageColor color, SoundToPlay soundToPlay) { + this(username, message, time, color, MessageType.TALK, soundToPlay); + } + + public ChatMessage(String username, String message, String time, MessageColor color, MessageType messageType, SoundToPlay soundToPlay) { this.username = username; this.message = message; this.time = time; this.color = color; + this.messageType = messageType; this.soundToPlay = soundToPlay; } @@ -72,7 +82,7 @@ public class ChatMessage implements Serializable { } public boolean isUserMessage() { - return color != null && color.equals(MessageColor.BLUE); + return color != null && (color.equals(MessageColor.BLUE) || color.equals(MessageColor.YELLOW)); } public boolean isStatusMessage() { @@ -91,4 +101,8 @@ public class ChatMessage implements Serializable { return soundToPlay; } + public MessageType getMessageType() { + return messageType; + } + } diff --git a/Mage.Common/src/mage/view/UsersView.java b/Mage.Common/src/mage/view/UsersView.java new file mode 100644 index 0000000000..ee634c2457 --- /dev/null +++ b/Mage.Common/src/mage/view/UsersView.java @@ -0,0 +1,62 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ +package mage.view; + +import java.io.Serializable; + +/** + * + * @author LevelX2 + */ +public class UsersView implements Serializable { + + private static final long serialVersionUID = 1L; + + private String userName; + private String infoState; + private String infoGames; + + public UsersView(String userName, String infoState, String infoGames) { + this.userName = userName; + this.infoState = infoState; + this.infoGames = infoGames; + } + + public String getUserName() { + return userName; + } + + public String getInfoState() { + return infoState; + } + + public String getInfoGames() { + return infoGames; + } + +} diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index a3eeebcad0..2f10f0a626 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -28,10 +28,11 @@ package mage.server; -import mage.view.ChatMessage.MessageColor; - +import java.util.Locale; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import mage.view.ChatMessage.MessageColor; +import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.SoundToPlay; /** @@ -69,17 +70,69 @@ public class ChatManager { } public void broadcast(UUID chatId, String userName, String message, MessageColor color) { - chatSessions.get(chatId).broadcast(userName, message, color); + this.broadcast(chatId, userName, message, color, true); } public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime) { - chatSessions.get(chatId).broadcast(userName, message, color, withTime); + this.broadcast(chatId, userName, message, color, withTime, MessageType.TALK); } - public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, SoundToPlay soundToPlay) { - chatSessions.get(chatId).broadcast(userName, message, color, withTime, soundToPlay); + public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, MessageType messageType) { + this.broadcast(chatId, userName, message, color, withTime, messageType, null); } + public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) { + if (message.startsWith("\\")) { + User user = UserManager.getInstance().findUser(userName); + if (user != null && performUserCommand(user, message, chatId)) { + return; + } + } + chatSessions.get(chatId).broadcast(userName, message, color, withTime, messageType, soundToPlay); + } + + + private boolean performUserCommand(User user, String message, UUID chatId) { + String command = message.trim().toUpperCase(Locale.ENGLISH); + if (command.equals("\\I") || command.equals("\\INFO")) { + user.setInfo(""); + chatSessions.get(chatId).broadcastInfoToUser(user,message); + return true; + } + if (command.startsWith("\\I ") || command.startsWith("\\INFO ")) { + user.setInfo(message.substring(command.startsWith("\\I ") ? 3 : 6)); + chatSessions.get(chatId).broadcastInfoToUser(user,message); + return true; + } + if (command.startsWith("\\W ") || command.startsWith("\\WHISPER ")) { + String rest = message.substring(command.startsWith("\\W ") ? 3 : 9); + int first = rest.indexOf(" "); + if (first > 1) { + String userToName = rest.substring(0,first); + rest = rest.substring(first + 1).trim(); + User userTo = UserManager.getInstance().findUser(userToName); + if (userTo != null) { + chatSessions.get(chatId).broadcastWhisperToUser(user, userTo, rest); + } else { + message += new StringBuilder("\nUser ").append(userToName).append(" not found").toString(); + chatSessions.get(chatId).broadcastInfoToUser(user,message); + } + return true; + } + } + if (command.equals("\\L") || command.equals("\\LIST")) { + message += new StringBuilder("\nList of commands:") + .append("\n\\info - set a info text to your player") + .append("\n\\list - Show a list of commands") + .append("\n\\whisper - Whiper to a player").toString(); + chatSessions.get(chatId).broadcastInfoToUser(user,message); + return true; + } + return false; + } + + + /** * * use mainly for announcing that a user connection was lost or that a user has reconnected diff --git a/Mage.Server/src/main/java/mage/server/ChatSession.java b/Mage.Server/src/main/java/mage/server/ChatSession.java index 4f92b2bcbf..a07d5de69d 100644 --- a/Mage.Server/src/main/java/mage/server/ChatSession.java +++ b/Mage.Server/src/main/java/mage/server/ChatSession.java @@ -37,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap; import mage.interfaces.callback.ClientCallback; import mage.view.ChatMessage; import mage.view.ChatMessage.MessageColor; +import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.SoundToPlay; import org.apache.log4j.Logger; @@ -47,6 +48,8 @@ import org.apache.log4j.Logger; public class ChatSession { private static final Logger logger = Logger.getLogger(ChatSession.class); + private static final Calendar cal = new GregorianCalendar(); + private ConcurrentHashMap clients = new ConcurrentHashMap(); private UUID chatId; private DateFormat timeFormatter = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT); @@ -60,7 +63,7 @@ public class ChatSession { if (user != null && !clients.containsKey(userId)) { String userName = user.getName(); clients.put(userId, userName); - broadcast(userName, " has joined", MessageColor.BLUE); + broadcast(null, new StringBuilder(userName).append(" has joined").toString(), MessageColor.BLUE, true, MessageType.STATUS); logger.debug(userName + " joined chat " + chatId); } } @@ -80,22 +83,46 @@ public class ChatSession { default: message = " has left chat"; } - broadcast(userName, message, MessageColor.BLUE); + broadcast(null, new StringBuilder(userName).append(message).toString(), MessageColor.BLUE, true, MessageType.STATUS); logger.debug(userName + message + " " + chatId); } } + public boolean broadcastInfoToUser(User toUser, String message) { + if (clients.containsKey(toUser.getId())) { + toUser.fireCallback(new ClientCallback("chatMessage", chatId, new ChatMessage(null, message, timeFormatter.format(cal.getTime()), MessageColor.ORANGE, MessageType.USER_INFO, null))); + return true; + } + return false; + } + + public boolean broadcastWhisperToUser(User fromUser, User toUser, String message) { + if (clients.containsKey(toUser.getId())) { + toUser.fireCallback(new ClientCallback("chatMessage", chatId, + new ChatMessage(new StringBuilder("Whisper from ").append(fromUser.getName()).toString(), message, timeFormatter.format(cal.getTime()), MessageColor.YELLOW, MessageType.WHISPER, SoundToPlay.PlayerWhispered))); + if (clients.containsKey(fromUser.getId())) { + fromUser.fireCallback(new ClientCallback("chatMessage", chatId, + new ChatMessage(new StringBuilder("Whisper to ").append(toUser.getName()).toString(), message, timeFormatter.format(cal.getTime()), MessageColor.YELLOW, MessageType.WHISPER, null))); + return true; + } + } + return false; + } + public void broadcast(String userName, String message, MessageColor color) { - broadcast(userName, message, color, true); + this.broadcast(userName, message, color, true); } public void broadcast(String userName, String message, MessageColor color, boolean withTime) { - broadcast(userName, message, color, withTime, null); + this.broadcast(userName, message, color, withTime, MessageType.TALK); } - public void broadcast(String userName, String message, MessageColor color, boolean withTime, SoundToPlay soundToPlay) { - if (!message.isEmpty()) { - Calendar cal = new GregorianCalendar(); + public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType) { + this.broadcast(userName, message, color, withTime, messageType, null); + } + + public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) { + if (!message.isEmpty()) { final String msg = message; final String time = (withTime ? timeFormatter.format(cal.getTime()):""); final String username = userName; @@ -103,7 +130,7 @@ public class ChatSession { for (UUID userId: clients.keySet()) { User user = UserManager.getInstance().getUser(userId); if (user != null) { - user.fireCallback(new ClientCallback("chatMessage", chatId, new ChatMessage(username, msg, time, color, soundToPlay))); + user.fireCallback(new ClientCallback("chatMessage", chatId, new ChatMessage(username, msg, time, color, messageType, soundToPlay))); } else { kill(userId, User.DisconnectReason.CleaningUp); diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index e4b00b104a..13f101dd75 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -78,6 +78,7 @@ import mage.view.TableView; import mage.view.TournamentView; import mage.view.UserDataView; import mage.view.UserView; +import mage.view.UsersView; import org.apache.log4j.Logger; /** @@ -291,7 +292,7 @@ public class MageServerImpl implements MageServer { @Override //FIXME: why no sessionId here??? - public List getConnectedPlayers(UUID roomId) throws MageException { + public List getConnectedPlayers(UUID roomId) throws MageException { try { GamesRoom room = GamesRoomManager.getInstance().getRoom(roomId); if (room != null) { diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 59b101a7a8..a6e4bd83e8 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -66,6 +66,7 @@ public class User { private String userName; private String sessionId = ""; private String host; + private String info; private Date connectionTime = new Date(); private Date lastActivity = new Date(); private UserState userState; @@ -305,7 +306,7 @@ public class User { return this.userData; } - public String getUserInfo() { + public String getGameInfo() { StringBuilder sb = new StringBuilder(); if (gameSessions.size() > 0) { sb.append("G: ").append(gameSessions.size()); @@ -316,10 +317,14 @@ public class User { } sb.append("T: ").append(tournamentSessions.size()); } - if (sb.length() > 0) { - sb.insert(0, " - ["); - sb.append("]"); - } return sb.toString(); } + + public String getInfo() { + return info; + } + + public void setInfo(String Info) { + this.info = Info; + } } diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 81e8ecedee..6888c760fd 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -76,7 +76,9 @@ import mage.server.util.ThreadExecutor; import mage.utils.timer.PriorityTimer; import mage.view.AbilityPickerView; import mage.view.CardsView; +import mage.view.ChatMessage; import mage.view.ChatMessage.MessageColor; +import mage.view.ChatMessage.MessageType; import mage.view.GameView; import mage.view.PermanentView; import org.apache.log4j.Logger; @@ -133,11 +135,11 @@ public class GameController implements GameCallback { updateGame(); break; case INFO: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK); + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME); logger.debug(game.getId() + " " + event.getMessage()); break; case STATUS: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime()); + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME); logger.debug(game.getId() + " " + event.getMessage()); break; case ERROR: @@ -272,7 +274,7 @@ public class GameController implements GameCallback { gameSession.setUserData(user.getUserData()); user.addGame(playerId, gameSession); logger.debug(new StringBuilder("Player ").append(playerId).append(" has joined game ").append(game.getId()).toString()); - ChatManager.getInstance().broadcast(chatId, "", new StringBuilder(game.getPlayer(playerId).getName()).append(" has joined the game").toString(), MessageColor.BLACK); + ChatManager.getInstance().broadcast(chatId, "", new StringBuilder(game.getPlayer(playerId).getName()).append(" has joined the game").toString(), MessageColor.ORANGE, true, MessageType.GAME); checkStart(); } @@ -321,7 +323,7 @@ public class GameController implements GameCallback { GameWatcher gameWatcher = new GameWatcher(userId, game, false); watchers.put(userId, gameWatcher); gameWatcher.init(); - ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE); + ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS); } } @@ -329,7 +331,7 @@ public class GameController implements GameCallback { watchers.remove(userId); User user = UserManager.getInstance().getUser(userId); if (user != null) { - ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE); + ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS); } } @@ -405,12 +407,11 @@ public class GameController implements GameCallback { public void timeout(UUID userId) { if (userPlayerMap.containsKey(userId)) { - ; StringBuilder sb = new StringBuilder(game.getPlayer(userPlayerMap.get(userId)).getName()) .append(" has timed out (player had priority and was not active for ") .append(ConfigSettings.getInstance().getMaxSecondsIdle()) .append(" seconds ) - Auto concede."); - ChatManager.getInstance().broadcast(chatId, "", sb.toString() , MessageColor.BLACK); + ChatManager.getInstance().broadcast(chatId, "", sb.toString() , MessageColor.BLACK, true, MessageType.STATUS); concede(userId); } } diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoom.java b/Mage.Server/src/main/java/mage/server/game/GamesRoom.java index e08489c8f6..b6abe9ee7e 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoom.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoom.java @@ -38,6 +38,7 @@ import mage.game.tournament.TournamentOptions; import mage.server.Room; import mage.view.MatchView; import mage.view.TableView; +import mage.view.UsersView; /** * @@ -47,7 +48,7 @@ public interface GamesRoom extends Room { List getTables(); List getFinished(); - List getPlayers(); + List getPlayers(); boolean joinTable(UUID userId, UUID tableId, String name, String playerType, int skill, DeckCardLists deckList) throws MageException; boolean joinTournamentTable(UUID userId, UUID tableId, String name, String playerType, int skill) throws GameException; TableView createTable(UUID userId, MatchOptions options); diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java index 3a01266284..95e1d2ec2f 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -38,9 +38,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import mage.constants.TableState; import mage.MageException; import mage.cards.decks.DeckCardLists; +import mage.constants.TableState; import mage.game.GameException; import mage.game.Table; import mage.game.match.MatchOptions; @@ -51,9 +51,9 @@ import mage.server.User; import mage.server.UserManager; import mage.view.MatchView; import mage.view.TableView; +import mage.view.UsersView; import org.apache.log4j.Logger; - /** * * @author BetaSteward_at_googlemail.com @@ -65,7 +65,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { private static ScheduledExecutorService updateExecutor = Executors.newSingleThreadScheduledExecutor(); private static List tableView = new ArrayList(); private static List matchView = new ArrayList(); - private static List playersView = new ArrayList(); + private static List usersView = new ArrayList(); private ConcurrentHashMap tables = new ConcurrentHashMap(); @@ -109,16 +109,16 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } tableView = tableList; matchView = matchList; - List players = new ArrayList(); + List users = new ArrayList(); for (User user : UserManager.getInstance().getUsers()) { - StringBuilder sb = new StringBuilder(user.getName()); - sb.append(user.getUserInfo()); + StringBuilder sb = new StringBuilder(user.getGameInfo()); if (!user.isConnected()) { sb.append(" (discon.)"); } - players.add(sb.toString()); + users.add(new UsersView(user.getName(), user.getInfo(), sb.toString())); } - playersView = players; + Collections.sort(users, new UserNameSorter()); + usersView = users; } @Override @@ -190,8 +190,8 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } @Override - public List getPlayers() { - return playersView; + public List getPlayers() { + return usersView; } } @@ -202,3 +202,10 @@ class TimestampSorter implements Comparator { return one.getCreateTime().compareTo(two.getCreateTime()); } } + +class UserNameSorter implements Comparator { + @Override + public int compare(UsersView one, UsersView two) { + return one.getUserName().compareTo(two.getUserName()); + } +} \ No newline at end of file diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index 53832c72dc..099af813c9 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -54,6 +54,7 @@ import mage.server.draft.DraftManager; import mage.server.game.GamesRoomManager; import mage.server.util.ThreadExecutor; import mage.view.ChatMessage.MessageColor; +import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.SoundToPlay; import mage.view.TournamentView; import org.apache.log4j.Logger; @@ -91,7 +92,7 @@ public class TournamentController { public void event(TableEvent event) { switch (event.getEventType()) { case INFO: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK); + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, MessageType.STATUS); logger.debug(tournament.getId() + " " + event.getMessage()); break; case START_DRAFT: @@ -137,7 +138,7 @@ public class TournamentController { if (!player.getPlayer().isHuman()) { player.setJoined(); logger.debug("player " + player.getPlayer().getId() + " has joined tournament " + tournament.getId()); - ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has joined the tournament", MessageColor.BLACK); + ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS); } } checkStart(); @@ -151,7 +152,7 @@ public class TournamentController { TournamentPlayer player = tournament.getPlayer(playerId); player.setJoined(); logger.debug("player " + playerId + " has joined tournament " + tournament.getId()); - ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has joined the tournament", MessageColor.BLACK); + ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS); checkStart(); } @@ -247,7 +248,7 @@ public class TournamentController { TournamentPlayer player = tournament.getPlayer(playerId); if (player != null && !player.hasQuit()) { tournamentSessions.get(playerId).submitDeck(deck); - ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has submitted his tournament deck", MessageColor.BLACK, true, SoundToPlay.PlayerSubmittedDeck); + ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has submitted his tournament deck", MessageColor.BLACK, true, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck); } } } @@ -275,7 +276,7 @@ public class TournamentController { TournamentPlayer tPlayer = tournament.getPlayer(playerId); if (tPlayer != null) { if (started) { - ChatManager.getInstance().broadcast(chatId, "", tPlayer.getPlayer().getName() + " has quit the tournament", MessageColor.BLACK, true, SoundToPlay.PlayerLeft); + ChatManager.getInstance().broadcast(chatId, "", tPlayer.getPlayer().getName() + " has quit the tournament", MessageColor.BLACK, true, MessageType.STATUS, SoundToPlay.PlayerLeft); String info; if (tournament.isDoneConstructing()) { info = new StringBuilder("during round ").append(tournament.getRounds().size()).toString(); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 6cc8fc00f8..8474f9f20f 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -558,7 +558,7 @@ public abstract class GameImpl> implements Game, Serializa boolean wasPaused = state.isPaused(); state.resume(); if (!isGameOver()) { - fireInformEvent("Turn " + Integer.toString(state.getTurnNum())); + fireInformEvent(new StringBuilder("Turn ").append(state.getTurnNum()).toString()); if (checkStopOnTurnOption()) { return; }