diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index ec45800b9a5..e56fcf0a5ea 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -93,6 +93,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.prefs.Preferences; +import mage.view.GameEndView; /** * @author BetaSteward_at_googlemail.com @@ -611,6 +612,12 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } } + public void showGameEndDialog(GameEndView gameEndView) { + GameEndDialog gameEndDialog = new GameEndDialog(gameEndView); + desktopPane.add(gameEndDialog, JLayeredPane.POPUP_LAYER); + gameEndDialog.showDialog(); + } + public void showTableWaitingDialog(UUID roomId, UUID tableId, boolean isTournament) { TableWaitingDialog tableWaitingDialog = new TableWaitingDialog(); desktopPane.add(tableWaitingDialog, JLayeredPane.MODAL_LAYER); diff --git a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form new file mode 100644 index 00000000000..256cc2251aa --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form @@ -0,0 +1,303 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java new file mode 100644 index 00000000000..2888b329118 --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java @@ -0,0 +1,318 @@ +/* + * 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. + */ + +/* + * GameEndDialog.java + * + * Created on Jul 31, 2013, 9:41:00 AM + */ + +package mage.client.dialog; + +import java.awt.Color; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.text.DateFormat; +import java.util.Calendar; +import java.util.Date; +import javax.swing.ImageIcon; +import mage.client.util.AudioManager; +import mage.client.util.Format; +import mage.client.util.ImageHelper; +import mage.client.util.gui.BufferedImageBuilder; +import mage.view.GameEndView; +import mage.view.PlayerView; + +/** + * + * @author LevelX2 + */ +public class GameEndDialog extends MageDialog { + + private final DateFormat df = DateFormat.getDateTimeInstance();; + + + /** Creates new form GameEndDialog */ + public GameEndDialog(GameEndView gameEndView) { + + initComponents(); + this.modal = true; + + pnlText.setOpaque(true); + pnlText.setBackground(new Color(240,240,240,140)); + + Rectangle r = new Rectangle(610, 250); + Image image = ImageHelper.getImageFromResources(gameEndView.hasWon() ?"/game_won.jpg":"/game_lost.jpg"); + BufferedImage imageResult = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r); + ImageIcon icon = new ImageIcon(imageResult); + lblResultImage.setIcon(icon); + + this.lblResultText.setText(gameEndView.getResultMessage()); + + // game duration + txtDurationGame.setText(Format.getDuration(gameEndView.getStartTime(), gameEndView.getEndTime())); + txtDurationGame.setToolTipText(new StringBuilder(df.format(gameEndView.getStartTime())).append(" - ").append(df.format(gameEndView.getEndTime())).toString() ); + + // match duration + Calendar cal = Calendar.getInstance(); + txtDurationMatch.setText(Format.getDuration(gameEndView.getMatchView().getStartTime(), cal.getTime())); + txtDurationMatch.setToolTipText(new StringBuilder(df.format(gameEndView.getMatchView().getStartTime())).append(" - ").append(df.format(cal.getTime())).toString() ); + + StringBuilder sb = new StringBuilder(); + for (PlayerView player : gameEndView.getPlayers()) { + sb.append(player.getName()).append(" Life: ").append(player.getLife()).append(" "); + } + this.txtLife.setText(sb.toString()); + + if (gameEndView.hasWon()) { + AudioManager.playPlayerJoinedTable(); + } else { + AudioManager.playButtonCancel(); + } + + txtMatchScore.setText(gameEndView.getMatchView().getResult()); + + if (gameEndView.getNameMatchWinner() != null) { + if (gameEndView.getClientPlayer().getName().equals(gameEndView.getNameMatchWinner())) { + lblMatchInfo.setText("You won the match!"); + } else { + lblMatchInfo.setText(new StringBuilder(gameEndView.getNameMatchWinner()).append(" won the match!").toString()); + } + } else { + int winsNeeded = gameEndView.getWinsNeeded() - gameEndView.getWins(); + lblMatchInfo.setText(new StringBuilder("You need ").append(winsNeeded == 1 ? "one win ":winsNeeded + " wins ").append("to win the match.").toString()); + } + + + } + + public void showDialog() { + this.setLocation(100, 100); + this.setVisible(true); + } + + /** 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 + private void initComponents() { + + jPanel2 = new javax.swing.JPanel(); + tabPane = new javax.swing.JTabbedPane(); + tabResult = new javax.swing.JLayeredPane(); + pnlText = new javax.swing.JLayeredPane(); + lblMatchInfo = new javax.swing.JLabel(); + lblResultText = new javax.swing.JLabel(); + lblResultImage = new javax.swing.JLabel(); + tabStatistics = new javax.swing.JPanel(); + lblDurationGame = new javax.swing.JLabel(); + txtDurationGame = new javax.swing.JLabel(); + lblLife = new javax.swing.JLabel(); + txtLife = new javax.swing.JLabel(); + lblDurationMatch = new javax.swing.JLabel(); + txtDurationMatch = new javax.swing.JLabel(); + lblMatchScore = new javax.swing.JLabel(); + txtMatchScore = new javax.swing.JLabel(); + lblPlayerInfo = new javax.swing.JLabel(); + txtPlayerInfo = new javax.swing.JLabel(); + btnOk = new javax.swing.JButton(); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 100, Short.MAX_VALUE) + ); + + setTitle("Game end information"); + + pnlText.setBackground(new java.awt.Color(200, 100, 100)); + pnlText.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + pnlText.setOpaque(true); + + lblMatchInfo.setFont(new java.awt.Font("Tahoma", 3, 24)); // NOI18N + lblMatchInfo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblMatchInfo.setText("matchInfo"); + lblMatchInfo.setBounds(11, 42, 550, 40); + pnlText.add(lblMatchInfo, javax.swing.JLayeredPane.DEFAULT_LAYER); + + lblResultText.setFont(new java.awt.Font("Tahoma", 3, 24)); // NOI18N + lblResultText.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblResultText.setText("result text"); + lblResultText.setBounds(11, 1, 550, 40); + pnlText.add(lblResultText, javax.swing.JLayeredPane.DEFAULT_LAYER); + + pnlText.setBounds(20, 150, 570, 90); + tabResult.add(pnlText, javax.swing.JLayeredPane.DEFAULT_LAYER); + + lblResultImage.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N + lblResultImage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblResultImage.setBounds(0, 0, 610, 250); + tabResult.add(lblResultImage, javax.swing.JLayeredPane.DEFAULT_LAYER); + + tabPane.addTab("Result", tabResult); + + lblDurationGame.setText("Duration game:"); + + txtDurationGame.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + lblLife.setText("Life at end:"); + + txtLife.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + lblDurationMatch.setText("Duration match:"); + + txtDurationMatch.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + lblMatchScore.setText("Match score:"); + + txtMatchScore.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + lblPlayerInfo.setText("Player info:"); + + txtPlayerInfo.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + javax.swing.GroupLayout tabStatisticsLayout = new javax.swing.GroupLayout(tabStatistics); + tabStatistics.setLayout(tabStatisticsLayout); + tabStatisticsLayout.setHorizontalGroup( + tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabStatisticsLayout.createSequentialGroup() + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabStatisticsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblPlayerInfo, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblDurationMatch, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblMatchScore, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(tabStatisticsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblDurationGame, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblLife, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtPlayerInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtDurationGame, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE) + .addComponent(txtLife, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE) + .addComponent(txtDurationMatch, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE) + .addComponent(txtMatchScore, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE)) + .addContainerGap()) + ); + tabStatisticsLayout.setVerticalGroup( + tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabStatisticsLayout.createSequentialGroup() + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblDurationGame, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtDurationGame, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblLife, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtLife, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblDurationMatch, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtDurationMatch, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblMatchScore, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtMatchScore, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblPlayerInfo, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtPlayerInfo, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(99, Short.MAX_VALUE)) + ); + + tabPane.addTab("Statistics", tabStatistics); + + btnOk.setText("OK"); + btnOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnOkActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnOk) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(tabPane, javax.swing.GroupLayout.PREFERRED_SIZE, 626, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(tabPane, javax.swing.GroupLayout.PREFERRED_SIZE, 277, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnOk) + .addGap(0, 25, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed + this.removeDialog(); + }//GEN-LAST:event_btnOkActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnOk; + private javax.swing.JPanel jPanel2; + private javax.swing.JLabel lblDurationGame; + private javax.swing.JLabel lblDurationMatch; + private javax.swing.JLabel lblLife; + private javax.swing.JLabel lblMatchInfo; + private javax.swing.JLabel lblMatchScore; + private javax.swing.JLabel lblPlayerInfo; + private javax.swing.JLabel lblResultImage; + private javax.swing.JLabel lblResultText; + private javax.swing.JLayeredPane pnlText; + private javax.swing.JTabbedPane tabPane; + private javax.swing.JLayeredPane tabResult; + private javax.swing.JPanel tabStatistics; + private javax.swing.JLabel txtDurationGame; + private javax.swing.JLabel txtDurationMatch; + private javax.swing.JLabel txtLife; + private javax.swing.JLabel txtMatchScore; + private javax.swing.JLabel txtPlayerInfo; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java b/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java index cac7b90cd95..21694f92aa5 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/MageDialog.java @@ -40,6 +40,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.lang.reflect.InvocationTargetException; +import mage.client.MageFrame; /** * @@ -157,6 +158,11 @@ public class MageDialog extends javax.swing.JInternalFrame { this.setVisible(false); } + public void removeDialog() { + this.setVisible(false); + MageFrame.getDesktop().remove(this); + } + public void setTitelBarToolTip(final String text) { desktopIcon.setToolTipText(text); //tooltip on icon Component[] children = desktopIcon.getComponents(); 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 b8738221bf3..1831240e0a5 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -51,6 +51,7 @@ import mage.view.DeckView; import mage.view.DraftClientMessage; import mage.view.DraftView; import mage.view.GameClientMessage; +import mage.view.GameEndView; import mage.view.GameView; import mage.view.TableClientMessage; import org.apache.log4j.Logger; @@ -240,6 +241,9 @@ public class CallbackClientImpl implements CallbackClient { panel.updateGame((GameView) callback.getData()); } } + else if (callback.getMethod().equals("endGameInfo")) { + MageFrame.getInstance().showGameEndDialog((GameEndView) callback.getData()); + } else if (callback.getMethod().equals("gameInform")) { if (callback.getMessageId() > messageId) { diff --git a/Mage.Client/src/main/java/mage/client/util/Format.java b/Mage.Client/src/main/java/mage/client/util/Format.java new file mode 100644 index 00000000000..d13423d58b8 --- /dev/null +++ b/Mage.Client/src/main/java/mage/client/util/Format.java @@ -0,0 +1,76 @@ +/* +* Copyright 2011 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.util; + +import java.util.Date; + +/** + * + * @author LevelX2 + */ +public class Format { + + /** + * calculates the duration between two dates and returns a string in the format hhh:mm:ss + * + * @param fromDate - start date + * @param toDate - end date + * @return a string in the format hhh:mm:ss + */ + public static String getDuration(Date fromDate, Date toDate) { + if (fromDate == null || toDate == null || fromDate.getTime() > toDate.getTime()) { + return ""; + } + + return getDuration((toDate.getTime() - fromDate.getTime()) / 1000); + } + /** + * Converts seconds to a string with hours, minutes and seconds + * + * @param seconds - seconds of the duration + * @return a string in the format hhh:mm:ss + */ + public static String getDuration(long seconds) { + StringBuilder sb = new StringBuilder(); + long h = seconds / 3600; + seconds = seconds % 3600; + long m = seconds / 60; + long s = seconds % 60; + sb.append(h).append(":"); + if (m<10) { + sb.append("0"); + } + sb.append(m).append(":"); + if (s<10) { + sb.append("0"); + } + sb.append(s); + return sb.toString(); + } +} diff --git a/Mage.Client/src/main/resources/game_lost.jpg b/Mage.Client/src/main/resources/game_lost.jpg new file mode 100644 index 00000000000..e2fcd36136d Binary files /dev/null and b/Mage.Client/src/main/resources/game_lost.jpg differ diff --git a/Mage.Client/src/main/resources/game_won.jpg b/Mage.Client/src/main/resources/game_won.jpg new file mode 100644 index 00000000000..241f8952f13 Binary files /dev/null and b/Mage.Client/src/main/resources/game_won.jpg differ diff --git a/Mage.Common/src/mage/view/GameEndView.java b/Mage.Common/src/mage/view/GameEndView.java new file mode 100644 index 00000000000..7aab1501c1b --- /dev/null +++ b/Mage.Common/src/mage/view/GameEndView.java @@ -0,0 +1,147 @@ +/* + * 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; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import mage.game.Game; +import mage.game.GameState; +import mage.game.match.Match; +import mage.game.match.MatchPlayer; +import mage.players.Player; + +/** + * @author LevelX2 + */ +public class GameEndView implements Serializable { + + private PlayerView clientPlayer = null; + private List players = new ArrayList(); + private Date startTime; + private Date endTime; + private String resultMessage; + private boolean won; + private MatchView matchView; + private int wins; + private int loses; + private int winsNeeded; + private String nameMatchWinner = null; + + public GameEndView(GameState state, Game game, UUID playerId, Match match) { + startTime = game.getStartTime(); + endTime = game.getEndTime(); + + // set result message + int winner = 0; + Player you = null; + for (Player player: state.getPlayers().values()) { + PlayerView playerView = new PlayerView(player, state, game); + if (playerView.getPlayerId().equals(playerId)) { + clientPlayer = playerView; + you = player; + } + players.add(playerView); + if (player.hasWon()) { + winner++; + } + } + if (you != null) { + won = you.hasWon(); + if (you.hasWon()) { + resultMessage = new StringBuilder("You won the game on turn ").append(game.getTurnNum()).append(".").toString(); + } else if (winner > 0) { + resultMessage = new StringBuilder("You lost the game on turn ").append(game.getTurnNum()).append(".").toString(); + } else { + resultMessage = new StringBuilder("Game is a draw on Turn ").append(game.getTurnNum()).append(".").toString(); + } + } + matchView = new MatchView(match); + + winsNeeded = match.getOptions().getWinsNeeded(); + for (MatchPlayer mPlayer: match.getPlayers()) { + if (mPlayer.getPlayer().equals(you)) { + wins = mPlayer.getWins(); + loses = mPlayer.getLoses(); + + } + if (mPlayer.getWins() == winsNeeded) { + nameMatchWinner = mPlayer.getPlayer().getName(); + } + } + + } + + public Date getStartTime() { + return startTime; + } + + public Date getEndTime() { + return endTime; + } + + public List getPlayers() { + return players; + } + + public String getResultMessage() { + return resultMessage; + } + + public boolean hasWon() { + return won; + } + + public MatchView getMatchView() { + return matchView; + } + + public int getWins() { + return wins; + } + + public int getLoses() { + return loses; + } + + public int getWinsNeeded() { + return winsNeeded; + } + + public String getNameMatchWinner() { + return nameMatchWinner; + } + + public PlayerView getClientPlayer() { + return clientPlayer; + } + +} diff --git a/Mage.Common/src/mage/view/PlayerView.java b/Mage.Common/src/mage/view/PlayerView.java index 9b10b0d376e..f549114171f 100644 --- a/Mage.Common/src/mage/view/PlayerView.java +++ b/Mage.Common/src/mage/view/PlayerView.java @@ -127,14 +127,17 @@ public class PlayerView implements Serializable { private boolean showInBattlefield(Permanent permanent, GameState state) { //show permanents controlled by player or attachments to permanents controlled by player - if (permanent.getAttachedTo() == null) + if (permanent.getAttachedTo() == null) { return permanent.getControllerId().equals(playerId); + } else { Permanent attachedTo = state.getPermanent(permanent.getAttachedTo()); - if (attachedTo != null) + if (attachedTo != null) { return attachedTo.getControllerId().equals(playerId); - else + } + else { return permanent.getControllerId().equals(playerId); + } } } diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 11968b95327..c79af48f7ba 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -155,6 +155,10 @@ public class TableController { tournament.addPlayer(player, seat.getPlayerType()); table.joinTable(player, seat); User user = UserManager.getInstance().getUser(userId); + if (user == null) { + logger.fatal(new StringBuilder("couldn't get user ").append(name).append(" for join tornament userId = ").append(userId).toString()); + return false; + } user.addTable(player.getId(), table); logger.info("player joined " + player.getId()); //only inform human players and add them to sessionPlayerMap diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 0fb03fa0a10..a87c4a061a5 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -160,6 +160,10 @@ public class User { fireCallback(new ClientCallback("showTournament", tournamentId)); } + public void showGameEndDialog(final UUID gameId) { + fireCallback(new ClientCallback("showGameEndDialog", gameId)); + } + public void watchGame(final UUID gameId) { fireCallback(new ClientCallback("watchGame", gameId)); } 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 b3abf298815..cd5b1610aab 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -57,6 +57,7 @@ import mage.cards.repository.CardRepository; import mage.constants.Zone; import mage.game.Game; import mage.game.GameException; +import mage.game.Table; import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; @@ -141,6 +142,9 @@ public class GameController implements GameCallback { case ERROR: error(event.getMessage(), event.getException()); break; + case END_GAME_INFO: + endGameInfo(); + break; case INIT_TIMER: final UUID initPlayerId = event.getPlayerId(); if (initPlayerId == null) { @@ -475,6 +479,21 @@ public class GameController implements GameCallback { } } + private synchronized void endGameInfo() { + Table table = TableManager.getInstance().getTable(tableId); + if (table != null) { + if (table.getMatch() != null) { + for (final GameSession gameSession: gameSessions.values()) { + gameSession.endGameInfo(table.getMatch()); + } + } + } + // TODO: inform watchers +// for (final GameWatcher gameWatcher: watchers.values()) { +// gameWatcher.update(); +// } + } + private synchronized void ask(UUID playerId, final String question) throws MageException { perform(playerId, new Command() { @Override diff --git a/Mage.Server/src/main/java/mage/server/game/GameSession.java b/Mage.Server/src/main/java/mage/server/game/GameSession.java index 1eee2b538f3..28a5cfecae2 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSession.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSession.java @@ -36,6 +36,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import mage.cards.Cards; import mage.game.Game; +import mage.game.match.Match; import mage.interfaces.callback.ClientCallback; import mage.players.Player; import mage.players.net.UserData; @@ -160,6 +161,15 @@ public class GameSession extends GameWatcher { } } + public void endGameInfo(Match match) { + if (!killed) { + User user = UserManager.getInstance().getUser(userId); + if (user != null) { + user.fireCallback(new ClientCallback("endGameInfo", game.getId(), getGameEndView(playerId, match))); + } + } + } + private synchronized void setupTimeout() { if (!useTimeout) { return; diff --git a/Mage.Server/src/main/java/mage/server/game/GameWatcher.java b/Mage.Server/src/main/java/mage/server/game/GameWatcher.java index ac458181121..7193e82faa0 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameWatcher.java +++ b/Mage.Server/src/main/java/mage/server/game/GameWatcher.java @@ -38,6 +38,8 @@ import org.apache.log4j.Logger; import java.rmi.RemoteException; import java.util.UUID; +import mage.game.match.Match; +import mage.view.GameEndView; /** * @@ -124,5 +126,9 @@ public class GameWatcher { public GameView getGameView() { return new GameView(game.getState(), game); } + + public GameEndView getGameEndView(UUID playerId, Match match) { + return new GameEndView(game.getState(), game, playerId, match); + } } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index cf8f6347d2c..45bc2de77ec 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -151,6 +151,7 @@ public interface Game extends MageItem, Serializable { void informPlayer(Player player, String message); void debugMessage(String message); void fireErrorEvent(String message, Exception ex); + void fireGameEndInfo(); //game event methods void fireEvent(GameEvent event); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 7f9b7b84bb9..230784c941a 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -1551,6 +1551,15 @@ public abstract class GameImpl> implements Game, Serializa tableEventSource.fireTableEvent(EventType.UPDATE, null, this); } + @Override + public void fireGameEndInfo() { + if (simulation) { + return; + } + logger.trace("fireGameEndIfo"); + tableEventSource.fireTableEvent(EventType.END_GAME_INFO, null, this); + } + @Override public void fireErrorEvent(String message, Exception ex) { tableEventSource.fireTableEvent(EventType.ERROR, message, ex, this); diff --git a/Mage/src/mage/game/events/TableEvent.java b/Mage/src/mage/game/events/TableEvent.java index a359155095b..eaf2568a0c9 100644 --- a/Mage/src/mage/game/events/TableEvent.java +++ b/Mage/src/mage/game/events/TableEvent.java @@ -45,7 +45,7 @@ import mage.game.tournament.TournamentPairing; public class TableEvent extends EventObject implements ExternalEvent, Serializable { public enum EventType { - UPDATE, INFO, STATUS, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR, + UPDATE, INFO, STATUS, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, END_GAME_INFO, ERROR, INIT_TIMER, RESUME_TIMER, PAUSE_TIMER } diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java index 8df1ee07903..d44d7ac4b4a 100644 --- a/Mage/src/mage/game/match/MatchImpl.java +++ b/Mage/src/mage/game/match/MatchImpl.java @@ -208,6 +208,7 @@ public abstract class MatchImpl implements Match { } } } + game.fireGameEndInfo(); } @Override