From f644ffe041feb4d2f5298486e31a5eefa8d19e45 Mon Sep 17 00:00:00 2001
From: LevelX2 <ludwig.hirth@online.de>
Date: Sun, 7 Apr 2013 21:29:27 +0200
Subject: [PATCH] Changed color of frame of avatar for active player to green
 again. Checked that a player of a game can't also watch his own game. Added a
 match score to the start of the game log. Changed the color of the Turn [X]
 message. Tips and join messages during a game are displayed in the chat panel
 instead the game log panel. Display of the player name when hovering over the
 avatar is more vertical centered.

---
 .../mage/client/components/HoverButton.java   |  9 +++++--
 .../java/mage/client/game/PlayerPanelExt.java |  3 ++-
 .../client/remote/CallbackClientImpl.java     |  4 +--
 Mage.Common/src/mage/view/ChatMessage.java    |  4 +++
 .../src/mage/game/CommanderDuelMatch.java     |  1 +
 .../src/mage/game/FreeForAllMatch.java        |  1 +
 .../src/mage/game/TwoPlayerMatch.java         |  2 ++
 .../main/java/mage/server/ChatManager.java    |  4 +++
 .../main/java/mage/server/ChatSession.java    | 10 ++++---
 .../java/mage/server/TableController.java     |  6 +++++
 .../java/mage/server/game/GameController.java | 26 ++++++++++++-------
 Mage/src/mage/game/Game.java                  |  1 +
 Mage/src/mage/game/GameImpl.java              | 21 +++++++++++++--
 Mage/src/mage/game/events/TableEvent.java     | 12 ++++++++-
 .../mage/game/events/TableEventSource.java    |  4 +++
 Mage/src/mage/game/match/MatchImpl.java       | 14 +++++++++-
 16 files changed, 100 insertions(+), 22 deletions(-)

diff --git a/Mage.Client/src/main/java/mage/client/components/HoverButton.java b/Mage.Client/src/main/java/mage/client/components/HoverButton.java
index cfa1370a96..4d78bbc3c1 100644
--- a/Mage.Client/src/main/java/mage/client/components/HoverButton.java
+++ b/Mage.Client/src/main/java/mage/client/components/HoverButton.java
@@ -24,6 +24,7 @@ public class HoverButton extends JPanel implements MouseListener {
     private Rectangle buttonSize;
     private String text;
     private int textOffsetY = 0;
+    private int textOffsetButtonY = 2;
     private int textOffsetX = -1;
     private Dimension overlayImageSize;
 
@@ -187,17 +188,21 @@ public class HoverButton extends JPanel implements MouseListener {
     @Override
     public void setBounds(Rectangle r) {
         super.setBounds(r);
-        this.textOffsetY = r.height - 2;
+        this.textOffsetY = r.height - this.textOffsetButtonY;
         this.buttonSize = r;
     }
 
     @Override
     public void setBounds(int x, int y, int width, int height) {
         super.setBounds(x, y, width, height);
-        this.textOffsetY = height - 2;
+        this.textOffsetY = height - this.textOffsetButtonY;
         this.buttonSize = new Rectangle(x, y, width, height);
     }
 
+    public void setTextOffsetButtonY(int textOffsetButtonY) {
+        this.textOffsetButtonY = textOffsetButtonY;
+    }
+
     public boolean isSelected() {
         return isSelected;
     }
diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
index 2fbdb04814..c9d06ff422 100644
--- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
+++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
@@ -90,7 +90,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
     private static final int PANEL_HEIGHT = 242;
     private static final int PANEL_HEIGHT_SMALL = 190;
 
-    private static final Border greenBorder = new LineBorder(Color.red, 3);
+    private static final Border greenBorder = new LineBorder(Color.green, 3);
     private static final Border redBorder = new LineBorder(Color.red, 2);
     private static final Border emptyBorder = BorderFactory.createEmptyBorder(0,0,0,0);
 
@@ -224,6 +224,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
 
         BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
         avatar = new HoverButton("player", resized, resized, resized, r);
+        avatar.setTextOffsetButtonY(10);
         avatar.setObserver(new Command() {
             @Override
             public void execute() {
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 ff659edb01..e06f83f3ab 100644
--- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java
+++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java
@@ -100,8 +100,8 @@ public class CallbackClientImpl implements CallbackClient {
                         ChatMessage message = (ChatMessage) callback.getData();
                         ChatPanel panel = frame.getChat(callback.getObjectId());
                         if (panel != null) {
-                            if (message.getMessage().equals(Constants.MSG_TIP_HOT_KEYS_CODE)) {
-                                panel.receiveMessage("[Tips] ", "You may use hot keys to play faster: " + "" +
+                            if (message.getMessage().equals(Constants.MSG_TIP_HOT_KEYS_CODE) && panel.getConnectedChat() != null) {
+                                panel.getConnectedChat().receiveMessage("[Tips] ", "You may use hot keys to play faster: " + "" +
                                         "\nF2 - Confirm \"Ok\", \"Yes\" or \"Done\" button" +
                                         "\nF4 - Skip current turn but stop on declare attackers" +
                                         "\nF9 - Skip everything until your next turn" +
diff --git a/Mage.Common/src/mage/view/ChatMessage.java b/Mage.Common/src/mage/view/ChatMessage.java
index 471b38882e..32eaa53105 100644
--- a/Mage.Common/src/mage/view/ChatMessage.java
+++ b/Mage.Common/src/mage/view/ChatMessage.java
@@ -65,6 +65,10 @@ public class ChatMessage implements Serializable {
         return color != null && color.equals(MessageColor.BLUE);
     }
 
+    public boolean isStatusMessage() {
+        return color != null && color.equals(MessageColor.ORANGE);
+    }
+
     public String getUsername() {
         return username;
     }
diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java b/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java
index 2ce2275b4d..4817c023c1 100644
--- a/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java
+++ b/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java
@@ -44,6 +44,7 @@ public class CommanderDuelMatch extends MatchImpl {
     @Override
     public void startGame() throws GameException {
         CommanderDuel game = new CommanderDuel(options.getAttackOption(), options.getRange());
+        game.setStartMessage(this.createGameStartMessage());
         initGame(game);
         games.add(game);
     }
diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/src/mage/game/FreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.FreeForAll/src/mage/game/FreeForAllMatch.java
index f5d0fe1178..e40e41a0c8 100644
--- a/Mage.Server.Plugins/Mage.Game.FreeForAll/src/mage/game/FreeForAllMatch.java
+++ b/Mage.Server.Plugins/Mage.Game.FreeForAll/src/mage/game/FreeForAllMatch.java
@@ -44,6 +44,7 @@ public class FreeForAllMatch extends MatchImpl {
     @Override
     public void startGame() throws GameException {
         FreeForAll game = new FreeForAll(options.getAttackOption(), options.getRange());
+        game.setStartMessage(this.createGameStartMessage());
         initGame(game);
         games.add(game);
     }
diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/src/mage/game/TwoPlayerMatch.java b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/src/mage/game/TwoPlayerMatch.java
index 9871a3ecea..a1c10f8a16 100644
--- a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/src/mage/game/TwoPlayerMatch.java
+++ b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/src/mage/game/TwoPlayerMatch.java
@@ -44,6 +44,8 @@ public class TwoPlayerMatch extends MatchImpl {
     @Override
     public void startGame() throws GameException {
         TwoPlayerDuel game = new TwoPlayerDuel(options.getAttackOption(), options.getRange());
+        // Sets a start message about the match score
+        game.setStartMessage(this.createGameStartMessage());
         initGame(game);
         games.add(game);
     }
diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java
index 4d7d8d5f75..4704c98651 100644
--- a/Mage.Server/src/main/java/mage/server/ChatManager.java
+++ b/Mage.Server/src/main/java/mage/server/ChatManager.java
@@ -71,6 +71,10 @@ public class ChatManager {
         chatSessions.get(chatId).broadcast(userName, message, color);
     }
 
+    public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime) {
+        chatSessions.get(chatId).broadcast(userName, message, color, withTime);
+    }
+
     /**
      * 
      * 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 b8f6f67a5e..c8d15646dc 100644
--- a/Mage.Server/src/main/java/mage/server/ChatSession.java
+++ b/Mage.Server/src/main/java/mage/server/ChatSession.java
@@ -59,7 +59,7 @@ public class ChatSession {
         if (user != null && !clients.containsKey(userId)) {
             String userName = user.getName();
             clients.put(userId, userName);
-            broadcast(userName, " has joined", MessageColor.BLACK);
+            broadcast(userName, " has joined", MessageColor.BLUE);
             logger.info(userName + " joined chat " + chatId);
         }
     }
@@ -68,16 +68,20 @@ public class ChatSession {
         if (userId != null && clients.containsKey(userId)) {
             String userName = clients.get(userId);
             clients.remove(userId);
-            broadcast(userName, " has left", MessageColor.BLACK);
+            broadcast(userName, " has left", MessageColor.BLUE);
             logger.info(userName + " has left chat " + chatId);
         }
     }
 
     public void broadcast(String userName, String message, MessageColor color) {
+        broadcast(userName, message, color, true);        
+    }
+
+    public void broadcast(String userName, String message, MessageColor color, boolean withTime) {
         if (!message.isEmpty()) {
             Calendar cal = new GregorianCalendar();
             final String msg = message;
-            final String time = timeFormatter.format(cal.getTime());
+            final String time = (withTime ? timeFormatter.format(cal.getTime()):"");
             final String username = userName;
             logger.debug("Broadcasting '" + msg + "' for " + chatId);
             for (UUID userId: clients.keySet()) {
diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java
index e5278b1779..aea7a46b9d 100644
--- a/Mage.Server/src/main/java/mage/server/TableController.java
+++ b/Mage.Server/src/main/java/mage/server/TableController.java
@@ -40,6 +40,7 @@ import mage.MageException;
 import mage.cards.decks.Deck;
 import mage.cards.decks.DeckCardLists;
 import mage.cards.decks.InvalidDeckException;
+import mage.game.Game;
 import mage.game.GameException;
 import mage.game.GameOptions;
 import mage.game.Seat;
@@ -63,6 +64,7 @@ import mage.server.tournament.TournamentFactory;
 import mage.server.tournament.TournamentManager;
 import mage.server.util.ServerMessagesUtil;
 import mage.server.util.ThreadExecutor;
+import mage.view.ChatMessage.MessageColor;
 import org.apache.log4j.Logger;
 
 
@@ -248,6 +250,10 @@ public class TableController {
         if (table.getState() != TableState.DUELING) {
             return false;
         }
+        // you can't watch your own game
+        if (userPlayerMap.get(userId) != null) {
+            return false;
+        }
         UserManager.getInstance().getUser(userId).watchGame(match.getGame().getId());
         return true;
     }
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 9304e8ab02..5f7f93654f 100644
--- a/Mage.Server/src/main/java/mage/server/game/GameController.java
+++ b/Mage.Server/src/main/java/mage/server/game/GameController.java
@@ -114,6 +114,10 @@ public class GameController implements GameCallback {
                                 ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK);
                                 logger.debug(game.getId() + " " + event.getMessage());
                                 break;
+                            case STATUS:
+                                ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime());
+                                logger.debug(game.getId() + " " + event.getMessage());
+                                break;
                             case REVEAL:
                                 revealCards(event.getMessage(), event.getCards());
                                 break;
@@ -180,11 +184,7 @@ public class GameController implements GameCallback {
                 }
             }
         );
-        for (Player player: game.getPlayers().values()) {
-            if (!player.isHuman()) {
-                ChatManager.getInstance().broadcast(chatId, "", player.getName() + " has joined the game", MessageColor.BLACK);
-            }
-        }
+
         checkStart();
     }
 
@@ -240,15 +240,21 @@ public class GameController implements GameCallback {
     }
 
     public void watch(UUID userId) {
-        GameWatcher gameWatcher = new GameWatcher(userId, game);
-        watchers.put(userId, gameWatcher);
-        gameWatcher.init();
-        ChatManager.getInstance().broadcast(chatId, "", " has started watching", MessageColor.BLACK);
+        User user = UserManager.getInstance().getUser(userId);
+        if (user != null) {
+            GameWatcher gameWatcher = new GameWatcher(userId, game);
+            watchers.put(userId, gameWatcher);
+            gameWatcher.init();
+            ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE);
+        }
     }
 
     public void stopWatching(UUID userId) {
         watchers.remove(userId);
-        ChatManager.getInstance().broadcast(chatId, "", " has stopped watching", MessageColor.BLACK);
+        User user = UserManager.getInstance().getUser(userId);
+        if (user != null) {
+            ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE);
+        }
     }
 
     public void concede(UUID userId) {
diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java
index 1b711253db..40bc619837 100644
--- a/Mage/src/mage/game/Game.java
+++ b/Mage/src/mage/game/Game.java
@@ -144,6 +144,7 @@ public interface Game extends MageItem, Serializable {
     void fireGetAmountEvent(UUID playerId, String message, int min, int max);
     void fireChoosePileEvent(UUID playerId, String message, List<? extends Card> pile1, List<? extends Card> pile2);
     void fireInformEvent(String message);
+    void fireStatusEvent(String message, boolean withTime);
     void fireUpdatePlayersEvent();
     void informPlayers(String message);
     void informPlayer(Player player, String message);
diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java
index a008247657..c6642d0cc5 100644
--- a/Mage/src/mage/game/GameImpl.java
+++ b/Mage/src/mage/game/GameImpl.java
@@ -136,6 +136,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
     protected RangeOfInfluence range;
     protected MultiplayerAttackOption attackOption;
     protected GameOptions gameOptions;
+    protected String startMessage;
 
     public static volatile int copyCount = 0;
     public static volatile long copyTime = 0;
@@ -536,7 +537,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
     }
 
     private boolean playTurn(Player player) {
-        fireInformEvent("Turn " + Integer.toString(state.getTurnNum()));
+        fireStatusEvent("Turn " + Integer.toString(state.getTurnNum()), true);
         if (checkStopOnTurnOption()) {
             return false;
         }
@@ -567,7 +568,11 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
         for (Player player: state.getPlayers().values()) {
             player.beginTurn(this);
         }
-        fireInformEvent("game has started");
+        if (startMessage.isEmpty()) {
+            startMessage = "Game has started";
+        }
+        fireStatusEvent(startMessage, false);
+
         //saveState();
 
         //20091005 - 103.1
@@ -1394,6 +1399,14 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
         tableEventSource.fireTableEvent(EventType.INFO, message, this);
     }
 
+    @Override
+    public void fireStatusEvent(String message, boolean withTime) {
+        if (simulation) {
+            return;
+        }
+        tableEventSource.fireTableEvent(EventType.STATUS, message, withTime, this);
+    }
+
     @Override
     public void fireUpdatePlayersEvent() {
         if (simulation) {
@@ -1804,4 +1817,8 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
     public boolean getScopeRelevant() {
         return this.scopeRelevant;
     }
+
+    public void setStartMessage(String startMessage) {
+        this.startMessage = startMessage;
+    }
 }
diff --git a/Mage/src/mage/game/events/TableEvent.java b/Mage/src/mage/game/events/TableEvent.java
index 9b57a85e3e..b9c9041cea 100644
--- a/Mage/src/mage/game/events/TableEvent.java
+++ b/Mage/src/mage/game/events/TableEvent.java
@@ -46,7 +46,7 @@ import java.util.UUID;
 public class TableEvent extends EventObject implements ExternalEvent, Serializable {
 
     public enum EventType {
-        UPDATE, INFO, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR
+        UPDATE, INFO, STATUS, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR
     }
 
     private Game game;
@@ -60,6 +60,7 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
     private TournamentPairing pair;
     private MatchOptions options;
     private int timeout;
+    private boolean withTime;
 
     public TableEvent(EventType eventType) {
         super(eventType);
@@ -67,10 +68,15 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
     }
 
     public TableEvent(EventType eventType, String message, Game game) {
+        this(eventType, message, true, game);
+    }
+
+    public TableEvent(EventType eventType, String message, boolean withTime, Game game) {
         super(game);
         this.game = game;
         this.message = message;
         this.eventType = eventType;
+        this.withTime = withTime;
     }
 
     public TableEvent(EventType eventType, String message, Cards cards, Game game) {
@@ -153,4 +159,8 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
     public int getTimeout() {
         return timeout;
     }
+
+    public boolean getWithTime() {
+        return withTime;
+    }
 }
diff --git a/Mage/src/mage/game/events/TableEventSource.java b/Mage/src/mage/game/events/TableEventSource.java
index 6d89abb684..c482a48903 100644
--- a/Mage/src/mage/game/events/TableEventSource.java
+++ b/Mage/src/mage/game/events/TableEventSource.java
@@ -60,6 +60,10 @@ public class TableEventSource implements EventSource<TableEvent>, Serializable {
         dispatcher.fireEvent(new TableEvent(eventType, message, game));
     }
 
+    public void fireTableEvent(EventType eventType, String message, boolean withTime, Game game) {
+        dispatcher.fireEvent(new TableEvent(eventType, message, withTime, game));
+    }
+
     public void fireTableEvent(EventType eventType, UUID playerId, String message, Game game) {
         dispatcher.fireEvent(new TableEvent(eventType, playerId, message, game));
     }
diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java
index 526c5b982a..5f6f8dbfa1 100644
--- a/Mage/src/mage/game/match/MatchImpl.java
+++ b/Mage/src/mage/game/match/MatchImpl.java
@@ -238,6 +238,18 @@ public abstract class MatchImpl implements Match {
             player.updateDeck(deck);
         }
     }
-
+    
+    protected String createGameStartMessage() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("\nMatch score:\n");
+        for (MatchPlayer mp :this.getPlayers()) {
+            sb.append("- ").append(mp.getPlayer().getName());
+            sb.append(" (").append(mp.getWins()).append(" wins / ");
+            sb.append(mp.getLoses()).append(" losses)\n");
+        }
+        sb.append("\n").append(this.getWinsNeeded()).append(" wins needed to win the match\n");
+        sb.append("\nGame has started\n");
+        return sb.toString();
+    }
 
 }