From e8cfb2231c54829e714e5851cfe4850325e586c4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 28 Aug 2014 13:32:44 +0200 Subject: [PATCH] Some minor changes. --- .gitignore | 3 +- Mage.Common/src/mage/remote/SessionImpl.java | 31 +++++++ .../src/main/java/mage/server/Main.java | 2 +- .../cards/abilities/lose/LoseAbilityTest.java | 9 ++ .../test/combat/FlyersCantBeBlockedTest.java | 87 +++++++++++++++++++ .../mage/abilities/TriggeredAbilityImpl.java | 1 + .../abilities/keyword/FlashbackAbility.java | 12 ++- 7 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/combat/FlyersCantBeBlockedTest.java diff --git a/.gitignore b/.gitignore index 5ba6afc6be..ca422bd18c 100644 --- a/.gitignore +++ b/.gitignore @@ -77,4 +77,5 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target *.iml /submitted -/Mage.Server/config/ai.please.cast.this.txt \ No newline at end of file +/Mage.Server/config/ai.please.cast.this.txt +/Mage.Stats/target/ \ No newline at end of file diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index e58d710b85..8431eb554e 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -136,6 +136,18 @@ public class SessionImpl implements Session { InvokerLocator clientLocator = new InvokerLocator(connection.getURI()); Map metadata = new HashMap<>(); + /* + 5.8.3.1.1. Write timeouts + The socket timeout facility offered by the JDK applies only to read operations on the socket. As of release 2.5.2, + the socket and bisocket (and also sslsocket and sslbisocket) transports offer a write timeout facility. When a client + or server is configured, in any of the usual ways, with the parameter org.jboss.remoting.transport.socket.SocketWrapper.WRITE_TIMEOUT + (actual value "writeTimeout") set to a positive value (in milliseconds), all write operations will time out if they do + not complete within the configured period. When a write operation times out, the socket upon which the write was invoked + will be closed, which is likely to result in a java.net.SocketException. + Note. A SocketException is considered to be a "retriable" exception, so, if the parameter "numberOfCallRetries" is set + to a value greater than 1, an invocation interrupted by a write timeout can be retried. + Note. The write timeout facility applies to writing of both invocations and responses. It applies to push callbacks as well. + */ metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000"); metadata.put("generalizeSocketException", "true"); server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata); @@ -159,6 +171,25 @@ public class SessionImpl implements Session { * the server, and on the server side an org.jboss.remoting.Lease informs registered listeners * if the PING doesn't arrive withing the specified timeout period. */ clientMetadata.put(Client.ENABLE_LEASE, "true"); + /* + When the socket client invoker makes its first invocation, it will check to see if there is an available + socket connection in its pool. Since is the first invocation, there will not be and will create a new socket + connection and use it for making the invocation. Then when finished making invocation, will return the still + active socket connection to the pool. As more client invocations are made, is possible for the number of + socket connections to reach the maximum allowed (which is controlled by 'clientMaxPoolSize' property). At this + point, when the next client invocation is made, it will wait up to some configured number of milliseconds, at + which point it will throw an org.jboss.remoting.CannotConnectException. The number of milliseconds is given by + the parameter MicroSocketClientInvoker.CONNECTION_WAIT (actual value "connectionWait"), with a default of + 30000 milliseconds. Note that if more than one call retry is configured (see next paragraph), + the CannotConnectException will be swallowed. + Once the socket client invoker get an available socket connection from the pool, are not out of the woods yet. + For example, a network problem could cause a java.net.SocketException. There is also a possibility that the socket + connection, while still appearing to be valid, has "gone stale" while sitting in the pool. For example, a ServerThread + on the other side of the connection could time out and close its socket. If the attempt to complete an invocation + fails, then MicroSocketClientInvoker will make a number of attempts, according to the parameter "numberOfCallRetries", + with a default value of 3. Once the configured number of retries has been exhausted, + an org.jboss.remoting.InvocationFailureException will be thrown. + */ clientMetadata.put("numberOfCallRetries", "1"); // Indicated the max number of threads used within oneway thread pool. diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 3209f263ae..094deee1f1 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -171,7 +171,7 @@ public class Main { } static boolean isAlreadyRunning(InvokerLocator serverLocator) { - Map metadata = new HashMap(); + Map metadata = new HashMap<>(); metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000"); metadata.put("generalizeSocketException", "true"); try { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/lose/LoseAbilityTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/lose/LoseAbilityTest.java index bca4c5b550..cd5a799c34 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/lose/LoseAbilityTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/lose/LoseAbilityTest.java @@ -97,12 +97,20 @@ public class LoseAbilityTest extends CardTestPlayerBase { // should NOT have flying Assert.assertFalse(airElemental.getAbilities().contains(FlyingAbility.getInstance())); } + /** * Tests that gaining two times a triggered ability and losing one will result in only one triggering */ @Test public void testMultiGainTriggeredVsLoseAbility() { addCard(Zone.BATTLEFIELD, playerA, "Sublime Archangel",2); + /* + * Sublime Archangel English + * Creature — Angel 4/3, 2WW + * Flying + * Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.) + * Other creatures you control have exalted. (If a creature has multiple instances of exalted, each triggers separately.) + */ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); addCard(Zone.BATTLEFIELD, playerA, "Island", 3); @@ -110,6 +118,7 @@ public class LoseAbilityTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Island", 5); castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Turn to Frog", "Sublime Archangel"); + attack(3, playerA, "Silvercoat Lion"); setStopAt(3, PhaseStep.END_COMBAT); diff --git a/Mage.Tests/src/test/java/org/mage/test/combat/FlyersCantBeBlockedTest.java b/Mage.Tests/src/test/java/org/mage/test/combat/FlyersCantBeBlockedTest.java new file mode 100644 index 0000000000..48860f7ae0 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/combat/FlyersCantBeBlockedTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package org.mage.test.combat; + +import junit.framework.Assert; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * Test that flyers can't be blocked if blocker has no flying and no reach ability + * + * @author LevelX2 + */ +public class FlyersCantBeBlockedTest extends CardTestPlayerBase { + + @Test + public void testFlyingVsNonFlying() { + addCard(Zone.BATTLEFIELD, playerA, "Necropede"); + addCard(Zone.BATTLEFIELD, playerB, "Pilgrim's Eye"); + addCard(Zone.HAND, playerB, "Pilgrim's Eye",2); + addCard(Zone.LIBRARY, playerB, "Pilgrim's Eye",2); + + attack(2, playerB, "Pilgrim's Eye"); + block(2, playerA, "Necropede", "Pilgrim's Eye"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 19); + assertLife(playerB, 20); + + Permanent pilgrimsEye = getPermanent("Pilgrim's Eye", playerB.getId()); + Assert.assertTrue("Should be tapped because of attacking", pilgrimsEye.isTapped()); + } + + @Test + public void testFlyingVsNonFlying2() { + addCard(Zone.BATTLEFIELD, playerA, "Necropede"); + addCard(Zone.BATTLEFIELD, playerB, "Pilgrim's Eye"); + addCard(Zone.LIBRARY, playerA, "Pilgrim's Eye"); + addCard(Zone.HAND, playerA, "Pilgrim's Eye"); + addCard(Zone.GRAVEYARD, playerA, "Pilgrim's Eye"); + + attack(2, playerB, "Pilgrim's Eye"); + block(2, playerA, "Necropede", "Pilgrim's Eye"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 19); + assertLife(playerB, 20); + + Permanent pilgrimsEye = getPermanent("Pilgrim's Eye", playerB.getId()); + Assert.assertTrue("Should be tapped because of attacking", pilgrimsEye.isTapped()); + } + + +} diff --git a/Mage/src/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/mage/abilities/TriggeredAbilityImpl.java index 1e0b1054e5..2cf4ac746e 100644 --- a/Mage/src/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/mage/abilities/TriggeredAbilityImpl.java @@ -157,6 +157,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge return sourceObject; } + @Override public void setSourceObject(MageObject sourceObject) { this.sourceObject = sourceObject; } diff --git a/Mage/src/mage/abilities/keyword/FlashbackAbility.java b/Mage/src/mage/abilities/keyword/FlashbackAbility.java index 49488cc43a..7618b11aae 100644 --- a/Mage/src/mage/abilities/keyword/FlashbackAbility.java +++ b/Mage/src/mage/abilities/keyword/FlashbackAbility.java @@ -47,9 +47,17 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.players.Player; -import mage.target.Target; /** + * 702.32. Flashback + * + * 702.32a. Flashback appears on some instants and sorceries. It represents two static abilities: + * one that functions while the card is in a player‘s graveyard and the other that functions + * while the card is on the stack. Flashback [cost] means, "You may cast this card from your + * graveyard by paying [cost] rather than paying its mana cost" and, "If the flashback cost + * was paid, exile this card instead of putting it anywhere else any time it would leave the + * stack." Casting a spell using its flashback ability follows the rules for paying alternative + * costs in rules 601.2b and 601.2e–g. * * @author nantuko */ @@ -235,4 +243,4 @@ class FlashbackTriggeredAbility extends DelayedTriggeredAbility { return "(If the flashback cost was paid, exile this card instead of putting it anywhere else any time it would leave the stack)"; } -} \ No newline at end of file +}