From f5c349472341bc58974fb90abf5631c444acad6d Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Mon, 5 Sep 2011 22:12:36 -0400 Subject: [PATCH] improved replays - can now skip forward 10 moves or let the client play through the moves --- .../main/java/mage/client/game/GamePanel.java | 111 +++++++++++++++--- .../buttons/control_double_stop_left.png | Bin 0 -> 580 bytes .../buttons/control_double_stop_right.png | Bin 0 -> 567 bytes .../main/resources/buttons/control_right.png | Bin 0 -> 411 bytes .../main/resources/buttons/control_stop.png | Bin 0 -> 528 bytes .../resources/buttons/control_stop_left.png | Bin 0 -> 452 bytes .../resources/buttons/control_stop_right.png | Bin 0 -> 433 bytes .../src/mage/interfaces/MageServer.java | 1 + Mage.Common/src/mage/remote/Session.java | 16 ++- .../main/java/mage/server/MageServerImpl.java | 20 ++++ .../java/mage/server/game/ReplayManager.java | 5 + .../java/mage/server/game/ReplaySession.java | 9 +- 12 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 Mage.Client/src/main/resources/buttons/control_double_stop_left.png create mode 100644 Mage.Client/src/main/resources/buttons/control_double_stop_right.png create mode 100644 Mage.Client/src/main/resources/buttons/control_right.png create mode 100644 Mage.Client/src/main/resources/buttons/control_stop.png create mode 100644 Mage.Client/src/main/resources/buttons/control_stop_left.png create mode 100644 Mage.Client/src/main/resources/buttons/control_stop_right.png diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index be5776bea15..403fc27d796 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -60,6 +60,8 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.Serializable; import java.util.*; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; import java.util.prefs.Preferences; import mage.client.components.MageComponents; @@ -79,6 +81,7 @@ public class GamePanel extends javax.swing.JPanel { private UUID gameId; private UUID playerId; private Session session; + private ReplayTask replayTask; private CombatDialog combat; private PickNumberDialog pickNumber; private JLayeredPane jLayeredPane; @@ -572,8 +575,10 @@ public class GamePanel extends javax.swing.JPanel { stack = new mage.client.cards.Cards(); pnlReplay = new javax.swing.JPanel(); btnStopReplay = new javax.swing.JButton(); - btnPreviousPlay = new javax.swing.JButton(); btnNextPlay = new javax.swing.JButton(); + btnPlay = new javax.swing.JButton(); + btnSkipForward = new javax.swing.JButton(); + btnPreviousPlay = new javax.swing.JButton(); pnlBattlefield = new javax.swing.JPanel(); hand = new mage.client.cards.Cards(true); gameChatPanel = new mage.client.chat.ChatPanel(); @@ -664,44 +669,63 @@ public class GamePanel extends javax.swing.JPanel { stack.setPreferredSize(new java.awt.Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight + 25)); - btnStopReplay.setText("Stop"); + btnStopReplay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop.png"))); // NOI18N btnStopReplay.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnStopReplayActionPerformed(evt); } }); - btnPreviousPlay.setText("Previous"); - btnPreviousPlay.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnPreviousPlayActionPerformed(evt); - } - }); - - btnNextPlay.setText("Next"); + btnNextPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop_right.png"))); // NOI18N btnNextPlay.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnNextPlayActionPerformed(evt); } }); + btnPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_right.png"))); // NOI18N + btnPlay.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPlayActionPerformed(evt); + } + }); + + btnSkipForward.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_double_stop_right.png"))); // NOI18N + btnSkipForward.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSkipForwardActionPerformed(evt); + } + }); + + btnPreviousPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/control_stop_left.png"))); // NOI18N + btnPreviousPlay.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPreviousPlayActionPerformed(evt); + } + }); + javax.swing.GroupLayout pnlReplayLayout = new javax.swing.GroupLayout(pnlReplay); pnlReplay.setLayout(pnlReplayLayout); pnlReplayLayout.setHorizontalGroup( pnlReplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnlReplayLayout.createSequentialGroup() - .addComponent(btnStopReplay) + .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnPreviousPlay) + .addComponent(btnPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnStopReplay, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnNextPlay)) + .addComponent(btnNextPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnSkipForward, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) ); pnlReplayLayout.setVerticalGroup( pnlReplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlReplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnStopReplay) - .addComponent(btnPreviousPlay) - .addComponent(btnNextPlay)) + .addComponent(btnSkipForward, 0, 0, Short.MAX_VALUE) + .addComponent(btnNextPlay, 0, 0, Short.MAX_VALUE) + .addComponent(btnStopReplay, 0, 0, Short.MAX_VALUE) + .addComponent(btnPlay, 0, 0, Short.MAX_VALUE) + .addComponent(btnPreviousPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 31, Short.MAX_VALUE) ); javax.swing.GroupLayout pnlGameInfoLayout = new javax.swing.GroupLayout(pnlGameInfo); @@ -919,7 +943,10 @@ public class GamePanel extends javax.swing.JPanel { }//GEN-LAST:event_btnStopWatchingActionPerformed private void btnStopReplayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopReplayActionPerformed - if (modalQuestion("Are you sure you want to stop replay?", "Stop replay") == JOptionPane.YES_OPTION) { + if (replayTask != null && !replayTask.isDone()) { + replayTask.cancel(true); + } + else if (modalQuestion("Are you sure you want to stop replay?", "Stop replay") == JOptionPane.YES_OPTION) { session.stopReplay(gameId); } }//GEN-LAST:event_btnStopReplayActionPerformed @@ -931,7 +958,18 @@ public class GamePanel extends javax.swing.JPanel { private void btnPreviousPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPreviousPlayActionPerformed session.previousPlay(gameId); }//GEN-LAST:event_btnPreviousPlayActionPerformed + + private void btnPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlayActionPerformed + if (replayTask == null || replayTask.isDone()) { + replayTask = new ReplayTask(session, gameId); + replayTask.execute(); + } + }//GEN-LAST:event_btnPlayActionPerformed + private void btnSkipForwardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSkipForwardActionPerformed + session.skipForward(gameId, 10); + }//GEN-LAST:event_btnSkipForwardActionPerformed + private Dimension getHandCardDimension() { Preferences pref = MageFrame.getPreferences(); String useBigCards = pref.get(PreferencesDialog.KEY_HAND_USE_BIG_CARDS, "false"); @@ -966,6 +1004,7 @@ public class GamePanel extends javax.swing.JPanel { setOpaque(false); jPanel.setOpaque(false); jScrollPane1.setOpaque(false); + pnlReplay.setOpaque(false); jPanel.setBorder(emptyBorder); jScrollPane1.setBorder(emptyBorder); @@ -1000,7 +1039,9 @@ public class GamePanel extends javax.swing.JPanel { private javax.swing.JButton btnConcede; private javax.swing.JButton btnSwitchHands; private javax.swing.JButton btnNextPlay; + private javax.swing.JButton btnPlay; private javax.swing.JButton btnPreviousPlay; + private javax.swing.JButton btnSkipForward; private javax.swing.JButton btnStopReplay; private javax.swing.JButton btnStopWatching; private mage.client.chat.ChatPanel gameChatPanel; @@ -1045,3 +1086,37 @@ public class GamePanel extends javax.swing.JPanel { private JButton prevStep; private JLabel endButtonTip; } + +class ReplayTask extends SwingWorker> { + + private Session session; + private UUID gameId; + + private final static Logger logger = Logger.getLogger(ReplayTask.class); + + ReplayTask(Session session, UUID gameId) { + this.session = session; + this.gameId = gameId; + } + + @Override + protected Void doInBackground() throws Exception { + while (!isCancelled()) { + session.nextPlay(gameId); + Thread.sleep(1000); + } + return null; + } + + @Override + protected void done() { + try { + get(); + } catch (InterruptedException ex) { + logger.fatal("Update Matches Task error", ex); + } catch (ExecutionException ex) { + logger.fatal("Update Matches Task error", ex); + } catch (CancellationException ex) {} + } + +} diff --git a/Mage.Client/src/main/resources/buttons/control_double_stop_left.png b/Mage.Client/src/main/resources/buttons/control_double_stop_left.png new file mode 100644 index 0000000000000000000000000000000000000000..181bd6f7c39acff0614b308fb8c6de33b43aef9c GIT binary patch literal 580 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+S!VC(K#9UIO`&C9V-A z!TD(=<%vb942~)JNvR5+xryniL8*x;m4zo$Z5S9BuX(yShE&{oGxN6JAqNrH?{}i~ z9j++7YSy>=WnI^D|B3q#YdeYLfF6<7ps0_1rG8W0M3g5bWLsP|QH-p;k$wK9LzBlO zmj9KWe?A{&(m8-YpEWkr@0iQ;-gDmEwzD0-0(V%)oYf1&dw(XK6?cm67g5y&1VkVYqaIc%fFU?R&8g|6*kR6YHM`UA# zfRnoA`-asjXC5UiiOoEmxlquyJwRV-`PbJvHo95%UPpVTnpD1TIBIhyLeeVWu#b}!10 zbuG);ePQQzF9==}+@W%41^@qD+5Qqzf~}?L%E^T_{blM+$&zy&Lbr$QNuJWQ?XW=U z{+au@O+L#tP%`InYMdsdA;leCIbdf LS3j3^P6r@-bc0b>r%Ld7}8a?*+((^3mg zECxo^9q+P|)_wF+?|h(dWJ2yCLq?}`u+YKhC2#( z;$~!9S19E*nzvi{75~_5*{ZT&PVLRwcm^L&_7ya>4?$647C$hFXIPJ(|a-8yp z@f6ozR-dCgrlg)?P5EA%&lYH+&&sn$WYWt`Cb##^Um?n|_tQlSwtqTx{2>QV|Kk5~ yi>aNVzp=iiYMrjbhyRQs4#=o+wdfC#1cvO>TQlDEip&GXJcFmJpUXO@geCytKJ9e? literal 0 HcmV?d00001 diff --git a/Mage.Client/src/main/resources/buttons/control_right.png b/Mage.Client/src/main/resources/buttons/control_right.png new file mode 100644 index 0000000000000000000000000000000000000000..fd06590db6bf498fe5869432c889a5c93187aadb GIT binary patch literal 411 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+S!VC(K#9UIO`&C9V-A z!TD(=<%vb942~)JNvR5+xryniL8*x;m4zo$Z5S9Bbv<1iLn>~)x#{b7*g$~w!Sf@2 zN>fEVR&Sd){o%`pMgMFLw6EXvHUInlS8~4g9WCOF zKR(obul@cy&BfX$>0xTviTE_Vn#(d5``s^oP-3|McU|pqi+M*5cQdqo>&dio=hQEr v=*pwd)FJtA)22W6FfV~U_h0OT@&SgZN73tS7Rqb_hAxArtDnm{r-UW|Uht_; literal 0 HcmV?d00001 diff --git a/Mage.Client/src/main/resources/buttons/control_stop.png b/Mage.Client/src/main/resources/buttons/control_stop.png new file mode 100644 index 0000000000000000000000000000000000000000..34cc507f15beeb29ab8027a2737967ed2100b511 GIT binary patch literal 528 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+S!VC(K#9UIO`&C9V-A z!TD(=<%vb942~)JNvR5+xryniL8*x;m4zo$Z5S9B7kRokhE&{oGt<}auz^79^YeRI zmp>Ai)9GBGwZv;pLUTmOp$ePi<-GS)7xhWFPt!IHz5l%O^PE*PirbX=o0|I>I2sVh z;==@8`MRpg8-H~E{rS;V&V1qHOuJX7JSMO_R7v$^IrGi#(4ziRwpE5)9I6%8@y|90 zi1nV~2s+~3c;Wi~cOSbaG92E>{Z_sfVR&S1|81||t4CXf_Hr3?wgzS131)PV33YGX zm2tl^H{q-O`5?w#KdFf2QKzJ*hkQ7@rOW3s^Xs-PJ9KIrSGq3~xc}y#4a2*)r75c_ zY}Z7k%z8iFF5%8|nHzUJvp?z@`Pw+Tt)8%>^j4R3Xu^CA2{*N?%g%}}i#+}&xn1fk z>jQqSy^hf_S*#{T(>azdeEW`n!J&0ZlmBiwHFM9zrOSmL)%kzi~)x#{oM>>$GSA^)Fa zXvVBdw|0C8kvn8u$+7MtS-VF}>gl$IUsuXRW9~V*J@^~?@Kuu5tFO{w zr+GzUw-x#yHkL?Ecwpe*dGW4rQf%&o=cU*8v|MO(UoN27waM+*mX?jH7vu`}H+RM# z*HGNF=s>Mies!at^82`y7LU(7+xz(ioPPY&bnLiU+%@~=+}#X}AJvm)oxRH%(p|88 r>W}M-KK^Hf`x)f@2MLVvOgs!x2QwtqTyNh4MgxPVtDnm{r-UW|d!4!P literal 0 HcmV?d00001 diff --git a/Mage.Client/src/main/resources/buttons/control_stop_right.png b/Mage.Client/src/main/resources/buttons/control_stop_right.png new file mode 100644 index 0000000000000000000000000000000000000000..7dced0bb6dbfe65ff99d449bfaf3ba41e8e87178 GIT binary patch literal 433 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+S!VC(K#9UIO`&C9V-A z!TD(=<%vb942~)JNvR5+xryniL8*x;m4zo$Z5S9BojqL~Ln>~)xf$=*>>$AQVdh`v zwMx0S)a)v?_#e)+Y5D$vwgvCNLye|oOdsaJ6=X}aPI+_#A*-Z)X$@z!ENLC$}d z3{{x~o?si^mquJxf^LyJ8~!AFE==9zcCp0lm5anl*$ZbvYSf5Kn z*DWStvWGU`-jw3)8ff;ge=Ap|>{{OV@M+Vwl$HNUulT6HXb6ZP&P1QH9gg^3dPXZYY_1r&%5*YfM($qZM_zr`l NJYD@<);T3K0RUB1tMUK< literal 0 HcmV?d00001 diff --git a/Mage.Common/src/mage/interfaces/MageServer.java b/Mage.Common/src/mage/interfaces/MageServer.java index 9d61d2077df..8df091e6943 100644 --- a/Mage.Common/src/mage/interfaces/MageServer.java +++ b/Mage.Common/src/mage/interfaces/MageServer.java @@ -113,6 +113,7 @@ public interface MageServer { public void stopReplay(UUID gameId, String sessionId) throws MageException; public void nextPlay(UUID gameId, String sessionId) throws MageException; public void previousPlay(UUID gameId, String sessionId) throws MageException; + public void skipForward(UUID gameId, String sessionId, int moves) throws MageException; //test methods public void cheat(UUID gameId, String sessionId, UUID playerId, DeckCardLists deckList) throws MageException; diff --git a/Mage.Common/src/mage/remote/Session.java b/Mage.Common/src/mage/remote/Session.java index 5c3169dea64..30a43b3186e 100644 --- a/Mage.Common/src/mage/remote/Session.java +++ b/Mage.Common/src/mage/remote/Session.java @@ -843,7 +843,21 @@ public class Session { return false; } - public boolean cheat(UUID gameId, UUID playerId, DeckCardLists deckList) { + public boolean skipForward(UUID gameId, int moves) { + try { + if (isConnected()) { + server.skipForward(gameId, sessionId, moves); + return true; + } + } catch (MageException ex) { + handleMageException(ex); + } catch (Throwable t) { + handleThrowable(t); + } + return false; + } + + public boolean cheat(UUID gameId, UUID playerId, DeckCardLists deckList) { try { if (isConnected()) { server.cheat(gameId, sessionId, playerId, deckList); diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 121794f44a9..f2f141dfc18 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -858,6 +858,26 @@ public class MageServerImpl implements MageServer { } @Override + public void skipForward(final UUID gameId, final String sessionId, final int moves) throws MageException { + if (SessionManager.getInstance().isValidSession(sessionId)) { + try { + callExecutor.execute( + new Runnable() { + @Override + public void run() { + UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId(); + ReplayManager.getInstance().skipForward(gameId, userId, moves); + } + } + ); + } + catch (Exception ex) { + handleException(ex); + } + } + } + + @Override public ServerState getServerState() throws MageException { try { return new ServerState( diff --git a/Mage.Server/src/main/java/mage/server/game/ReplayManager.java b/Mage.Server/src/main/java/mage/server/game/ReplayManager.java index a181936ecf6..52de54ea7bc 100644 --- a/Mage.Server/src/main/java/mage/server/game/ReplayManager.java +++ b/Mage.Server/src/main/java/mage/server/game/ReplayManager.java @@ -68,5 +68,10 @@ public class ReplayManager { public void previousPlay(UUID gameId, UUID userId) { replaySessions.get(gameId.toString() + userId.toString()).previous(); } + + public void skipForward(UUID gameId, UUID userId, int moves) { + replaySessions.get(gameId.toString() + userId.toString()).next(moves); + } + } diff --git a/Mage.Server/src/main/java/mage/server/game/ReplaySession.java b/Mage.Server/src/main/java/mage/server/game/ReplaySession.java index ed26b7c1c05..30c3e7fb0e3 100644 --- a/Mage.Server/src/main/java/mage/server/game/ReplaySession.java +++ b/Mage.Server/src/main/java/mage/server/game/ReplaySession.java @@ -68,7 +68,14 @@ public class ReplaySession implements GameCallback { updateGame(replay.next(), replay.getGame()); } - public synchronized void previous() { + public synchronized void next(int moves) { + for (int i = 0; i < moves; i++) { + replay.next(); + } + updateGame(replay.next(), replay.getGame()); + } + + public synchronized void previous() { updateGame(replay.previous(), replay.getGame()); }