From 0a5bb7329e65ecca19d02d892342c791a842963b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 30 Apr 2014 19:09:38 +0200 Subject: [PATCH 01/15] Added Jouney into NyxIntro packs to the example decks. --- .../2014/Into packs/[JOU] Fates Foreseen.dck | 28 +++++++++++++++++++ .../2014/Into packs/[JOU] Mortals of Myth.dck | 28 +++++++++++++++++++ .../Into packs/[JOU] Pantheon's Power.dck | 27 ++++++++++++++++++ .../[JOU] The Wilds and the Deep.dck | 28 +++++++++++++++++++ .../2014/Into packs/[JOU] Voracious Rage.dck | 26 +++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 Mage.Client/release/sample-decks/2014/Into packs/[JOU] Fates Foreseen.dck create mode 100644 Mage.Client/release/sample-decks/2014/Into packs/[JOU] Mortals of Myth.dck create mode 100644 Mage.Client/release/sample-decks/2014/Into packs/[JOU] Pantheon's Power.dck create mode 100644 Mage.Client/release/sample-decks/2014/Into packs/[JOU] The Wilds and the Deep.dck create mode 100644 Mage.Client/release/sample-decks/2014/Into packs/[JOU] Voracious Rage.dck diff --git a/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Fates Foreseen.dck b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Fates Foreseen.dck new file mode 100644 index 00000000000..89a90227c70 --- /dev/null +++ b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Fates Foreseen.dck @@ -0,0 +1,28 @@ +NAME:Fates Foreseen +1 [THS:45] Crackling Triton +1 [JOU:38] Font of Fortunes +2 [BNG:36] Divination +1 [JOU:32] Cloaked Siren +2 [JOU:101] Knowledge and Power +2 [JOU:52] Sigiled Starfish +1 [JOU:51] Scourge of Fleets +1 [JOU:103] Magma Spray +2 [JOU:105] Pensive Minotaur +1 [JOU:90] Bladetusk Boar +2 [BNG:112] Stormcaller of Keranos +2 [THS:123] Flamespeaker Adept +2 [JOU:107] Riddle of Lightning +1 [JOU:92] Cyclops of Eternal Fury +1 [THS:52] Lost in a Labyrinth +1 [JOU:97] Font of Ire +1 [THS:57] Omenspeaker +1 [THS:59] Prescient Chimera +2 [JOU:49] Rise of Eagles +1 [JOU:47] Pull from the Deep +1 [JOU:113] Spite of Mogis +1 [JOU:43] Interpret the Signs +2 [JOU:111] Sigiled Skink +1 [THS:137] Rage of Purphoros +13 [C13:349] Mountain +1 [THS:60] Prognostic Sphinx +13 [DDM:37] Island diff --git a/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Mortals of Myth.dck b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Mortals of Myth.dck new file mode 100644 index 00000000000..e5fab14e9dc --- /dev/null +++ b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Mortals of Myth.dck @@ -0,0 +1,28 @@ +NAME:Mortals of Myth +1 [JOU:131] Nature's Panoply +1 [THS:33] Spear of Heliod +2 [JOU:5] Banishing Light +1 [JOU:20] Oreskos Swiftclaw +1 [JOU:6] Dawnbringer Charioteers +1 [BNG:3] Akroan Skyguard +1 [JOU:21] Phalanx Formation +2 [JOU:2] Ajani's Presence +1 [BNG:8] Elite Skirmisher +2 [JOU:3] Akroan Mastiff +1 [BNG:29] Vanguard of Brimaz +11 [DDM:84] Forest +1 [JOU:26] Skyspear Cavalry +2 [JOU:28] Supply-Line Cranes +1 [JOU:22] Quarry Colossus +1 [THS:26] Phalanx Leader +15 [C13:337] Plains +1 [BNG:135] Raised by Wolves +2 [JOU:124] Golden Hind +1 [JOU:141] Solidarity of Heroes +1 [THS:36] Wingsteed Rider +2 [JOU:14] Lagonna-Band Trailblazer +1 [JOU:11] Font of Vigor +1 [JOU:119] Consign to Dust +2 [JOU:118] Colossal Heroics +2 [JOU:134] Pheres-Band Thunderhoof +2 [JOU:19] Oppressive Rays diff --git a/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Pantheon's Power.dck b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Pantheon's Power.dck new file mode 100644 index 00000000000..ec064430d10 --- /dev/null +++ b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Pantheon's Power.dck @@ -0,0 +1,27 @@ +NAME:Pantheon's Power +1 [JOU:78] Pharika's Chosen +2 [JOU:77] Nyx Infusion +1 [JOU:9] Eagle of the Watch +2 [BNG:79] Odunos River Trawler +1 [JOU:4] Armament of Nyx +1 [BNG:58] Archetype of Finality +1 [JOU:5] Banishing Light +1 [BNG:4] Archetype of Courage +2 [JOU:3] Akroan Mastiff +2 [JOU:73] Grim Guardian +11 [C13:337] Plains +1 [JOU:71] Font of Return +1 [BNG:68] Fate Unraveler +1 [JOU:66] Doomwake Giant +2 [JOU:67] Dreadbringer Lampads +2 [JOU:18] Nyx-Fleece Ram +1 [JOU:60] Aspect of Gorgon +2 [JOU:13] Harvestguard Alseids +1 [JOU:63] Cast into Darkness +1 [JOU:62] Brain Maggot +1 [JOU:11] Font of Vigor +15 [DDM:79] Swamp +2 [JOU:157] Underworld Coinsmith +2 [JOU:85] Thoughtrender Lamia +2 [JOU:19] Oppressive Rays +1 [JOU:81] Rotted Hulk diff --git a/Mage.Client/release/sample-decks/2014/Into packs/[JOU] The Wilds and the Deep.dck b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] The Wilds and the Deep.dck new file mode 100644 index 00000000000..f920f570cf4 --- /dev/null +++ b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] The Wilds and the Deep.dck @@ -0,0 +1,28 @@ +NAME:The Wilds and the Deep +1 [JOU:130] Market Festival +1 [BNG:32] Archetype of Imagination +1 [JOU:56] Triton Shorestalker +1 [JOU:38] Font of Fortunes +1 [THS:176] Savage Surge +2 [BNG:150] Kiora's Follower +1 [THS:148] Agent of Horizons +15 [DDM:84] Forest +1 [THS:164] Nessian Asp +1 [JOU:32] Cloaked Siren +1 [THS:165] Nessian Courser +1 [JOU:54] Thassa's Ire +1 [JOU:126] Heroes' Bane +1 [JOU:144] Swarmborn Giant +2 [JOU:149] Fleetfeather Cockatrice +2 [JOU:123] Font of Fertility +2 [JOU:124] Golden Hind +1 [THS:150] Arbor Colossus +2 [BNG:142] Swordwise Centaur +1 [JOU:41] Hubris +2 [THS:181] Time to Feed +1 [THS:156] Defend the Hearth +1 [JOU:117] Bassara Tower Archer +2 [JOU:136] Ravenous Leucrocota +2 [THS:62] Sealock Monster +11 [DDM:37] Island +2 [JOU:132] Nessian Game Warden diff --git a/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Voracious Rage.dck b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Voracious Rage.dck new file mode 100644 index 00000000000..6b32bad4126 --- /dev/null +++ b/Mage.Client/release/sample-decks/2014/Into packs/[JOU] Voracious Rage.dck @@ -0,0 +1,26 @@ +NAME:Voracious Rage +1 [JOU:78] Pharika's Chosen +2 [BNG:70] Felhide Brawler +2 [BNG:153] Ragemonger +2 [THS:195] Kragma Warcaller +1 [JOU:102] Lightning Diadem +2 [JOU:103] Magma Spray +1 [BNG:111] Searing Blood +3 [JOU:105] Pensive Minotaur +1 [THS:92] Insatiable Harpy +1 [JOU:108] Rollick of Abandon +1 [THS:121] Fanatic of Mogis +1 [JOU:70] Felhide Petrifier +2 [JOU:96] Flurry of Horns +1 [BNG:85] Warchanter of Mogis +1 [THS:130] Minotaur Skullcleaver +3 [THS:117] Deathbellow Raider +1 [JOU:112] Spawn of Thraxes +1 [THS:138] Rageblood Shaman +1 [JOU:63] Cast into Darkness +2 [JOU:114] Starfall +11 [DDM:79] Swamp +14 [C13:349] Mountain +1 [BNG:105] Pinnacle of Rage +2 [THS:114] Borderland Minotaur +2 [JOU:83] Spiteful Blow From b93cafe7078f5d01bdf122d76dfd09dc67eb6eaf Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 30 Apr 2014 20:23:50 +0200 Subject: [PATCH 02/15] * Quarry Colossus / Unexpectedly Absent - Fixed that card was not moved to the correct position inlibrary. --- .../commander2013/UnexpectedlyAbsent.java | 51 +++++++++++-------- .../sets/journeyintonyx/QuarryColossus.java | 23 +++++---- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/Mage.Sets/src/mage/sets/commander2013/UnexpectedlyAbsent.java b/Mage.Sets/src/mage/sets/commander2013/UnexpectedlyAbsent.java index d0fa4212bde..974176181ef 100644 --- a/Mage.Sets/src/mage/sets/commander2013/UnexpectedlyAbsent.java +++ b/Mage.Sets/src/mage/sets/commander2013/UnexpectedlyAbsent.java @@ -28,6 +28,8 @@ package mage.sets.commander2013; import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.UUID; @@ -100,31 +102,38 @@ class UnexpectedlyAbsentEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (permanent != null) { - Player owner = game.getPlayer(permanent.getOwnerId()); - if (owner != null) { - int xValue = Math.min(source.getManaCostsToPay().getX(), owner.getLibrary().size()); - Cards cards = new CardsImpl(Zone.PICK); - List cardIds = new ArrayList<>(); - for (int i = 0; i < xValue; i++) { - Card card = owner.getLibrary().getFromTop(game); - cards.add(card); - cardIds.add(card.getId()); - } - // return cards back to library - permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); - ListIterator l = cardIds.listIterator(); - while(l.hasPrevious()) { - UUID cardId = l.previous(); - Card card = cards.get(cardId, game); - if (card != null) { - card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + Player owner = game.getPlayer(permanent.getOwnerId()); + if (owner != null) { + int xValue = Math.min(source.getManaCostsToPay().getX(), owner.getLibrary().size()); + Cards cards = new CardsImpl(Zone.PICK); + Deque cardIds = new LinkedList<>(); + for (int i = 0; i < xValue; i++) { + Card card = owner.getLibrary().removeFromTop(game); + cards.add(card); + cardIds.push(card.getId()); } + // return cards back to library + game.informPlayers(new StringBuilder(controller.getName()) + .append(" puts ").append(permanent.getName()) + .append(" beneath the top ").append(xValue) + .append(" cards of ").append(owner.getName()).append("'s library").toString()); + permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + while(!cardIds.isEmpty()) { + UUID cardId = cardIds.poll(); + Card card = cards.get(cardId, game); + if (card != null) { + card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + } + } + return true; } - return true; } } + return false; } } diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/QuarryColossus.java b/Mage.Sets/src/mage/sets/journeyintonyx/QuarryColossus.java index 75cc01f4243..5eb98f81c1a 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/QuarryColossus.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/QuarryColossus.java @@ -27,10 +27,10 @@ */ package mage.sets.journeyintonyx; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; +import java.util.Deque; +import java.util.LinkedList; import java.util.UUID; +import java.util.logging.Logger; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -106,17 +106,20 @@ class QuarryColossusReturnLibraryEffect extends OneShotEffect cardIds = new ArrayList<>(); + Deque cardIds = new LinkedList<>(); for (int i = 0; i < xValue; i++) { - Card card = owner.getLibrary().getFromTop(game); + Card card = owner.getLibrary().removeFromTop(game); cards.add(card); - cardIds.add(card.getId()); + cardIds.push(card.getId()); } // return cards back to library - controller.moveCardToLibraryWithInfo(permanent, source.getSourceId(), game, Zone.BATTLEFIELD, true); - ListIterator libraryCards = cardIds.listIterator(); - while(libraryCards.hasPrevious()) { - UUID cardId = libraryCards.previous(); + permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + game.informPlayers(new StringBuilder(controller.getName()) + .append(" puts ").append(permanent.getName()) + .append(" beneath the top ").append(xValue) + .append(" cards of ").append(owner.getName()).append("'s library").toString()); + while(!cardIds.isEmpty()) { + UUID cardId = cardIds.poll(); Card card = cards.get(cardId, game); if (card != null) { card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); From c953bf62600612824e5771c96172242db39c5275 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 1 May 2014 08:42:46 +0200 Subject: [PATCH 03/15] * Consign to Dust - Fixed that only creature enchantments could be selected as target. --- Mage.Sets/src/mage/sets/journeyintonyx/ConsignToDust.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/ConsignToDust.java b/Mage.Sets/src/mage/sets/journeyintonyx/ConsignToDust.java index 618e45dd1ae..509478a97f9 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/ConsignToDust.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/ConsignToDust.java @@ -34,7 +34,7 @@ import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.Target; @@ -46,7 +46,7 @@ import mage.target.TargetPermanent; */ public class ConsignToDust extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("artifacts and/or enchantments"); + private static final FilterPermanent filter = new FilterPermanent("artifacts and/or enchantments"); static { filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.ENCHANTMENT))); From 57d1dc0f6d820be05fa0007f7a170fa1718f0e17 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 1 May 2014 19:27:26 +0200 Subject: [PATCH 04/15] Some additional info to the game end window. --- .../mage/client/dialog/GameEndDialog.form | 50 +++++++---- .../mage/client/dialog/GameEndDialog.java | 77 ++++++++--------- Mage.Common/src/mage/view/GameEndView.java | 85 +++++++++++++------ 3 files changed, 129 insertions(+), 83 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form index 5cbcc54bdb8..62cf99bc3bf 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.form @@ -1,6 +1,6 @@ -
+ @@ -56,7 +56,7 @@ - + @@ -75,7 +75,9 @@ - + + + @@ -90,38 +92,54 @@ - - + + - + + + + + + + + + + + + + + + + + - + - - + + - + - + - + - - + + @@ -135,8 +153,8 @@ - - + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java index d5dbd22cef8..b471904258a 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/GameEndDialog.java @@ -45,13 +45,12 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.swing.ImageIcon; -import javax.swing.JLayeredPane; import javax.swing.JOptionPane; import mage.client.MageFrame; import mage.client.game.GamePanel; -import mage.client.util.audio.AudioManager; import mage.client.util.Format; import mage.client.util.ImageHelper; +import mage.client.util.audio.AudioManager; import mage.client.util.gui.BufferedImageBuilder; import mage.view.GameEndView; import mage.view.PlayerView; @@ -65,7 +64,8 @@ public class GameEndDialog extends MageDialog { private final DateFormat df = DateFormat.getDateTimeInstance();; - /** Creates new form GameEndDialog */ + /** Creates new form GameEndDialog + * @param gameEndView */ public GameEndDialog(GameEndView gameEndView) { initComponents(); @@ -80,13 +80,14 @@ public class GameEndDialog extends MageDialog { ImageIcon icon = new ImageIcon(imageResult); lblResultImage.setIcon(icon); - this.lblResultText.setText(gameEndView.getResultMessage()); + this.lblGameInfo.setText(gameEndView.getGameInfo()); + this.lblMatchInfo.setText(gameEndView.getMatchInfo()); + this.lblAdditionalInfo.setText(gameEndView.getAdditionalInfo()); String autoSave = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_LOG_AUTO_SAVE, "true"); if (autoSave.equals("true")) { this.saveGameLog(gameEndView); } - // game duration txtDurationGame.setText(Format.getDuration(gameEndView.getStartTime(), gameEndView.getEndTime())); @@ -110,17 +111,6 @@ public class GameEndDialog extends MageDialog { } 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()); - } } private void saveGameLog(GameEndView gameEndView) { @@ -169,8 +159,9 @@ public class GameEndDialog extends MageDialog { tabPane = new javax.swing.JTabbedPane(); tabResult = new javax.swing.JLayeredPane(); pnlText = new javax.swing.JLayeredPane(); + lblGameInfo = new javax.swing.JLabel(); lblMatchInfo = new javax.swing.JLabel(); - lblResultText = new javax.swing.JLabel(); + lblAdditionalInfo = new javax.swing.JLabel(); lblResultImage = new javax.swing.JLabel(); tabStatistics = new javax.swing.JPanel(); lblDurationGame = new javax.swing.JLabel(); @@ -202,25 +193,31 @@ public class GameEndDialog extends MageDialog { pnlText.setBorder(javax.swing.BorderFactory.createEtchedBorder()); pnlText.setOpaque(true); - lblMatchInfo.setFont(new java.awt.Font("Tahoma", 3, 24)); // NOI18N + lblGameInfo.setFont(new java.awt.Font("Tahoma", 3, 18)); // NOI18N + lblGameInfo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblGameInfo.setText("gameInfo"); + pnlText.add(lblGameInfo); + lblGameInfo.setBounds(11, 1, 550, 25); + + lblMatchInfo.setFont(new java.awt.Font("Tahoma", 3, 18)); // NOI18N lblMatchInfo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); lblMatchInfo.setText("matchInfo"); - lblMatchInfo.setBounds(11, 42, 550, 40); - pnlText.add(lblMatchInfo, javax.swing.JLayeredPane.DEFAULT_LAYER); + pnlText.add(lblMatchInfo); + lblMatchInfo.setBounds(10, 30, 550, 25); - 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); + lblAdditionalInfo.setFont(new java.awt.Font("Tahoma", 3, 18)); // NOI18N + lblAdditionalInfo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblAdditionalInfo.setText("additionalInfo"); + pnlText.add(lblAdditionalInfo); + lblAdditionalInfo.setBounds(10, 60, 550, 25); + tabResult.add(pnlText); 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); + tabResult.add(lblResultImage); lblResultImage.setBounds(0, 0, 610, 250); - tabResult.add(lblResultImage, javax.swing.JLayeredPane.DEFAULT_LAYER); tabPane.addTab("Result", tabResult); @@ -249,22 +246,17 @@ public class GameEndDialog extends MageDialog { tabStatisticsLayout.setHorizontalGroup( tabStatisticsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(tabStatisticsLayout.createSequentialGroup() + .addContainerGap() .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)))) + .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) + .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(txtDurationGame, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 494, 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)) @@ -292,7 +284,7 @@ public class GameEndDialog extends MageDialog { .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)) + .addContainerGap(105, Short.MAX_VALUE)) ); tabPane.addTab("Statistics", tabStatistics); @@ -322,7 +314,7 @@ public class GameEndDialog extends MageDialog { .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)) + .addGap(0, 8, Short.MAX_VALUE)) ); pack(); @@ -335,14 +327,15 @@ public class GameEndDialog extends MageDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnOk; private javax.swing.JPanel jPanel2; + private javax.swing.JLabel lblAdditionalInfo; private javax.swing.JLabel lblDurationGame; private javax.swing.JLabel lblDurationMatch; + private javax.swing.JLabel lblGameInfo; 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; diff --git a/Mage.Common/src/mage/view/GameEndView.java b/Mage.Common/src/mage/view/GameEndView.java index cc0eff99541..6255760c942 100644 --- a/Mage.Common/src/mage/view/GameEndView.java +++ b/Mage.Common/src/mage/view/GameEndView.java @@ -45,16 +45,17 @@ import mage.players.Player; public class GameEndView implements Serializable { private PlayerView clientPlayer = null; - private List players = new ArrayList(); - private Date startTime; - private Date endTime; - private String resultMessage; + private final List players = new ArrayList<>(); + private final Date startTime; + private final Date endTime; + private String gameInfo; + private final String matchInfo; + private final String additionalInfo; private boolean won; - private MatchView matchView; + private final MatchView matchView; private int wins; private int loses; - private int winsNeeded; - private String nameMatchWinner = null; + private final int winsNeeded; public GameEndView(GameState state, Game game, UUID playerId, Match match) { startTime = game.getStartTime(); @@ -68,6 +69,7 @@ public class GameEndView implements Serializable { if (playerView.getPlayerId().equals(playerId)) { clientPlayer = playerView; you = player; + won = you.hasWon(); // needed to control image } players.add(playerView); if (player.hasWon()) { @@ -75,29 +77,58 @@ public class GameEndView implements Serializable { } } if (you != null) { - won = you.hasWon(); if (you.hasWon()) { - resultMessage = new StringBuilder("You won the game on turn ").append(game.getTurnNum()).append(".").toString(); + gameInfo = 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(); + gameInfo = 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(); + gameInfo = 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(); + MatchPlayer matchWinner = null; + winsNeeded = match.getOptions().getWinsNeeded(); + StringBuilder additonalText = new StringBuilder(); + for (MatchPlayer matchPlayer: match.getPlayers()) { + if (matchPlayer.getPlayer().equals(you)) { + wins = matchPlayer.getWins(); } - if (mPlayer.getWins() == winsNeeded) { - nameMatchWinner = mPlayer.getName(); + if (matchPlayer.isMatchWinner()) { + matchWinner = matchPlayer; + } + if (matchPlayer.hasTimerTimeout()) { + if (matchPlayer.getPlayer().equals(you)) { + additonalText.append("You run out of time. "); + } else { + additonalText.append(matchPlayer.getName()).append(" runs out of time. "); + } + } else if (matchPlayer.hasQuit()) { + if (matchPlayer.getPlayer().equals(you)) { + additonalText.append("You have quit the match. "); + } else { + additonalText.append(matchPlayer.getName()).append(" has quit the match. "); + } + } else if (matchPlayer.getPlayer().hasIdleTimeout()) { + if (matchPlayer.getPlayer().equals(you)) { + additonalText.append("You lost the match for beeing idle. "); + } else { + additonalText.append(matchPlayer.getName()).append(" lost for beeing idle. "); + } } } + if (matchWinner != null) { + if (matchWinner.getPlayer().equals(you)) { + matchInfo = "You won the match!"; + } else { + matchInfo = new StringBuilder(matchWinner.getName()).append(" won the match!").toString(); + } + } else { + matchInfo = new StringBuilder("You need ").append(winsNeeded - wins == 1 ? "one more win ":winsNeeded - wins + " more wins ").append("to win the match.").toString(); + } + additionalInfo = additonalText.toString(); + } public Date getStartTime() { @@ -112,8 +143,16 @@ public class GameEndView implements Serializable { return players; } - public String getResultMessage() { - return resultMessage; + public String getGameInfo() { + return gameInfo; + } + + public String getMatchInfo() { + return matchInfo; + } + + public String getAdditionalInfo() { + return additionalInfo; } public boolean hasWon() { @@ -136,10 +175,6 @@ public class GameEndView implements Serializable { return winsNeeded; } - public String getNameMatchWinner() { - return nameMatchWinner; - } - public PlayerView getClientPlayer() { return clientPlayer; } From 6d039e426223836d1ef0911c596ab5ac1d00104d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 1 May 2014 19:28:33 +0200 Subject: [PATCH 05/15] Tournament view some design changes and the remaining construction time and the round running time is shown. --- .../client/tournament/TournamentPanel.form | 228 ++++++++++++------ .../client/tournament/TournamentPanel.java | 169 +++++++++---- Mage.Common/src/mage/view/TournamentView.java | 22 +- 3 files changed, 296 insertions(+), 123 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form index f3da192341b..8eb281e6233 100644 --- a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form +++ b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form @@ -30,50 +30,55 @@ - + + + + + + + + + + - + - - + + + + + + + + - - - - - - - - - - - - - - - - - + - - - - - - - - + + + + + + + + + + + + + + @@ -81,87 +86,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + @@ -185,10 +231,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -267,6 +356,9 @@ + + + diff --git a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java index 0f5f29b01b6..b892d1968a4 100644 --- a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java +++ b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java @@ -52,6 +52,7 @@ import mage.client.MageFrame; import mage.client.chat.ChatPanel; import mage.client.dialog.PreferencesDialog; import mage.client.util.ButtonColumn; +import mage.client.util.Format; import mage.remote.Session; import mage.view.RoundView; import mage.view.TournamentGameView; @@ -208,9 +209,20 @@ public class TournamentPanel extends javax.swing.JPanel { firstInitDone = true; } + switch (tournament.getTournamentState()) { + case "Constructing": + String constructionTime = Format.getDuration(tournament.getConstructionTime() - (tournament.getServerTime().getTime() - tournament.getStepStartTime().getTime())/1000); + txtTournamentState.setText(new StringBuilder(tournament.getTournamentState()).append(" (").append(constructionTime).append(")").toString()); + break; + case "Dueling": + String duelingTime = Format.getDuration((tournament.getServerTime().getTime() - tournament.getStepStartTime().getTime())/1000); + txtTournamentState.setText(new StringBuilder(tournament.getTournamentState()).append(" (").append(duelingTime).append(")").toString()); + break; + default: + txtTournamentState.setText(tournament.getTournamentState()); + break; + } - txtTournamentState.setText(tournament.getTournamentState()); - if (txtEndTime == null) { return; } @@ -263,17 +275,18 @@ public class TournamentPanel extends javax.swing.JPanel { private void initComponents() { actionPanel = new javax.swing.JPanel(); - lblName = new javax.swing.JLabel(); txtName = new javax.swing.JTextField(); - lblType = new javax.swing.JLabel(); txtType = new javax.swing.JTextField(); - lblStartTime = new javax.swing.JLabel(); txtStartTime = new javax.swing.JTextField(); txtEndTime = new javax.swing.JTextField(); - lblTournamentState = new javax.swing.JLabel(); txtTournamentState = new javax.swing.JTextField(); btnQuitTournament = new javax.swing.JButton(); btnCloseWindow = new javax.swing.JButton(); + lblName = new javax.swing.JLabel(); + lblType = new javax.swing.JLabel(); + lblState = new javax.swing.JLabel(); + lblStartTime = new javax.swing.JLabel(); + lblEndTime = new javax.swing.JLabel(); jSplitPane2 = new javax.swing.JSplitPane(); jSplitPane1 = new javax.swing.JSplitPane(); jScrollPane1 = new javax.swing.JScrollPane(); @@ -284,36 +297,49 @@ public class TournamentPanel extends javax.swing.JPanel { setPreferredSize(new java.awt.Dimension(908, 580)); - lblName.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblName.setText("Name:"); + actionPanel.setBackground(java.awt.SystemColor.controlHighlight); + actionPanel.setFont(new java.awt.Font("Arial", 0, 10)); // NOI18N txtName.setEditable(false); txtName.setHorizontalAlignment(javax.swing.JTextField.LEFT); + txtName.setBorder(javax.swing.BorderFactory.createEtchedBorder()); txtName.setFocusable(false); txtName.setMaximumSize(new java.awt.Dimension(50, 22)); - - lblType.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblType.setText("Type:"); + txtName.setOpaque(false); + txtName.setRequestFocusEnabled(false); + txtName.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + txtNameActionPerformed(evt); + } + }); txtType.setEditable(false); txtType.setHorizontalAlignment(javax.swing.JTextField.LEFT); + txtType.setBorder(javax.swing.BorderFactory.createEtchedBorder()); txtType.setFocusable(false); - - lblStartTime.setText("Start / end time:"); + txtType.setOpaque(false); + txtType.setRequestFocusEnabled(false); txtStartTime.setEditable(false); txtStartTime.setHorizontalAlignment(javax.swing.JTextField.CENTER); + txtStartTime.setBorder(javax.swing.BorderFactory.createEtchedBorder()); txtStartTime.setFocusable(false); + txtStartTime.setOpaque(false); + txtStartTime.setRequestFocusEnabled(false); txtEndTime.setEditable(false); txtEndTime.setHorizontalAlignment(javax.swing.JTextField.CENTER); + txtEndTime.setBorder(javax.swing.BorderFactory.createEtchedBorder()); txtEndTime.setFocusable(false); - - lblTournamentState.setText("State:"); + txtEndTime.setOpaque(false); + txtEndTime.setRequestFocusEnabled(false); txtTournamentState.setEditable(false); txtTournamentState.setHorizontalAlignment(javax.swing.JTextField.CENTER); + txtTournamentState.setBorder(javax.swing.BorderFactory.createEtchedBorder()); txtTournamentState.setFocusable(false); + txtTournamentState.setOpaque(false); + txtTournamentState.setRequestFocusEnabled(false); btnQuitTournament.setText("Quit Tournament"); btnQuitTournament.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); @@ -331,59 +357,88 @@ public class TournamentPanel extends javax.swing.JPanel { } }); + lblName.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N + lblName.setText("Name:"); + + lblType.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N + lblType.setText("Type:"); + + lblState.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N + lblState.setText("State:"); + + lblStartTime.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N + lblStartTime.setText("Start time:"); + + lblEndTime.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N + lblEndTime.setText("End time:"); + javax.swing.GroupLayout actionPanelLayout = new javax.swing.GroupLayout(actionPanel); actionPanel.setLayout(actionPanelLayout); actionPanelLayout.setHorizontalGroup( actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(lblName) - .addComponent(lblType)) + .addComponent(lblState) + .addComponent(txtName, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE) + .addComponent(txtTournamentState)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(txtName, javax.swing.GroupLayout.DEFAULT_SIZE, 175, Short.MAX_VALUE) - .addComponent(txtType)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblStartTime) - .addComponent(lblTournamentState)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(txtTournamentState) - .addComponent(txtStartTime, javax.swing.GroupLayout.DEFAULT_SIZE, 203, Short.MAX_VALUE)) - .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblType) + .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, 440, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(actionPanelLayout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(txtEndTime, javax.swing.GroupLayout.PREFERRED_SIZE, 203, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, 47, Short.MAX_VALUE) - .addComponent(btnQuitTournament, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, actionPanelLayout.createSequentialGroup() - .addGap(154, 154, 154) - .addComponent(btnCloseWindow, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblStartTime)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblEndTime) + .addComponent(txtEndTime)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 126, Short.MAX_VALUE) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(btnQuitTournament, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnCloseWindow, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); actionPanelLayout.setVerticalGroup( actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(actionPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblName, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblStartTime) - .addComponent(txtStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnQuitTournament) - .addComponent(txtEndTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblType) - .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnCloseWindow) - .addComponent(lblTournamentState) - .addComponent(txtTournamentState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(actionPanelLayout.createSequentialGroup() + .addGap(7, 7, 7) + .addComponent(lblName)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, actionPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(lblType))) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(actionPanelLayout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnQuitTournament)) + .addGap(13, 13, 13) + .addComponent(btnCloseWindow)) + .addGroup(actionPanelLayout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblState) + .addComponent(lblStartTime) + .addComponent(lblEndTime)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(actionPanelLayout.createSequentialGroup() + .addComponent(txtTournamentState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtStartTime) + .addComponent(txtEndTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))) + .addContainerGap()) ); + jSplitPane2.setBackground(java.awt.SystemColor.controlHighlight); jSplitPane2.setResizeWeight(1.0); jSplitPane2.setToolTipText(""); @@ -407,6 +462,8 @@ public class TournamentPanel extends javax.swing.JPanel { jSplitPane1.setBottomComponent(jScrollPane2); jSplitPane2.setLeftComponent(jSplitPane1); + + chatPanel1.setStartMessageDone(true); jSplitPane2.setRightComponent(chatPanel1); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); @@ -421,7 +478,8 @@ public class TournamentPanel extends javax.swing.JPanel { .addGroup(layout.createSequentialGroup() .addComponent(actionPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 511, Short.MAX_VALUE)) + .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 454, Short.MAX_VALUE) + .addContainerGap()) ); }// //GEN-END:initComponents @@ -436,6 +494,10 @@ public class TournamentPanel extends javax.swing.JPanel { }//GEN-LAST:event_btnQuitTournamentActionPerformed + private void txtNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtNameActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_txtNameActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel actionPanel; @@ -446,9 +508,10 @@ public class TournamentPanel extends javax.swing.JPanel { private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JSplitPane jSplitPane2; + private javax.swing.JLabel lblEndTime; private javax.swing.JLabel lblName; private javax.swing.JLabel lblStartTime; - private javax.swing.JLabel lblTournamentState; + private javax.swing.JLabel lblState; private javax.swing.JLabel lblType; private javax.swing.JTable tableMatches; private javax.swing.JTable tablePlayers; diff --git a/Mage.Common/src/mage/view/TournamentView.java b/Mage.Common/src/mage/view/TournamentView.java index 27d471ca214..4332df9b575 100644 --- a/Mage.Common/src/mage/view/TournamentView.java +++ b/Mage.Common/src/mage/view/TournamentView.java @@ -50,7 +50,9 @@ public class TournamentView implements Serializable { private final Date startTime; private final Date endTime; - + private final Date stepStartTime; + private final Date serverTime; + private final int constructionTime; private final boolean watchingAllowed; private final List rounds = new ArrayList<>(); @@ -60,10 +62,14 @@ public class TournamentView implements Serializable { public TournamentView(Tournament tournament) { tournamentName = tournament.getOptions().getName(); - tournamentType = tournament.getOptions().getTournamentType(); + + tournamentType = new StringBuilder(tournament.getOptions().getTournamentType()).append(" ").append(tournament.getNumberRounds()).append(" rounds").toString(); startTime = tournament.getStartTime(); endTime = tournament.getEndTime(); + stepStartTime = tournament.getStepStartTime(); + constructionTime = tournament.getOptions().getLimitedOptions().getConstructionTime(); watchingAllowed = tournament.getOptions().isWatchingAllowed(); + serverTime = new Date(); tournamentState = tournament.getTournamentState(); for (TournamentPlayer player: tournament.getPlayers()) { @@ -109,5 +115,17 @@ public class TournamentView implements Serializable { public String getTournamentState() { return tournamentState; } + + public Date getStepStartTime() { + return stepStartTime; + } + + public int getConstructionTime() { + return constructionTime; + } + + public Date getServerTime() { + return serverTime; + } } From 473c9e207bef26327d7bcf9b53c3a32f5efd180f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 1 May 2014 19:34:52 +0200 Subject: [PATCH 06/15] Fixed (probably) the player1 concedes but other player2 wins. Fixed that if player runs out of timer time or player lose of beeing idle, the match will end correctly. --- .../client/dialog/NewTournamentDialog.java | 17 ++-- Mage.Common/src/mage/interfaces/Action.java | 1 + .../src/mage/utils/timer/PriorityTimer.java | 16 ++-- Mage.Common/src/mage/view/MatchView.java | 16 ++-- Mage.Common/src/mage/view/TableView.java | 1 - .../src/mage/view/TournamentGameView.java | 2 +- .../src/mage/player/ai/ComputerPlayer6.java | 8 +- .../src/mage/player/ai/ComputerPlayer7.java | 10 +-- .../mage/player/ai/GameStateEvaluator2.java | 2 +- .../player/ai/simulators/ActionSimulator.java | 8 +- .../src/mage/player/ai/MCTSNode.java | 19 ++--- .../src/mage/player/ai/ComputerPlayer2.java | 8 +- .../src/mage/player/ai/ComputerPlayer3.java | 12 +-- .../mage/player/ai/GameStateEvaluator.java | 2 +- .../java/mage/server/TableController.java | 10 +-- .../java/mage/server/game/GameController.java | 6 +- Mage/src/mage/constants/TableState.java | 2 +- Mage/src/mage/game/Game.java | 5 +- Mage/src/mage/game/GameImpl.java | 78 +++++++++++++++---- Mage/src/mage/game/Table.java | 6 +- Mage/src/mage/game/combat/Combat.java | 4 +- Mage/src/mage/game/match/Match.java | 3 +- Mage/src/mage/game/match/MatchImpl.java | 47 +++++++---- Mage/src/mage/game/match/MatchPlayer.java | 24 +++++- Mage/src/mage/game/tournament/Round.java | 2 +- Mage/src/mage/game/tournament/Tournament.java | 4 + .../mage/game/tournament/TournamentImpl.java | 21 ++++- .../game/tournament/TournamentPairing.java | 2 +- Mage/src/mage/game/turn/Phase.java | 20 ++--- Mage/src/mage/game/turn/Turn.java | 8 +- Mage/src/mage/players/Player.java | 4 + Mage/src/mage/players/PlayerImpl.java | 50 +++++++++++- 32 files changed, 286 insertions(+), 132 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 5a54960e658..b0c645f25f0 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -71,10 +71,12 @@ public class NewTournamentDialog extends MageDialog { private TableView table; private UUID playerId; private UUID roomId; - private Session session; + private final Session session; private String lastSessionId; private final List players = new ArrayList<>(); private final List packs = new ArrayList<>(); + private final int CONSTRUCTION_TIME_MIN = 6; + private final int CONSTRUCTION_TIME_MAX = 30; /** Creates new form NewTournamentDialog */ public NewTournamentDialog() { @@ -84,7 +86,7 @@ public class NewTournamentDialog extends MageDialog { txtName.setText("Tournament"); this.spnNumWins.setModel(new SpinnerNumberModel(2, 1, 5, 1)); this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1)); - this.spnConstructTime.setModel(new SpinnerNumberModel(10, 10, 30, 5)); + this.spnConstructTime.setModel(new SpinnerNumberModel(10, CONSTRUCTION_TIME_MIN, CONSTRUCTION_TIME_MAX, 2)); this.spnNumRounds.setModel(new SpinnerNumberModel(2, 2, 10, 1)); } @@ -427,9 +429,8 @@ public class NewTournamentDialog extends MageDialog { if (tournamentType.isLimited()) { if (tOptions.getLimitedOptions() == null) { tOptions.setLimitedOptions(new LimitedOptions()); - } - tOptions.getLimitedOptions().setConstructionTime(60); - // tOptions.getLimitedOptions().setConstructionTime((Integer)this.spnConstructTime.getValue() * 60); + } + tOptions.getLimitedOptions().setConstructionTime((Integer)this.spnConstructTime.getValue() * 60); if (tournamentType.isCubeBooster()) { tOptions.getLimitedOptions().setDraftCubeName(this.cbDraftCube.getSelectedItem().toString()); } else { @@ -646,7 +647,11 @@ public class NewTournamentDialog extends MageDialog { break; } } - this.spnConstructTime.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_CONSTR_TIME, "600"))/60); + int constructionTime = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_CONSTR_TIME, "600")) / 60; + if (constructionTime < CONSTRUCTION_TIME_MIN || constructionTime > CONSTRUCTION_TIME_MAX) { + constructionTime = CONSTRUCTION_TIME_MIN; + } + this.spnConstructTime.setValue(constructionTime); String tournamentTypeName = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_TYPE, "Sealed Elimination"); for (TournamentTypeView tournamentTypeView : session.getTournamentTypes()) { if (tournamentTypeView.getName().equals(tournamentTypeName)) { diff --git a/Mage.Common/src/mage/interfaces/Action.java b/Mage.Common/src/mage/interfaces/Action.java index 7ab3bca44ef..d7fc3fbe89c 100644 --- a/Mage.Common/src/mage/interfaces/Action.java +++ b/Mage.Common/src/mage/interfaces/Action.java @@ -12,6 +12,7 @@ public interface Action { /** * Executes action. + * @throws mage.MageException */ void execute() throws MageException; } diff --git a/Mage.Common/src/mage/utils/timer/PriorityTimer.java b/Mage.Common/src/mage/utils/timer/PriorityTimer.java index 73c0d9ff72b..31dd52276f0 100644 --- a/Mage.Common/src/mage/utils/timer/PriorityTimer.java +++ b/Mage.Common/src/mage/utils/timer/PriorityTimer.java @@ -1,11 +1,10 @@ package mage.utils.timer; -import mage.MageException; -import mage.interfaces.Action; -import org.apache.log4j.Logger; - import java.util.Timer; import java.util.TimerTask; +import mage.MageException; +import mage.interfaces.Action; +import org.apache.log4j.Logger; /** * @author noxx @@ -14,14 +13,11 @@ public class PriorityTimer extends TimerTask { private static final Logger logger = Logger.getLogger(PriorityTimer.class); + private final long delay; + private final Action taskOnTimeout; + private int count; - - private long delay; - - private Action taskOnTimeout; - private Action taskOnTick; - private States state = States.NONE; enum States { diff --git a/Mage.Common/src/mage/view/MatchView.java b/Mage.Common/src/mage/view/MatchView.java index 86bd43c2bbf..5bb8f0fca5d 100644 --- a/Mage.Common/src/mage/view/MatchView.java +++ b/Mage.Common/src/mage/view/MatchView.java @@ -72,14 +72,18 @@ public class MatchView implements Serializable { } StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(); - for (MatchPlayer player: match.getPlayers()) { - sb1.append(player.getName()); - if(player.hasQuit()) { - sb1.append(" [quit] "); + for (MatchPlayer matchPlayer: match.getPlayers()) { + sb1.append(matchPlayer.getName()); + if(matchPlayer.hasQuit()) { + if (matchPlayer.hasTimerTimeout()) { + sb1.append(" [timer] "); + } else { + sb1.append(" [quit] "); + } } sb1.append(", "); - sb2.append(player.getName()).append(" "); - sb2.append(player.getWins()).append("-").append(player.getLoses()).append(", "); + sb2.append(matchPlayer.getName()).append(" "); + sb2.append(matchPlayer.getWins()).append("-").append(matchPlayer.getLoses()).append(", "); } players = sb1.substring(0, sb1.length() - 2); result = sb2.substring(0, sb2.length() - 2); diff --git a/Mage.Common/src/mage/view/TableView.java b/Mage.Common/src/mage/view/TableView.java index 6c52f6332fe..86a814a2b3d 100644 --- a/Mage.Common/src/mage/view/TableView.java +++ b/Mage.Common/src/mage/view/TableView.java @@ -39,7 +39,6 @@ import mage.game.Seat; import mage.game.Table; import mage.game.match.MatchPlayer; import mage.game.tournament.TournamentPlayer; -import org.jboss.logging.Logger; /** * diff --git a/Mage.Common/src/mage/view/TournamentGameView.java b/Mage.Common/src/mage/view/TournamentGameView.java index 201771e75ed..2ec4a74aa44 100644 --- a/Mage.Common/src/mage/view/TournamentGameView.java +++ b/Mage.Common/src/mage/view/TournamentGameView.java @@ -54,7 +54,7 @@ public class TournamentGameView implements Serializable { this.matchId = pair.getMatch().getId(); this.gameId = game.getId(); this.players = pair.getPlayer1().getPlayer().getName() + " - " + pair.getPlayer2().getPlayer().getName(); - if (game.isGameOver()) { + if (game.hasEnded()) { this.state = "Finished"; this.result = game.getWinner(); } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index ce79182fe1d..29d0ee54491 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -467,7 +467,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements logger.trace("interrupted - " + val); return val; } - if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.isGameOver()) { + if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.gameOver(null)) { logger.trace("Add actions -- reached end state, node count=" + SimulationNode2.nodeCount + ", depth=" + depth); val = GameStateEvaluator2.evaluate(playerId, game); UUID currentPlayerId = node.getGame().getPlayerList().get(); @@ -488,7 +488,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements } } - if (game.isGameOver()) { + if (game.gameOver(null)) { val = GameStateEvaluator2.evaluate(playerId, game); } else if (node.getChildren().size() > 0) { //declared attackers or blockers or triggered abilities @@ -534,7 +534,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements logger.debug("Sim Prio [" + depth + "] -- repeated action: " + action.toString()); continue; } - if (!sim.isGameOver() && action.isUsesStack()) { + if (!sim.gameOver(null) && action.isUsesStack()) { // only pass if the last action uses the stack sim.getPlayer(currentPlayer.getId()).pass(game); sim.getPlayerList().getNext(); @@ -797,7 +797,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements break; case CLEANUP: game.getPhase().getStep().beginStep(game, activePlayerId); - if (!game.checkStateAndTriggered() && !game.isGameOver()) { + if (!game.checkStateAndTriggered() && !game.gameOver(null)) { game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext()); game.getTurn().setPhase(new BeginningPhase()); game.getPhase().setStep(new UntapStep()); diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java index 8252532655e..ad485a9e62e 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java @@ -229,7 +229,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { return GameStateEvaluator2.evaluate(playerId, game); } // Condition to stop deeper simulation - if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.isGameOver()) { + if (depth <= 0 || SimulationNode2.nodeCount > maxNodes || game.gameOver(null)) { val = GameStateEvaluator2.evaluate(playerId, game); if (logger.isTraceEnabled()) { StringBuilder sb = new StringBuilder("Add Actions -- reached end state <").append(val).append(">"); @@ -265,7 +265,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { } } - if (game.isGameOver()) { + if (game.gameOver(null)) { val = GameStateEvaluator2.evaluate(playerId, game); } else if (stepFinished) { @@ -494,7 +494,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); Combat simCombat = sim.getCombat().copy(); finishCombat(sim); - if (sim.isGameOver()) { + if (sim.gameOver(null)) { val = GameStateEvaluator2.evaluate(playerId, sim); } else if (!counter) { @@ -568,7 +568,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { logger.debug("interrupted"); return; } - if (!game.isGameOver()) { + if (!game.gameOver(null)) { game.getPhase().setStep(step); if (!step.skipStep(game, game.getActivePlayerId())) { step.beginStep(game, game.getActivePlayerId()); @@ -617,7 +617,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 { logger.debug("interrupted"); return; } - if (!game.isGameOver()) { + if (!game.gameOver(null)) { game.getTurn().getPhase().endPhase(game, game.getActivePlayerId()); game.getTurn().setPhase(new EndPhase()); if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) { diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java index 27a1abbd813..52b99359a6e 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java @@ -33,7 +33,7 @@ public class GameStateEvaluator2 { public static int evaluate(UUID playerId, Game game) { Player player = game.getPlayer(playerId); Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next()); - if (game.isGameOver()) { + if (game.gameOver(null)) { if (player.hasLost() || opponent.hasWon()) { return LOSE_GAME_SCORE; } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java index 27438f7cbca..54368cc841d 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java @@ -60,11 +60,13 @@ public class ActionSimulator { public int evaluateState() { Player opponent = game.getPlayer(game.getOpponents(player.getId()).iterator().next()); - if (game.isGameOver()) { - if (player.hasLost() || opponent.hasWon()) + if (game.gameOver(null)) { + if (player.hasLost() || opponent.hasWon()) { return Integer.MIN_VALUE; - if (opponent.hasLost() || player.hasWon()) + } + if (opponent.hasLost() || player.hasWon()) { return Integer.MAX_VALUE; + } } int value = player.getLife(); value -= opponent.getLife(); diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java index 5ac55f69c82..3705b35e611 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java @@ -58,11 +58,11 @@ public class MCTSNode { private int visits = 0; private int wins = 0; private MCTSNode parent; - private List children = new ArrayList(); + private final List children = new ArrayList(); private Ability action; private Game game; private Combat combat; - private String stateValue; + private final String stateValue; private UUID playerId; private boolean terminal = false; @@ -71,7 +71,7 @@ public class MCTSNode { public MCTSNode(Game game) { this.game = game; this.stateValue = game.getState().getValue(false, game); - this.terminal = game.isGameOver(); + this.terminal = game.gameOver(null); setPlayer(); nodeCount = 1; } @@ -79,7 +79,7 @@ public class MCTSNode { protected MCTSNode(MCTSNode parent, Game game, Ability action) { this.game = game; this.stateValue = game.getState().getValue(false, game); - this.terminal = game.isGameOver(); + this.terminal = game.gameOver(null); this.parent = parent; this.action = action; setPlayer(); @@ -90,20 +90,21 @@ public class MCTSNode { this.game = game; this.combat = combat; this.stateValue = game.getState().getValue(false, game); - this.terminal = game.isGameOver(); + this.terminal = game.gameOver(null); this.parent = parent; setPlayer(); nodeCount++; } private void setPlayer() { - if (game.getStep().getStepPart() == StepPart.PRIORITY) + if (game.getStep().getStepPart() == StepPart.PRIORITY) { playerId = game.getPriorityPlayerId(); - else { - if (game.getStep().getType() == PhaseStep.DECLARE_BLOCKERS) + } else { + if (game.getStep().getType() == PhaseStep.DECLARE_BLOCKERS) { playerId = game.getCombat().getDefenders().iterator().next(); - else + } else { playerId = game.getActivePlayerId(); + } } } diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java index 881130ca1fb..bbdafd26c2c 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java @@ -330,7 +330,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements return GameStateEvaluator.evaluate(playerId, game); } int val; - if (node.depth > maxDepth || game.isGameOver()) { + if (node.depth > maxDepth || game.gameOver(null)) { logger.debug(indent(node.depth) + "simulating -- reached end state"); val = GameStateEvaluator.evaluate(playerId, game); } @@ -357,7 +357,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements } } - if (game.isGameOver()) { + if (game.gameOver(null)) { val = GameStateEvaluator.evaluate(playerId, game); } else if (node.getChildren().size() > 0) { @@ -403,7 +403,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements logger.debug(indent(node.depth) + "found useless action: " + action); continue; } - if (!sim.isGameOver() && action.isUsesStack()) { + if (!sim.gameOver(null) && action.isUsesStack()) { // only pass if the last action uses the stack sim.getPlayer(currentPlayer.getId()).pass(game); sim.getPlayerList().getNext(); @@ -587,7 +587,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements break; case CLEANUP: game.getPhase().getStep().beginStep(game, activePlayerId); - if (!game.checkStateAndTriggered() && !game.isGameOver()) { + if (!game.checkStateAndTriggered() && !game.gameOver(null)) { game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext()); game.getTurn().setPhase(new BeginningPhase()); game.getPhase().setStep(new UntapStep()); diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java index ee3e42d2610..2046f080050 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java @@ -185,7 +185,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { logger.debug(indent(node.depth) + "interrupted"); return GameStateEvaluator.evaluate(playerId, game); } - if (node.depth > maxDepth || game.isGameOver()) { + if (node.depth > maxDepth || game.gameOver(null)) { logger.debug(indent(node.depth) + "simulating -- reached end state"); val = GameStateEvaluator.evaluate(playerId, game); } @@ -205,7 +205,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { } } - if (game.isGameOver()) { + if (game.gameOver(null)) { val = GameStateEvaluator.evaluate(playerId, game); } else if (stepFinished) { @@ -406,7 +406,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, sim.getActivePlayerId(), sim.getActivePlayerId())); Combat simCombat = sim.getCombat().copy(); finishCombat(sim); - if (sim.isGameOver()) { + if (sim.gameOver(null)) { val = GameStateEvaluator.evaluate(playerId, sim); } else if (!counter) { @@ -448,7 +448,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { return GameStateEvaluator.evaluate(playerId, game); } Integer val = null; - if (!game.isGameOver()) { + if (!game.gameOver(null)) { logger.debug(indent(node.depth) + "simulating -- ending turn"); simulateToEnd(game); game.getState().setActivePlayerId(game.getState().getPlayerList(game.getActivePlayerId()).getNext()); @@ -476,7 +476,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { logger.debug("interrupted"); return; } - if (!game.isGameOver()) { + if (!game.gameOver(null)) { game.getPhase().setStep(step); if (!step.skipStep(game, game.getActivePlayerId())) { step.beginStep(game, game.getActivePlayerId()); @@ -524,7 +524,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player { logger.debug("interrupted"); return; } - if (!game.isGameOver()) { + if (!game.gameOver(null)) { game.getTurn().getPhase().endPhase(game, game.getActivePlayerId()); game.getTurn().setPhase(new EndPhase()); if (game.getTurn().getPhase().beginPhase(game, game.getActivePlayerId())) { diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java index 88c590ba20e..920b00d2520 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java @@ -70,7 +70,7 @@ public class GameStateEvaluator { public static int evaluate(UUID playerId, Game game, boolean ignoreTapped) { Player player = game.getPlayer(playerId); Player opponent = game.getPlayer(game.getOpponents(playerId).iterator().next()); - if (game.isGameOver()) { + if (game.gameOver(null)) { if (player.hasLost() || opponent.hasWon()) return LOSE_SCORE; if (opponent.hasLost() || player.hasWon()) diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 99faf99cf4f..7008d093364 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -593,7 +593,6 @@ public class TableController { * @return true if table can be closed */ public boolean endGameAndStartNextGame() { - boolean matchIsOver = false; // get player that chooses who goes first UUID choosingPlayerId = match.getChooser(); match.endGame(); @@ -604,27 +603,24 @@ public class TableController { } GameManager.getInstance().removeGame(match.getGame().getId()); try { - if (!match.isMatchOver()) { + if (!match.hasEnded()) { table.sideboard(); setupTimeout(Match.SIDEBOARD_TIME); match.sideboard(); cancelTimeout(); - if (!match.isMatchOver()) { + if (!match.hasEnded()) { startGame(choosingPlayerId); } else { - matchIsOver = true; closeTable(); } } else { - // if match has only one game - matchIsOver = true; closeTable(); } } catch (GameException ex) { logger.fatal(null, ex); } - return matchIsOver; + return match.hasEnded(); } /** 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 d924e8a39ab..dcbbd1bdf34 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -240,8 +240,8 @@ public class GameController implements GameCallback { PriorityTimer timer = new PriorityTimer(count, delay, new Action() { @Override public void execute() throws MageException { - game.concede(initPlayerId); - logger.debug("Game timeout for player: " + initPlayerId + ". Conceding."); + game.timerTimeout(initPlayerId); + logger.debug(new StringBuilder("Game timeout for player: ").append(initPlayerId).append(". Conceding.")); } }); timers.put(playerId, timer); @@ -399,7 +399,7 @@ public class GameController implements GameCallback { .append(ConfigSettings.getInstance().getMaxSecondsIdle()) .append(" seconds ) - Auto concede."); ChatManager.getInstance().broadcast(chatId, "", sb.toString() , MessageColor.BLACK, true, MessageType.STATUS); - concede(userId); + game.idleTimeout(getPlayerId(userId)); } } diff --git a/Mage/src/mage/constants/TableState.java b/Mage/src/mage/constants/TableState.java index 3d8a21bf6d2..2c0e45bb5e7 100644 --- a/Mage/src/mage/constants/TableState.java +++ b/Mage/src/mage/constants/TableState.java @@ -13,7 +13,7 @@ public enum TableState { CONSTRUCTING ("Constructing"), FINISHED ("Finished"); - private String text; + private final String text; TableState(String text) { this.text = text; diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 55fd6455d46..9a4b052c1f1 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -122,7 +122,8 @@ public interface Game extends MageItem, Serializable { UUID getActivePlayerId(); UUID getPriorityPlayerId(); void leave(UUID playerId); - boolean isGameOver(); + boolean gameOver(UUID playerId); + boolean hasEnded(); Battlefield getBattlefield(); SpellStack getStack(); Exile getExile(); @@ -218,6 +219,8 @@ public interface Game extends MageItem, Serializable { void mulligan(UUID playerId); void endMulligan(UUID playerId); void quit(UUID playerId); + void timerTimeout(UUID playerId); + void idleTimeout(UUID playerId); void concede(UUID playerId); void undo(UUID playerId); void emptyManaPools(); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 129962b0335..ef68f7e4695 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -418,8 +418,26 @@ public abstract class GameImpl> implements Game, Serializa } } + /** + * Starts check if game over or if playerId is given + * let the player concede. + * + * @param playerId + * @return + */ @Override - public synchronized boolean isGameOver() { + public synchronized boolean gameOver(UUID playerId) { + if (playerId == null) { + boolean result = checkIfGameIsOver(); + return result; + } else { + leave(playerId); + return true; + } + } + + + private boolean checkIfGameIsOver() { if (state.isGameOver()) { return true; } @@ -447,6 +465,11 @@ public abstract class GameImpl> implements Game, Serializa return false; } + @Override + public boolean hasEnded() { + return endTime != null; + } + @Override public String getWinner() { if (winnerId == null) { @@ -546,13 +569,13 @@ public abstract class GameImpl> implements Game, Serializa Player player = getPlayer(players.get()); boolean wasPaused = state.isPaused(); state.resume(); - if (!isGameOver()) { + if (!gameOver(null)) { fireInformEvent(new StringBuilder("Turn ").append(state.getTurnNum()).toString()); if (checkStopOnTurnOption()) { return; } state.getTurn().resumePlay(this, wasPaused); - if (!isPaused() && !isGameOver()) { + if (!isPaused() && !gameOver(null)) { endOfTurn(); player = players.getNext(this); state.setTurnNum(state.getTurnNum() + 1); @@ -562,10 +585,10 @@ public abstract class GameImpl> implements Game, Serializa } protected void play(UUID nextPlayerId) { - if (!isPaused() && !isGameOver()) { + if (!isPaused() && !gameOver(null)) { PlayerList players = state.getPlayerList(nextPlayerId); Player player = getPlayer(players.get()); - while (!isPaused() && !isGameOver()) { + while (!isPaused() && !gameOver(null)) { if (!playTurn(player)) { break; @@ -583,7 +606,7 @@ public abstract class GameImpl> implements Game, Serializa player = players.getNext(this); } } - if (isGameOver()) { + if (gameOver(null)) { winnerId = findWinnersAndLosers(); logger.info(new StringBuilder("Game with gameId ").append(this.getId()).append(" ended.")); } @@ -597,7 +620,7 @@ public abstract class GameImpl> implements Game, Serializa state.setActivePlayerId(player.getId()); player.becomesActivePlayer(); state.getTurn().play(this, player.getId()); - if (isPaused() || isGameOver()) { + if (isPaused() || gameOver(null)) { return false; } endOfTurn(); @@ -865,9 +888,30 @@ public abstract class GameImpl> implements Game, Serializa @Override public synchronized void quit(UUID playerId) { Player player = state.getPlayer(playerId); - if (player != null) { - fireInformEvent(player.getName() + " quits the match."); + if (player != null) { player.quit(this); + }else { + logger.error(new StringBuilder("player not found - playerId: ").append(playerId)); + } + } + + @Override + public synchronized void timerTimeout(UUID playerId) { + Player player = state.getPlayer(playerId); + if (player != null) { + player.timerTimeout(this); + } else { + logger.error(new StringBuilder("player not found - playerId: ").append(playerId)); + } + } + + @Override + public synchronized void idleTimeout(UUID playerId) { + Player player = state.getPlayer(playerId); + if (player != null) { + player.idleTimeout(this); + } else { + logger.error(new StringBuilder("player not found - playerId: ").append(playerId)); } } @@ -923,7 +967,7 @@ public abstract class GameImpl> implements Game, Serializa int bookmark = 0; clearAllBookmarks(); try { - while (!isPaused() && !isGameOver()) { + while (!isPaused() && !gameOver(null)) { if (!resuming) { state.getPlayers().resetPassed(); state.getPlayerList().setCurrent(activePlayerId); @@ -933,13 +977,13 @@ public abstract class GameImpl> implements Game, Serializa } fireUpdatePlayersEvent(); Player player; - while (!isPaused() && !isGameOver()) { + while (!isPaused() && !gameOver(null)) { try { //if (bookmark == 0) //bookmark = bookmarkState(); player = getPlayer(state.getPlayerList().get()); state.setPriorityPlayerId(player.getId()); - while (!player.isPassed() && player.isInGame() && !isPaused() && !isGameOver()) { + while (!player.isPassed() && player.isInGame() && !isPaused() && !gameOver(null)) { if (!resuming) { if (checkStateAndTriggered()) { applyEffects(); @@ -947,7 +991,7 @@ public abstract class GameImpl> implements Game, Serializa //resetLKI(); applyEffects(); saveState(false); - if (isPaused() || isGameOver()) { + if (isPaused() || gameOver(null)) { return; } // resetPassed should be called if player performs any action @@ -962,7 +1006,7 @@ public abstract class GameImpl> implements Game, Serializa } resetShortLivingLKI(); resuming = false; - if (isPaused() || isGameOver()) { + if (isPaused() || gameOver(null)) { return; } if (allPassed()) { @@ -1164,9 +1208,9 @@ public abstract class GameImpl> implements Game, Serializa public boolean checkStateAndTriggered() { boolean somethingHappened = false; //20091005 - 115.5 - while (!isPaused() && !this.isGameOver()) { + while (!isPaused() && !gameOver(null)) { if (!checkStateBasedActions() ) { - if (isPaused() || this.isGameOver() || !checkTriggered()) { + if (isPaused() || gameOver(null) || !checkTriggered()) { break; } } @@ -1729,7 +1773,7 @@ public abstract class GameImpl> implements Game, Serializa return; } player.leave(); - if (this.isGameOver()) { + if (gameOver(null)) { // no need to remove objects if only one player is left so the game is over return; } diff --git a/Mage/src/mage/game/Table.java b/Mage/src/mage/game/Table.java index e6dabdbb89c..4aa4490122f 100644 --- a/Mage/src/mage/game/Table.java +++ b/Mage/src/mage/game/Table.java @@ -112,8 +112,8 @@ public class Table implements Serializable { } public void initTournament() { - setState(TableState.DUELING); - + setState(TableState.DUELING); + tournament.setStepStartTime(new Date()); } public void endTournament() { @@ -122,10 +122,12 @@ public class Table implements Serializable { public void initDraft() { setState(TableState.DRAFTING); + tournament.setStepStartTime(new Date()); } public void construct() { setState(TableState.CONSTRUCTING); + tournament.setStepStartTime(new Date()); } /** diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java index fa41efc01c7..b5624938e84 100644 --- a/Mage/src/mage/game/combat/Combat.java +++ b/Mage/src/mage/game/combat/Combat.java @@ -191,7 +191,7 @@ public class Combat implements Serializable, Copyable { //20101001 - 508.1d checkAttackRequirements(player, game); player.selectAttackers(game, attackerId); - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return; } checkAttackRestrictions(player, game); @@ -316,7 +316,7 @@ public class Combat implements Serializable, Copyable { } while (choose) { blockController.selectBlockers(game, defenderId); - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return; } if (!this.checkBlockRestrictions(defender, game)) { diff --git a/Mage/src/mage/game/match/Match.java b/Mage/src/mage/game/match/Match.java index 2e5493c895e..a9917638dea 100644 --- a/Mage/src/mage/game/match/Match.java +++ b/Mage/src/mage/game/match/Match.java @@ -48,7 +48,8 @@ public interface Match { UUID getId(); String getName(); - boolean isMatchOver(); + boolean hasEnded(); + boolean checkIfMatchEnds(); List getPlayers(); MatchPlayer getPlayer(UUID playerId); diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java index cc95c095062..b4caf5e9b85 100644 --- a/Mage/src/mage/game/match/MatchImpl.java +++ b/Mage/src/mage/game/match/MatchImpl.java @@ -126,20 +126,31 @@ public abstract class MatchImpl implements Match { } @Override - public boolean isMatchOver() { + public boolean hasEnded() { + return endTime != null; + }; + + @Override + public boolean checkIfMatchEnds() { int activePlayers = 0; - for (MatchPlayer player: players) { - if (!player.hasQuit()) { + MatchPlayer matchWinner = null; + for (MatchPlayer matchPlayer: players) { + if (!matchPlayer.hasQuit()) { activePlayers++; + matchWinner = matchPlayer; } - if (player.getWins() >= options.getWinsNeeded()) { + if (matchPlayer.getWins() >= options.getWinsNeeded()) { + matchPlayer.setMatchWinner(true); endTime = new Date(); return true; } } if (activePlayers < 2) { - endTime = new Date(); - return true; + if (matchWinner != null) { + matchWinner.setMatchWinner(true); + } + endTime = new Date(); + return true; } return false; } @@ -200,24 +211,28 @@ public abstract class MatchImpl implements Match { @Override public void endGame() { Game game = getGame(); - for (MatchPlayer player: this.players) { - Player p = game.getPlayer(player.getPlayer().getId()); - if (p != null) { + for (MatchPlayer matchPlayer: this.players) { + Player player = game.getPlayer(matchPlayer.getPlayer().getId()); + if (player != null) { // get the left time from player priority timer if (game.getPriorityTime() > 0) { - player.setPriorityTimeLeft(p.getPriorityTimeLeft()); + matchPlayer.setPriorityTimeLeft(player.getPriorityTimeLeft()); } - if (p.hasQuit()) { - player.setQuit(true); + if (player.hasQuit()) { + matchPlayer.setQuit(true); } - if (p.hasWon()) { - player.addWin(); + if (player.hasTimerTimeout()) { + matchPlayer.setTimerTimeout(true); } - if (p.hasLost()) { - player.addLose(); + if (player.hasWon()) { + matchPlayer.addWin(); + } + if (player.hasLost()) { + matchPlayer.addLose(); } } } + checkIfMatchEnds(); game.fireGameEndInfo(); } diff --git a/Mage/src/mage/game/match/MatchPlayer.java b/Mage/src/mage/game/match/MatchPlayer.java index 01dc95f7ab0..b9a5438227c 100644 --- a/Mage/src/mage/game/match/MatchPlayer.java +++ b/Mage/src/mage/game/match/MatchPlayer.java @@ -39,12 +39,14 @@ import mage.players.Player; public class MatchPlayer { private int wins; private int loses; - + private boolean matchWinner; + private Deck deck; private Player player; private final String name; private boolean quit; + private boolean timerTimeout; private boolean doneSideboarding; private int priorityTimeLeft; @@ -55,7 +57,9 @@ public class MatchPlayer { this.loses = 0; this.doneSideboarding = true; this.quit = false; + this.timerTimeout = false; this.name = player.getName(); + this.matchWinner = false; } public int getPriorityTimeLeft() { @@ -125,7 +129,23 @@ public class MatchPlayer { this.doneSideboarding = true; this.quit = quit; } - + + public boolean hasTimerTimeout() { + return timerTimeout; + } + + public void setTimerTimeout(boolean timerTimeout) { + this.timerTimeout = timerTimeout; + } + + public boolean isMatchWinner() { + return matchWinner; + } + + public void setMatchWinner(boolean matchWinner) { + this.matchWinner = matchWinner; + } + public void cleanUpOnMatchEnd() { // Free resources that are not needed after match end this.deck = null; diff --git a/Mage/src/mage/game/tournament/Round.java b/Mage/src/mage/game/tournament/Round.java index 2b107cde0dc..5f2e5395216 100644 --- a/Mage/src/mage/game/tournament/Round.java +++ b/Mage/src/mage/game/tournament/Round.java @@ -72,7 +72,7 @@ public class Round { public boolean isRoundOver() { boolean roundIsOver = true; for (TournamentPairing pair: pairs) { - if (pair.getMatch() != null && !pair.getMatch().isMatchOver()) { + if (pair.getMatch() != null && !pair.getMatch().hasEnded()) { roundIsOver = false; } else { if (!pair.isAlreadyPublished()) { diff --git a/Mage/src/mage/game/tournament/Tournament.java b/Mage/src/mage/game/tournament/Tournament.java index 84b8438a496..046afbe0a93 100644 --- a/Mage/src/mage/game/tournament/Tournament.java +++ b/Mage/src/mage/game/tournament/Tournament.java @@ -78,6 +78,10 @@ public interface Tournament { // tournament times Date getStartTime(); Date getEndTime(); + + Date getStepStartTime(); + void setStepStartTime(Date date); + // tournament type TournamentType getTournamentType(); void setTournamentType(TournamentType tournamentType); diff --git a/Mage/src/mage/game/tournament/TournamentImpl.java b/Mage/src/mage/game/tournament/TournamentImpl.java index e49d61880bd..26941faa59a 100644 --- a/Mage/src/mage/game/tournament/TournamentImpl.java +++ b/Mage/src/mage/game/tournament/TournamentImpl.java @@ -74,6 +74,7 @@ public abstract class TournamentImpl implements Tournament { protected Date startTime; protected Date endTime; + protected Date stepStartTime; protected boolean abort; protected String tournamentState; @@ -244,7 +245,7 @@ public abstract class TournamentImpl implements Tournament { for (Round round: rounds) { for (TournamentPairing pair: round.getPairs()) { Match match = pair.getMatch(); - if (match != null && match.isMatchOver()) { + if (match != null && match.hasEnded()) { TournamentPlayer tp1 = pair.getPlayer1(); TournamentPlayer tp2 = pair.getPlayer2(); MatchPlayer mp1 = match.getPlayer(pair.getPlayer1().getPlayer().getId()); @@ -302,11 +303,11 @@ public abstract class TournamentImpl implements Tournament { matchResult.append(p2.getPlayer().getName()); matchResult.append(" (").append(mp1.getWins()); if (mp1.hasQuit()) { - matchResult.append("Q"); + matchResult.append(mp1.hasTimerTimeout()?"T":"Q"); } matchResult.append("-").append(mp2.getWins()); if (mp2.hasQuit()) { - matchResult.append("Q"); + matchResult.append(mp2.hasTimerTimeout()?"T":"Q"); } matchResult.append(") "); return matchResult.toString(); @@ -479,4 +480,18 @@ public abstract class TournamentImpl implements Tournament { this.tournamentState = tournamentState; } + @Override + public Date getStepStartTime() { + if (stepStartTime != null) { + return new Date(stepStartTime.getTime()); + } + return null; + } + + @Override + public void setStepStartTime(Date stepStartTime) { + this.stepStartTime = stepStartTime; + } + + } diff --git a/Mage/src/mage/game/tournament/TournamentPairing.java b/Mage/src/mage/game/tournament/TournamentPairing.java index ccdd1f90da6..41abf20b43f 100644 --- a/Mage/src/mage/game/tournament/TournamentPairing.java +++ b/Mage/src/mage/game/tournament/TournamentPairing.java @@ -72,7 +72,7 @@ public class TournamentPairing { } public void eliminatePlayers() { - if (match.isMatchOver()) { + if (match.hasEnded()) { MatchPlayer mPlayer1 = match.getPlayer(player1.getPlayer().getId()); MatchPlayer mPlayer2 = match.getPlayer(player2.getPlayer().getId()); if (mPlayer1.hasQuit() || (!mPlayer2.hasQuit() && mPlayer1.getWins() < match.getWinsNeeded())) { diff --git a/Mage/src/mage/game/turn/Phase.java b/Mage/src/mage/game/turn/Phase.java index 545854fb56e..916351fd83e 100644 --- a/Mage/src/mage/game/turn/Phase.java +++ b/Mage/src/mage/game/turn/Phase.java @@ -95,7 +95,7 @@ public abstract class Phase> implements Serializable { } public boolean play(Game game, UUID activePlayerId) { - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return false; } @@ -104,7 +104,7 @@ public abstract class Phase> implements Serializable { if (beginPhase(game, activePlayerId)) { for (Step step: steps) { - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return false; } currentStep = step; @@ -115,7 +115,7 @@ public abstract class Phase> implements Serializable { playStep(game); } } - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return false; } count++; @@ -136,7 +136,7 @@ public abstract class Phase> implements Serializable { } public boolean resumePlay(Game game, PhaseStep stepType, boolean wasPaused) { - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return false; } @@ -150,7 +150,7 @@ public abstract class Phase> implements Serializable { resumeStep(game, wasPaused); while (it.hasNext()) { step = it.next(); - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return false; } currentStep = step; @@ -159,7 +159,7 @@ public abstract class Phase> implements Serializable { } } - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return false; } count++; @@ -194,10 +194,10 @@ public abstract class Phase> implements Serializable { protected void playStep(Game game) { if (!currentStep.skipStep(game, activePlayerId)) { prePriority(game, activePlayerId); - if (!game.isPaused() && !game.isGameOver()) { + if (!game.isPaused() && !game.gameOver(null)) { currentStep.priority(game, activePlayerId, false); } - if (!game.isPaused() && !game.isGameOver()) { + if (!game.isPaused() && !game.gameOver(null)) { postPriority(game, activePlayerId); } } @@ -219,11 +219,11 @@ public abstract class Phase> implements Serializable { prePriority(game, activePlayerId); } case PRIORITY: - if (!game.isPaused() && !game.isGameOver()) { + if (!game.isPaused() && !game.gameOver(null)) { currentStep.priority(game, activePlayerId, resuming); } case POST: - if (!game.isPaused() && !game.isGameOver()) { + if (!game.isPaused() && !game.gameOver(null)) { postPriority(game, activePlayerId); } } diff --git a/Mage/src/mage/game/turn/Turn.java b/Mage/src/mage/game/turn/Turn.java index 40395bd82e9..b00e44eda62 100644 --- a/Mage/src/mage/game/turn/Turn.java +++ b/Mage/src/mage/game/turn/Turn.java @@ -47,7 +47,7 @@ public class Turn implements Serializable { private Phase currentPhase; private UUID activePlayerId; - private List phases = new ArrayList(); + private final List phases = new ArrayList<>(); private boolean declareAttackersStepStarted = false; public Turn() { @@ -109,7 +109,7 @@ public class Turn implements Serializable { public void play(Game game, UUID activePlayerId) { this.setDeclareAttackersStepStarted(false); - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return; } @@ -123,7 +123,7 @@ public class Turn implements Serializable { resetCounts(); game.getPlayer(activePlayerId).beginTurn(game); for (Phase phase: phases) { - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return; } currentPhase = phase; @@ -168,7 +168,7 @@ public class Turn implements Serializable { } while (it.hasNext()) { phase = it.next(); - if (game.isPaused() || game.isGameOver()) { + if (game.isPaused() || game.gameOver(null)) { return; } currentPhase = phase; diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index ae9f9d5c845..3fd0486aabc 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -129,6 +129,10 @@ public interface Player extends MageItem, Copyable { boolean hasWon(); boolean hasQuit(); void quit(Game game); + boolean hasTimerTimeout(); + void timerTimeout(Game game); + boolean hasIdleTimeout(); + void idleTimeout(Game game); boolean hasLeft(); /** * Player is still active in game (has not left, lost or won the game). diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index dc4cfd8ff1d..c5b5b1698db 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -114,7 +114,10 @@ import mage.target.common.TargetDiscard; import mage.watchers.common.BloodthirstWatcher; import org.apache.log4j.Logger; - +/** + * + * * @param + */ public abstract class PlayerImpl> implements Player, Serializable { private static final transient Logger log = Logger.getLogger(PlayerImpl.class); @@ -160,6 +163,10 @@ public abstract class PlayerImpl> implements Player, Ser protected boolean left; // set if the player quits the complete match protected boolean quit; + // set if the player lost match because of priority timeout + protected boolean timerTimeout; + // set if the player lost match because of idle timeout + protected boolean idleTimeout; protected RangeOfInfluence range; protected Set inRange = new HashSet<>(); @@ -234,6 +241,8 @@ public abstract class PlayerImpl> implements Player, Ser this.left = player.left; this.quit = player.quit; + this.timerTimeout = player.timerTimeout; + this.idleTimeout = player.idleTimeout; this.range = player.range; this.canGainLife = player.canGainLife; this.canLoseLife = player.canLoseLife; @@ -288,6 +297,8 @@ public abstract class PlayerImpl> implements Player, Ser this.left = player.hasLeft(); this.quit = player.hasQuit(); + this.timerTimeout = player.hasTimerTimeout(); + this.idleTimeout = player.hasIdleTimeout(); this.range = player.getRange(); this.canGainLife = player.isCanGainLife(); this.canLoseLife = player.isCanLoseLife(); @@ -343,7 +354,11 @@ public abstract class PlayerImpl> implements Player, Ser this.wins = false; this.loses = false; this.left = false; - this.quit = false; // reset is neccessary because in tournament player will be used for each round + // reset is neccessary because in tournament player will be used for each round + this.quit = false; + this.timerTimeout = false; + this.idleTimeout = false; + this.passed = false; this.passedTurn = false; this.passedAllTurns = false; @@ -732,7 +747,7 @@ public abstract class PlayerImpl> implements Player, Ser resetStoredBookmark(game); return true; } - if (!game.isGameOver()) { // if player left or game is over no undo is possible - this could lead to wrong winner + if (!game.hasEnded()) { // if player left or game is over no undo is possible - this could lead to wrong winner game.restoreState(bookmark); } } @@ -1475,13 +1490,30 @@ public abstract class PlayerImpl> implements Player, Ser @Override public void quit(Game game) { + game.informPlayers(new StringBuilder(getName()).append(" quits the match.").toString()); quit = true; this.concede(game); } + @Override + public void timerTimeout(Game game) { + game.informPlayers(new StringBuilder(getName()).append(" has run out of time. Loosing the Match.").toString()); + quit = true; + timerTimeout = true; + this.concede(game); + } + + @Override + public void idleTimeout(Game game) { + game.informPlayers(new StringBuilder(getName()).append(" has run out of time. Loosing the Match.").toString()); + quit = true; + idleTimeout = true; + this.concede(game); + } + @Override public void concede(Game game) { - game.leave(playerId); + game.gameOver(playerId); lost(game); this.left = true; } @@ -2117,6 +2149,16 @@ public abstract class PlayerImpl> implements Player, Ser return quit; } + @Override + public boolean hasTimerTimeout() { + return timerTimeout; + } + + @Override + public boolean hasIdleTimeout() { + return idleTimeout; + } + @Override public void setReachedNextTurnAfterLeaving(boolean reachedNextTurnAfterLeaving) { this.reachedNextTurnAfterLeaving = reachedNextTurnAfterLeaving; From 13ac2d0103bd975bd47330d7d6a56f32b417fdd9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 2 May 2014 09:32:51 +0200 Subject: [PATCH 07/15] Tournament panel - Showing the number of rounds now only if tournament is swiss style tournament. --- Mage.Common/src/mage/view/TournamentView.java | 6 +++++- Mage/src/mage/game/tournament/TournamentPlayer.java | 7 ------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Mage.Common/src/mage/view/TournamentView.java b/Mage.Common/src/mage/view/TournamentView.java index 4332df9b575..a887d53f7ab 100644 --- a/Mage.Common/src/mage/view/TournamentView.java +++ b/Mage.Common/src/mage/view/TournamentView.java @@ -63,7 +63,11 @@ public class TournamentView implements Serializable { tournamentName = tournament.getOptions().getName(); - tournamentType = new StringBuilder(tournament.getOptions().getTournamentType()).append(" ").append(tournament.getNumberRounds()).append(" rounds").toString(); + if (tournament.getNumberRounds() > 0) { + tournamentType = tournament.getOptions().getTournamentType() + " " + tournament.getNumberRounds()+ " rounds"; + } else { + tournamentType = tournament.getOptions().getTournamentType(); + } startTime = tournament.getStartTime(); endTime = tournament.getEndTime(); stepStartTime = tournament.getStepStartTime(); diff --git a/Mage/src/mage/game/tournament/TournamentPlayer.java b/Mage/src/mage/game/tournament/TournamentPlayer.java index 21838521358..6204fd0be0b 100644 --- a/Mage/src/mage/game/tournament/TournamentPlayer.java +++ b/Mage/src/mage/game/tournament/TournamentPlayer.java @@ -28,15 +28,8 @@ package mage.game.tournament; -import java.util.List; -import java.util.Random; import java.util.Set; -import mage.cards.Card; import mage.cards.decks.Deck; -import mage.cards.repository.CardCriteria; -import mage.cards.repository.CardInfo; -import mage.cards.repository.CardRepository; -import mage.constants.Rarity; import mage.constants.TournamentPlayerState; import mage.players.Player; import mage.util.TournamentUtil; From 21149dc0accd531bf2e8b8e1719b715f3792cb96 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 2 May 2014 09:34:36 +0200 Subject: [PATCH 08/15] * Undo wrongly removed generic Exception hadling, --- .../src/main/java/mage/server/MageServerImpl.java | 4 +--- Mage.Server/src/main/java/mage/server/Main.java | 12 ++---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 227a9dc1a03..6216facb1a0 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -172,9 +172,7 @@ public class MageServerImpl implements MageServer { logger.debug("Tournament table " + table.getTableId() + " created"); LogServiceImpl.instance.log(LogKeys.KEY_TOURNAMENT_TABLE_CREATED, sessionId, userId.toString(), table.getTableId().toString()); return table; - } catch (NumberFormatException ex) { - handleException(ex); - } catch (MageException ex) { + } catch (Exception ex) { handleException(ex); } return null; diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index e32d494d17c..d99dd991938 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -284,11 +284,7 @@ public class Main { return (MatchType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance(); } catch (ClassNotFoundException ex) { logger.warn("Game type not found:" + plugin.getJar() + " - check plugin folder", ex); - } catch (IllegalAccessException ex) { - logger.fatal("Error loading game type " + plugin.getJar(), ex); - } catch (InstantiationException ex) { - logger.fatal("Error loading game type " + plugin.getJar(), ex); - } catch (MalformedURLException ex) { + } catch (Exception ex) { logger.fatal("Error loading game type " + plugin.getJar(), ex); } return null; @@ -301,11 +297,7 @@ public class Main { return (TournamentType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance(); } catch (ClassNotFoundException ex) { logger.warn("Tournament type not found:" + plugin.getName() + " / "+ plugin.getJar() + " - check plugin folder", ex); - } catch (IllegalAccessException ex) { - logger.fatal("Error loading game type " + plugin.getJar(), ex); - } catch (InstantiationException ex) { - logger.fatal("Error loading game type " + plugin.getJar(), ex); - } catch (MalformedURLException ex) { + } catch (Exception ex) { logger.fatal("Error loading game type " + plugin.getJar(), ex); } return null; From 5de03a4165f3d170d0e3401caf0a6bc13337420e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 2 May 2014 09:49:32 +0200 Subject: [PATCH 09/15] Adding the new server log to .gitignore. --- .gitignore | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e1c0d2d44b0..3e4715c9608 100644 --- a/.gitignore +++ b/.gitignore @@ -24,15 +24,17 @@ Mage.Server.Plugins/Mage.Player.AIMCTS/target Mage.Server.Plugins/Mage.Player.Human/target Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target Mage.Server.Plugins/Mage.Tournament.BoosterDraft/target -/Mage.Server.Plugins/Mage.Tournament.Constructed/target +Mage.Server.Plugins/Mage.Tournament.Constructed/target Mage.Server.Plugins/Mage.Tournament.Sealed/target Mage.Server.Plugins/Mage.Player.AI.DraftBot/target +Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/ Mage.Server/config/init.txt Mage.Server/saved Mage.Server/target Mage.Server/db Mage.Server/cache Mage.Server/mageserver.log +Mage.Server/magediag.log Mage.Sets/target Mage.Tests/target Mage.Tests/cache @@ -69,8 +71,8 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target \.rej$ \.conflict\~$ /Mage.Server.Plugins/Mage.Player.AIMCTS/target/ -/Mage.Server.Console/target/ + *.classpath *.iml /submitted -/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/ \ No newline at end of file + From 3b3f136d346cd961d0a124d7214c644fa4db1816 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 2 May 2014 16:45:26 +0200 Subject: [PATCH 10/15] Spells on the stack can now get counters. --- Mage.Common/src/mage/view/CardView.java | 1 - .../src/mage/view/StackAbilityView.java | 10 ++++--- Mage/src/mage/abilities/AbilityImpl.java | 4 +++ Mage/src/mage/constants/MageObjectType.java | 8 ++--- Mage/src/mage/game/stack/Spell.java | 29 ++++++++++++++----- Mage/src/mage/game/stack/SpellStack.java | 7 ++--- 6 files changed, 38 insertions(+), 21 deletions(-) diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 267e2559252..d1e8b55cff9 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -41,7 +41,6 @@ import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.MageObjectType; import mage.constants.Rarity; -import mage.constants.SpellAbilityType; import mage.constants.Zone; import mage.counters.Counter; import mage.counters.CounterType; diff --git a/Mage.Common/src/mage/view/StackAbilityView.java b/Mage.Common/src/mage/view/StackAbilityView.java index 1ebe6c4bb66..deeacb9be92 100644 --- a/Mage.Common/src/mage/view/StackAbilityView.java +++ b/Mage.Common/src/mage/view/StackAbilityView.java @@ -47,7 +47,7 @@ import mage.target.targetpointer.TargetPointer; public class StackAbilityView extends CardView { private static final long serialVersionUID = 1L; - private CardView sourceCard; + private final CardView sourceCard; public StackAbilityView(Game game, StackAbility ability, String sourceName, CardView sourceCard) { this.id = ability.getId(); @@ -55,7 +55,7 @@ public class StackAbilityView extends CardView { this.sourceCard = sourceCard; this.sourceCard.setMageObjectType(mageObjectType); this.name = "Ability"; - this.rules = new ArrayList(); + this.rules = new ArrayList<>(); rules.add(ability.getRule(sourceName)); this.power = ability.getPower().toString(); this.toughness = ability.getToughness().toString(); @@ -65,17 +65,19 @@ public class StackAbilityView extends CardView { this.superTypes = ability.getSupertype(); this.color = ability.getColor(); this.manaCost = ability.getManaCost().getSymbols(); + this.counters = sourceCard.getCounters(); + updateTargets(game, ability); } private void updateTargets(Game game, StackAbility ability) { - List names = new ArrayList(); + List names = new ArrayList<>(); for(UUID modeId : ability.getModes().getSelectedModes()) { ability.getModes().setMode(ability.getModes().get(modeId)); if (ability.getTargets().size() > 0) { setTargets(ability.getTargets()); } else { - List targetList = new ArrayList(); + List targetList = new ArrayList<>(); for (Effect effect : ability.getEffects()) { TargetPointer targetPointer = effect.getTargetPointer(); if (targetPointer instanceof FixedTarget) { diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 2a5d4ac3737..0dc5ed073fb 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -889,6 +889,10 @@ public abstract class AbilityImpl> implements Ability { return sb.toString(); } + public String getTargetDescription(Targets targets, Game game) { + return getTargetDescriptionForLog(targets, game); + } + protected String getTargetDescriptionForLog(Targets targets, Game game) { StringBuilder sb = new StringBuilder(); if (targets.size() > 0) { diff --git a/Mage/src/mage/constants/MageObjectType.java b/Mage/src/mage/constants/MageObjectType.java index 7afa5f33930..05fc18383f9 100644 --- a/Mage/src/mage/constants/MageObjectType.java +++ b/Mage/src/mage/constants/MageObjectType.java @@ -29,14 +29,14 @@ public enum MageObjectType { CARD ("Card", false, true), COPY_CARD ("Copy of a Card", false, true), TOKEN ("Token", true, true), - SPELL ("Spell", false, false), + SPELL ("Spell", false, true), PERMANENT ("Permanent", true, true), EMBLEM ("Emblem", false, false), COMMANDER ("Commander", false, false); - private String text; - private boolean permanent; - private boolean canHaveCounters; + private final String text; + private final boolean permanent; + private final boolean canHaveCounters; MageObjectType(String text, boolean permanent, boolean canHaveCounters) { diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index f3cc359e7c1..af56e853196 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -372,6 +372,7 @@ public class Spell> implements StackObject, Card { public boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget) { Player player = game.getPlayer(playerId); if (player != null) { + StringBuilder newTargetDescription = new StringBuilder(); // Fused split spells or spells where "Splice on Arcane" was used can have more than one ability for (SpellAbility spellAbility : spellAbilities) { // Some spells can have more than one mode @@ -386,9 +387,11 @@ public class Spell> implements StackObject, Card { } } + newTargetDescription.append(getSpellAbility().getTargetDescription(mode.getTargets(), game)); } } + game.informPlayers(this.getName() + " is now " + newTargetDescription.toString()); return true; } return false; @@ -851,26 +854,38 @@ public class Spell> implements StackObject, Card { @Override public Counters getCounters() { - return null; + return card.getCounters(); } @Override - public void addCounters(String name, int amount, Game game) {} + public void addCounters(String name, int amount, Game game) { + card.addCounters(name, amount, game); + } @Override - public void addCounters(String name, int amount, Game game, ArrayList appliedEffects) {} + public void addCounters(String name, int amount, Game game, ArrayList appliedEffects) { + card.addCounters(name, amount, game, appliedEffects); + } @Override - public void addCounters(Counter counter, Game game) {} + public void addCounters(Counter counter, Game game) { + card.addCounters(counter, game); + } @Override - public void addCounters(Counter counter, Game game, ArrayList appliedEffects) {} + public void addCounters(Counter counter, Game game, ArrayList appliedEffects) { + card.addCounters(counter, game, appliedEffects); + } @Override - public void removeCounters(String name, int amount, Game game) {} + public void removeCounters(String name, int amount, Game game) { + card.removeCounters(name, amount, game); + } @Override - public void removeCounters(Counter counter, Game game) {} + public void removeCounters(Counter counter, Game game) { + card.removeCounters(counter, game); + } public Card getCard() { return card; diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index 65538aadd94..3e221ec5def 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -105,13 +105,10 @@ public class SpellStack extends ArrayDeque { public Spell getSpell(UUID id) { for (StackObject stackObject: this) { - if (stackObject.getId().equals(id)) { - if (stackObject instanceof Spell) { + if (stackObject instanceof Spell) { + if (stackObject.getId().equals(id) || stackObject.getSourceId().equals(id)) { return (Spell)stackObject; } - else { - return null; - } } } return null; From 0e327c13f28825b5198c31368b7fa6ffd3fd8da3 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 2 May 2014 16:45:46 +0200 Subject: [PATCH 11/15] Added Lightning Storm. --- .../mage/sets/coldsnap/LightningStorm.java | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/coldsnap/LightningStorm.java diff --git a/Mage.Sets/src/mage/sets/coldsnap/LightningStorm.java b/Mage.Sets/src/mage/sets/coldsnap/LightningStorm.java new file mode 100644 index 00000000000..ca21228424f --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/LightningStorm.java @@ -0,0 +1,150 @@ +/* + * 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.sets.coldsnap; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EmptyEffect; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.counters.common.ChargeCounter; +import mage.filter.common.FilterLandCard; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LevelX2 + */ +public class LightningStorm extends CardImpl { + + public LightningStorm(UUID ownerId) { + super(ownerId, 89, "Lightning Storm", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{R}{R}"); + this.expansionSetCode = "CSP"; + + this.color.setRed(true); + + // Lightning Storm deals X damage to target creature or player, where X is 3 plus the number of charge counters on it. + Effect effect = new DamageTargetEffect(new LightningStormCountCondition(CounterType.CHARGE)); + effect.setText("{this} deals X damage to target creature or player, where X is 3 plus the number of charge counters on it"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer(true)); + // Discard a land card: Put two charge counters on Lightning Storm. You may choose a new target for it. Any player may activate this ability but only if Lightning Storm is on the stack. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.STACK, + new LightningStormAddCounterEffect() , + new DiscardTargetCost(new TargetCardInHand(new FilterLandCard()))); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new EmptyEffect("Any player may activate this ability but only if {this} is on the stack")); + this.addAbility(ability); + } + + public LightningStorm(final LightningStorm card) { + super(card); + } + + @Override + public LightningStorm copy() { + return new LightningStorm(this); + } +} + +class LightningStormCountCondition implements DynamicValue { + private final CounterType counter; + + public LightningStormCountCondition(CounterType counter) { + this.counter = counter; + } + + public LightningStormCountCondition(final LightningStormCountCondition countersCount) { + this.counter = countersCount.counter; + } + + @Override + public int calculate(Game game, Ability sourceAbility) { + Spell spell = game.getStack().getSpell(sourceAbility.getSourceId()); + if (spell != null) { + return spell.getCounters().getCount(counter) + 3; + } + return 0; + } + + @Override + public DynamicValue copy() { + return new LightningStormCountCondition(this); + } + + @Override + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return "3 plus the number of charge counters on it"; + } +} + +class LightningStormAddCounterEffect extends OneShotEffect { + + public LightningStormAddCounterEffect() { + super(Outcome.Benefit); + this.staticText = "Put two charge counters on {this}. You may choose a new target for it."; + } + + public LightningStormAddCounterEffect(final LightningStormAddCounterEffect effect) { + super(effect); + } + + @Override + public LightningStormAddCounterEffect copy() { + return new LightningStormAddCounterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + spell.addCounters(new ChargeCounter(2), game); + return spell.chooseNewTargets(game, source.getControllerId(), false, false); + } + return false; + } +} From 15e3fd906ece4b2753dffc97293be11058606a95 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 2 May 2014 19:14:59 +0200 Subject: [PATCH 12/15] Added Ashling the Pilgrim, Reset and Flash of insight. --- .../mage/sets/judgment/FlashOfInsight.java | 162 ++++++++++++++++++ Mage.Sets/src/mage/sets/legends/Reset.java | 112 ++++++++++++ .../mage/sets/lorwyn/AshlingThePilgrim.java | 136 +++++++++++++++ Mage/src/mage/game/events/GameEvent.java | 2 +- 4 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/sets/judgment/FlashOfInsight.java create mode 100644 Mage.Sets/src/mage/sets/legends/Reset.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/AshlingThePilgrim.java diff --git a/Mage.Sets/src/mage/sets/judgment/FlashOfInsight.java b/Mage.Sets/src/mage/sets/judgment/FlashOfInsight.java new file mode 100644 index 00000000000..de50e9c7a35 --- /dev/null +++ b/Mage.Sets/src/mage/sets/judgment/FlashOfInsight.java @@ -0,0 +1,162 @@ +/* + * 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.sets.judgment; + +import java.util.UUID; +import mage.MageObject; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.costs.common.ExileXFromYourGraveCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TimingRule; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; + +/** + * + * @author LevelX2 + */ +public class FlashOfInsight extends CardImpl { + + private static final FilterCard filter = new FilterCard("blue cards from your graveyard"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + } + + public FlashOfInsight(UUID ownerId) { + super(ownerId, 40, "Flash of Insight", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{X}{1}{U}"); + this.expansionSetCode = "JUD"; + + this.color.setBlue(true); + + // Look at the top X cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order. + this.getSpellAbility().addEffect(new FlashOfInsightEffect()); + // Flashback-{1}{U}, Exile X blue cards from your graveyard. + Ability ability = new FlashbackAbility(new ManaCostsImpl("{1}{U}"), TimingRule.INSTANT); + ability.addCost(new ExileXFromYourGraveCost(filter)); + this.addAbility(ability); + } + + public FlashOfInsight(final FlashOfInsight card) { + super(card); + } + + @Override + public FlashOfInsight copy() { + return new FlashOfInsight(this); + } +} + +class FlashOfInsightEffect extends OneShotEffect { + + public FlashOfInsightEffect() { + super(Outcome.DrawCard); + this.staticText = "Look at the top X cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order"; + } + + public FlashOfInsightEffect(final FlashOfInsightEffect effect) { + super(effect); + } + + @Override + public FlashOfInsightEffect copy() { + return new FlashOfInsightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (player == null || sourceObject == null) { + return false; + } + + int xValue; + xValue = source.getManaCostsToPay().getX(); + + Cards cards = new CardsImpl(Zone.PICK); + int count = Math.min(player.getLibrary().size(), xValue); + for (int i = 0; i < count; i++) { + Card card = player.getLibrary().removeFromTop(game); + if (card != null) { + cards.add(card); + game.setZone(card.getId(), Zone.PICK); + } + } + player.lookAtCards(sourceObject.getName(), cards, game); + + TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put into your hand")); + if (player.choose(Outcome.DrawCard, cards, target, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + card.moveToZone(Zone.HAND, source.getSourceId(), game, false); + game.informPlayers(sourceObject.getName() + ": " + player.getName() + " puts a card into his or her hand"); + } + } + + target = new TargetCard(Zone.PICK, new FilterCard("card to put on the bottom of your library")); + target.setRequired(true); + if (cards.size() > 0) { + game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ") + .append(player.getName()).append(" puts ") + .append(cards.size() == 1 ? "a":cards.size()) + .append(" card").append(cards.size() > 1 ? "s":"") + .append(" on the bottom of his or her library").toString()); + } + while (cards.size() > 1) { + player.choose(Outcome.Neutral, cards, target, game); + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); + } + target.clearChosen(); + } + if (cards.size() == 1) { + Card card = cards.get(cards.iterator().next(), game); + card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); + } + + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/legends/Reset.java b/Mage.Sets/src/mage/sets/legends/Reset.java new file mode 100644 index 00000000000..a127d6082e3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/Reset.java @@ -0,0 +1,112 @@ +/* + * 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.sets.legends; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.UntapAllLandsControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LevelX2 + */ +public class Reset extends CardImpl { + + public Reset(UUID ownerId) { + super(ownerId, 73, "Reset", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{U}{U}"); + this.expansionSetCode = "LEG"; + + this.color.setBlue(true); + + // Cast Reset only during an opponent's turn after his or her upkeep step. + Ability ability = new SimpleStaticAbility(Zone.ALL, new ResetReplacementEffect()); + ability.setRuleAtTheTop(true); + this.addAbility(ability); + // Untap all lands you control. + this.getSpellAbility().addEffect(new UntapAllLandsControllerEffect()); + } + + public Reset(final Reset card) { + super(card); + } + + @Override + public Reset copy() { + return new Reset(this); + } +} + +class ResetReplacementEffect extends ReplacementEffectImpl { + ResetReplacementEffect() { + super(Duration.EndOfGame, Outcome.Detriment); + staticText = "Cast {this} only during an opponent's turn after his or her upkeep step"; + } + + ResetReplacementEffect(final ResetReplacementEffect effect) { + super(effect); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType().equals(GameEvent.EventType.CAST_SPELL) && event.getSourceId().equals(source.getSourceId())) { + if (game.getTurn().getStepType().equals(PhaseStep.UNTAP) + || game.getTurn().getStepType().equals(PhaseStep.UPKEEP) + || !game.getOpponents(source.getControllerId()).contains(game.getActivePlayerId())) { + return true; + } + + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public ResetReplacementEffect copy() { + return new ResetReplacementEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/AshlingThePilgrim.java b/Mage.Sets/src/mage/sets/lorwyn/AshlingThePilgrim.java new file mode 100644 index 00000000000..ab0bebdd393 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/AshlingThePilgrim.java @@ -0,0 +1,136 @@ +/* + * 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.sets.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class AshlingThePilgrim extends CardImpl { + + public AshlingThePilgrim(UUID ownerId) { + super(ownerId, 149, "Ashling the Pilgrim", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{R}"); + this.expansionSetCode = "LRW"; + this.supertype.add("Legendary"); + this.subtype.add("Elemental"); + this.subtype.add("Shaman"); + + this.color.setRed(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{R}: Put a +1/+1 counter on Ashling the Pilgrim. If this is the third time this ability has resolved this turn, remove all +1/+1 counters from Ashling the Pilgrim, and it deals that much damage to each creature and each player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(), true), new ManaCostsImpl("{1}{R}")); + ability.addEffect(new AshlingThePilgrimEffect()); + this.addAbility(ability); + } + + public AshlingThePilgrim(final AshlingThePilgrim card) { + super(card); + } + + @Override + public AshlingThePilgrim copy() { + return new AshlingThePilgrim(this); + } +} + +class AshlingThePilgrimEffect extends OneShotEffect { + + class ActivationInfo { + public int zoneChangeCounter; + public int turn; + public int activations; + } + + public AshlingThePilgrimEffect() { + super(Outcome.Damage); + this.staticText = "If this is the third time this ability has resolved this turn, remove all +1/+1 counters from {this}, and it deals that much damage to each creature and each player"; + } + + public AshlingThePilgrimEffect(final AshlingThePilgrimEffect effect) { + super(effect); + } + + @Override + public AshlingThePilgrimEffect copy() { + return new AshlingThePilgrimEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + ActivationInfo info; + Object object = game.getState().getValue(source.getSourceId() + "ActivationInfo"); + if (object instanceof ActivationInfo) { + info = (ActivationInfo) object; + if (info.turn != game.getTurnNum() || sourcePermanent.getZoneChangeCounter() != info.zoneChangeCounter) { + info.turn = game.getTurnNum(); + info.zoneChangeCounter = sourcePermanent.getZoneChangeCounter(); + info.activations = 0; + } + } else { + info = new ActivationInfo(); + info.turn = game.getTurnNum(); + info.zoneChangeCounter = sourcePermanent.getZoneChangeCounter(); + game.getState().setValue(source.getSourceId() + "ActivationInfo", info); + } + info.activations++; + if (info.activations == 3) { + int damage = sourcePermanent.getCounters().getCount(CounterType.P1P1); + if (damage > 0) { + sourcePermanent.removeCounters(CounterType.P1P1.getName(), damage, game); + return new DamageEverythingEffect(damage, new FilterCreaturePermanent()).apply(game, source); + } + } + return true; + } + return false; + } +} diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 1a0b8c5b055..6a3f02c1a1a 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -46,7 +46,7 @@ public class GameEvent { protected boolean flag; protected String data; protected Zone zone; - protected ArrayList appliedEffects = new ArrayList(); + protected ArrayList appliedEffects = new ArrayList<>(); public enum EventType { From 7318ecb50e1277766e1c5522da760502b5133ddd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 3 May 2014 02:48:24 +0200 Subject: [PATCH 13/15] Tournament handling - small change to check who to eliminate. --- Mage/src/mage/game/tournament/TournamentPairing.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/game/tournament/TournamentPairing.java b/Mage/src/mage/game/tournament/TournamentPairing.java index 41abf20b43f..2eb74ecedfc 100644 --- a/Mage/src/mage/game/tournament/TournamentPairing.java +++ b/Mage/src/mage/game/tournament/TournamentPairing.java @@ -71,14 +71,17 @@ public class TournamentPairing { this.match = match; } + /** + * Called by eliminate tournaments after each match + */ public void eliminatePlayers() { if (match.hasEnded()) { MatchPlayer mPlayer1 = match.getPlayer(player1.getPlayer().getId()); MatchPlayer mPlayer2 = match.getPlayer(player2.getPlayer().getId()); - if (mPlayer1.hasQuit() || (!mPlayer2.hasQuit() && mPlayer1.getWins() < match.getWinsNeeded())) { + if (mPlayer1.hasQuit() || !mPlayer1.isMatchWinner()) { player1.setEliminated(); } - if (mPlayer2.hasQuit() || (!mPlayer1.hasQuit() && mPlayer2.getWins() < match.getWinsNeeded())) { + if (mPlayer2.hasQuit() || !mPlayer2.isMatchWinner()) { player2.setEliminated(); } } From 866c65c49696b4a8b021ef53af799afa54e5a092 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 3 May 2014 02:49:23 +0200 Subject: [PATCH 14/15] Made head line connection info shorter, to have enough space if sreen size is small with new mem info. --- Mage.Common/src/mage/remote/SessionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index ecc7c855a5b..8daecf03783 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -206,7 +206,7 @@ public class SessionImpl implements Session { serverState = server.getServerState(); updateDatabase(); logger.info(new StringBuilder("Connected as ").append(this.getUserName()).append(" to MAGE server at ").append(connection.getHost()).append(":").append(connection.getPort()).toString()); - client.connected(new StringBuilder("Connected as ").append(this.getUserName()).append(" to ").append(connection.getHost()).append(":").append(connection.getPort()).append(" ").toString()); + client.connected(new StringBuilder(this.getUserName()).append("@").append(connection.getHost()).append(":").append(connection.getPort()).append(" ").toString()); return true; } disconnect(false); From f676bd1650edd90eb2254fc6ce0ebfc52b2922a1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 3 May 2014 02:50:51 +0200 Subject: [PATCH 15/15] Increased card repository number for new dev release. --- Mage/src/mage/cards/repository/CardRepository.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Mage/src/mage/cards/repository/CardRepository.java b/Mage/src/mage/cards/repository/CardRepository.java index cb8bad16b91..3951e19e699 100644 --- a/Mage/src/mage/cards/repository/CardRepository.java +++ b/Mage/src/mage/cards/repository/CardRepository.java @@ -35,12 +35,15 @@ import com.j256.ormlite.stmt.SelectArg; import com.j256.ormlite.stmt.Where; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; -import mage.constants.CardType; - import java.io.File; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.Callable; +import mage.constants.CardType; /** * @@ -52,7 +55,7 @@ public enum CardRepository { private static final String JDBC_URL = "jdbc:sqlite:db/cards.db"; private static final String VERSION_ENTITY_NAME = "card"; - private static final long CARD_DB_VERSION = 30; + private static final long CARD_DB_VERSION = 31; private final Random random = new Random(); private Dao cardDao;