From 4232a3b7f13428e5c62b8cc3cf73c19ea9246bd7 Mon Sep 17 00:00:00 2001
From: LevelX2 <ludwig.hirth@online.de>
Date: Sun, 16 Mar 2014 10:05:20 +0100
Subject: [PATCH] Fixed the "can only block flying creatures effect" (e.g.
 Varporkin). It was implemented as replacement effect instead of  restriction
 effect which leads to dead locks in combat if it was forced to block a non
 flyer.

---
 .../mage/sets/avacynrestored/Gloomwidow.java  | 10 +--
 .../sets/avacynrestored/ScrapskinDrake.java   | 13 ++-
 .../sets/darkascension/StormboundGeist.java   | 11 +--
 .../mage/sets/magic2012/SkywinderDrake.java   | 13 ++-
 .../src/mage/sets/tenth/CloudElemental.java   | 11 ++-
 .../src/mage/sets/tenth/CloudSprite.java      | 13 ++-
 Mage.Sets/src/mage/sets/theros/Vaporkin.java  |  6 +-
 .../src/mage/sets/zendikar/WelkinTern.java    | 11 ++-
 .../common/CanBlockOnlyFlyingAbility.java     | 46 +++++++++++
 .../combat/CanBlockOnlyFlyingEffect.java      | 82 -------------------
 .../common/combat/CantBlockAllEffect.java     |  4 +-
 Mage/src/mage/players/PlayerImpl.java         |  4 +
 12 files changed, 89 insertions(+), 135 deletions(-)
 create mode 100644 Mage/src/mage/abilities/common/CanBlockOnlyFlyingAbility.java
 delete mode 100644 Mage/src/mage/abilities/effects/common/combat/CanBlockOnlyFlyingEffect.java

diff --git a/Mage.Sets/src/mage/sets/avacynrestored/Gloomwidow.java b/Mage.Sets/src/mage/sets/avacynrestored/Gloomwidow.java
index 6fc8e73e48..9e00cbca09 100644
--- a/Mage.Sets/src/mage/sets/avacynrestored/Gloomwidow.java
+++ b/Mage.Sets/src/mage/sets/avacynrestored/Gloomwidow.java
@@ -28,14 +28,12 @@
 package mage.sets.avacynrestored;
 
 import java.util.UUID;
-import mage.constants.CardType;
-import mage.constants.Rarity;
-import mage.constants.Zone;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.ReachAbility;
 import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  *
@@ -54,7 +52,7 @@ public class Gloomwidow extends CardImpl<Gloomwidow> {
 
         this.addAbility(ReachAbility.getInstance());
         // Gloomwidow can block only creatures with flying.
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+        this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public Gloomwidow(final Gloomwidow card) {
diff --git a/Mage.Sets/src/mage/sets/avacynrestored/ScrapskinDrake.java b/Mage.Sets/src/mage/sets/avacynrestored/ScrapskinDrake.java
index f981e35596..124ca5449d 100644
--- a/Mage.Sets/src/mage/sets/avacynrestored/ScrapskinDrake.java
+++ b/Mage.Sets/src/mage/sets/avacynrestored/ScrapskinDrake.java
@@ -27,16 +27,13 @@
  */
 package mage.sets.avacynrestored;
 
-import mage.constants.CardType;
-import mage.constants.Rarity;
+import java.util.UUID;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.cards.CardImpl;
-import mage.constants.Zone;
-
-import java.util.UUID;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  *
@@ -58,7 +55,7 @@ public class ScrapskinDrake extends CardImpl<ScrapskinDrake> {
         this.addAbility(FlyingAbility.getInstance());
 
         // Scrapskin Drake can block only creatures with flying.
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+        this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public ScrapskinDrake(final ScrapskinDrake card) {
diff --git a/Mage.Sets/src/mage/sets/darkascension/StormboundGeist.java b/Mage.Sets/src/mage/sets/darkascension/StormboundGeist.java
index 54a474d24d..72bc3b36e0 100644
--- a/Mage.Sets/src/mage/sets/darkascension/StormboundGeist.java
+++ b/Mage.Sets/src/mage/sets/darkascension/StormboundGeist.java
@@ -28,16 +28,13 @@
 package mage.sets.darkascension;
 
 import java.util.UUID;
-
-import mage.constants.CardType;
-import mage.constants.Rarity;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.abilities.keyword.UndyingAbility;
 import mage.cards.CardImpl;
-import mage.constants.Zone;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  * @author Loki
@@ -55,7 +52,7 @@ public class StormboundGeist extends CardImpl<StormboundGeist> {
 
         this.addAbility(FlyingAbility.getInstance());
         // Stormbound Geist can block only creatures with flying.
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+        this.addAbility(new CanBlockOnlyFlyingAbility());
         // Undying
         this.addAbility(new UndyingAbility());
     }
diff --git a/Mage.Sets/src/mage/sets/magic2012/SkywinderDrake.java b/Mage.Sets/src/mage/sets/magic2012/SkywinderDrake.java
index cf5e931ef2..eeecabead0 100644
--- a/Mage.Sets/src/mage/sets/magic2012/SkywinderDrake.java
+++ b/Mage.Sets/src/mage/sets/magic2012/SkywinderDrake.java
@@ -1,4 +1,4 @@
-/*
+                        /*
  *  Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without modification, are
@@ -28,14 +28,12 @@
 package mage.sets.magic2012;
 
 import java.util.UUID;
-import mage.constants.CardType;
-import mage.constants.Rarity;
-import mage.constants.Zone;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  *
@@ -53,7 +51,8 @@ public class SkywinderDrake extends CardImpl<SkywinderDrake> {
         this.toughness = new MageInt(1);
 
         this.addAbility(FlyingAbility.getInstance());
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+        // Skywinder Drake can block only creatures with flying.
+        this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public SkywinderDrake(final SkywinderDrake card) {
diff --git a/Mage.Sets/src/mage/sets/tenth/CloudElemental.java b/Mage.Sets/src/mage/sets/tenth/CloudElemental.java
index 26e88d2c07..c59d206d31 100644
--- a/Mage.Sets/src/mage/sets/tenth/CloudElemental.java
+++ b/Mage.Sets/src/mage/sets/tenth/CloudElemental.java
@@ -28,14 +28,12 @@
 package mage.sets.tenth;
 
 import java.util.UUID;
-import mage.constants.CardType;
-import mage.constants.Rarity;
-import mage.constants.Zone;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  *
@@ -53,7 +51,8 @@ public class CloudElemental extends CardImpl<CloudElemental> {
         this.toughness = new MageInt(3);
 
         this.addAbility(FlyingAbility.getInstance());
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+        // Cloud Elemental can block only creatures with flying.
+        this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public CloudElemental(final CloudElemental card) {
diff --git a/Mage.Sets/src/mage/sets/tenth/CloudSprite.java b/Mage.Sets/src/mage/sets/tenth/CloudSprite.java
index 93e0357fa3..87f2911544 100644
--- a/Mage.Sets/src/mage/sets/tenth/CloudSprite.java
+++ b/Mage.Sets/src/mage/sets/tenth/CloudSprite.java
@@ -28,15 +28,12 @@
 package mage.sets.tenth;
 
 import java.util.UUID;
-
-import mage.constants.CardType;
-import mage.constants.Rarity;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.cards.CardImpl;
-import mage.constants.Zone;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  *
@@ -52,7 +49,9 @@ public class CloudSprite extends CardImpl<CloudSprite> {
         this.power = new MageInt(1);
         this.toughness = new MageInt(1);
         this.addAbility(FlyingAbility.getInstance());
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+
+        // Cloud Sprite can block only creatures with flying.
+        this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public CloudSprite(final CloudSprite card) {
diff --git a/Mage.Sets/src/mage/sets/theros/Vaporkin.java b/Mage.Sets/src/mage/sets/theros/Vaporkin.java
index dde4497c0d..6e2dffd0a0 100644
--- a/Mage.Sets/src/mage/sets/theros/Vaporkin.java
+++ b/Mage.Sets/src/mage/sets/theros/Vaporkin.java
@@ -29,13 +29,11 @@ package mage.sets.theros;
 
 import java.util.UUID;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.cards.CardImpl;
 import mage.constants.CardType;
 import mage.constants.Rarity;
-import mage.constants.Zone;
 
 /**
  *
@@ -55,7 +53,7 @@ public class Vaporkin extends CardImpl<Vaporkin> {
         // Flying
         this.addAbility(FlyingAbility.getInstance());
         // Vaporkin can block only creatures with flying.
-         this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+         this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public Vaporkin(final Vaporkin card) {
diff --git a/Mage.Sets/src/mage/sets/zendikar/WelkinTern.java b/Mage.Sets/src/mage/sets/zendikar/WelkinTern.java
index 1b6801d697..16f13edff7 100644
--- a/Mage.Sets/src/mage/sets/zendikar/WelkinTern.java
+++ b/Mage.Sets/src/mage/sets/zendikar/WelkinTern.java
@@ -29,14 +29,12 @@
 package mage.sets.zendikar;
 
 import java.util.UUID;
-import mage.constants.CardType;
-import mage.constants.Rarity;
-import mage.constants.Zone;
 import mage.MageInt;
-import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.combat.CanBlockOnlyFlyingEffect;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
 import mage.abilities.keyword.FlyingAbility;
 import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
 
 /**
  *
@@ -54,7 +52,8 @@ public class WelkinTern extends CardImpl<WelkinTern> {
         this.toughness = new MageInt( 1);
 
         this.addAbility(FlyingAbility.getInstance());
-        this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingEffect()));
+        // Welkin Tern can block only creatures with flying.
+         this.addAbility(new CanBlockOnlyFlyingAbility());
     }
 
     public WelkinTern (final WelkinTern card) {
diff --git a/Mage/src/mage/abilities/common/CanBlockOnlyFlyingAbility.java b/Mage/src/mage/abilities/common/CanBlockOnlyFlyingAbility.java
new file mode 100644
index 0000000000..aaeb261838
--- /dev/null
+++ b/Mage/src/mage/abilities/common/CanBlockOnlyFlyingAbility.java
@@ -0,0 +1,46 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package mage.abilities.common;
+
+import mage.abilities.effects.common.combat.CantBlockAllEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.constants.Duration;
+import mage.constants.Zone;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+
+/**
+ *
+ * @author LevelX2
+ */
+
+public class CanBlockOnlyFlyingAbility extends SimpleStaticAbility {
+
+    private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with flying");
+
+    static {
+        filter.add(new AbilityPredicate(FlyingAbility.class));
+    }
+
+    public CanBlockOnlyFlyingAbility() {
+        super(Zone.BATTLEFIELD, new CantBlockAllEffect(filter, Duration.WhileOnBattlefield));
+    }
+
+    private CanBlockOnlyFlyingAbility(CanBlockOnlyFlyingAbility ability) {
+        super(ability);
+    }
+
+    @Override
+    public String getRule() {
+        return "{this} can block only creatures with flying.";
+    }
+
+    @Override
+    public CanBlockOnlyFlyingAbility copy() {
+        return new CanBlockOnlyFlyingAbility(this);
+    }
+}
diff --git a/Mage/src/mage/abilities/effects/common/combat/CanBlockOnlyFlyingEffect.java b/Mage/src/mage/abilities/effects/common/combat/CanBlockOnlyFlyingEffect.java
deleted file mode 100644
index 9639a900e2..0000000000
--- a/Mage/src/mage/abilities/effects/common/combat/CanBlockOnlyFlyingEffect.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  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.abilities.effects.common.combat;
-
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.abilities.Ability;
-import mage.abilities.MageSingleton;
-import mage.abilities.effects.ReplacementEffectImpl;
-import mage.abilities.keyword.FlyingAbility;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
-import mage.game.permanent.Permanent;
-
-/**
- *
- * @author North
- */
-public class CanBlockOnlyFlyingEffect extends ReplacementEffectImpl<CanBlockOnlyFlyingEffect> implements MageSingleton {
-
-    public CanBlockOnlyFlyingEffect() {
-        super(Duration.WhileOnBattlefield, Outcome.Detriment);
-        staticText = "{this} can block only creatures with flying";
-    }
-
-    public CanBlockOnlyFlyingEffect(final CanBlockOnlyFlyingEffect effect) {
-        super(effect);
-    }
-
-    @Override
-    public CanBlockOnlyFlyingEffect copy() {
-        return new CanBlockOnlyFlyingEffect(this);
-    }
-
-    @Override
-    public boolean apply(Game game, Ability source) {
-        return true;
-    }
-
-    @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() == EventType.DECLARE_BLOCKER && source.getSourceId().equals(event.getSourceId())) {
-            Permanent permanent = game.getPermanent(event.getTargetId());
-            if (permanent != null && !permanent.getAbilities().containsKey(FlyingAbility.getInstance().getId())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
diff --git a/Mage/src/mage/abilities/effects/common/combat/CantBlockAllEffect.java b/Mage/src/mage/abilities/effects/common/combat/CantBlockAllEffect.java
index 84f30f0fc8..cc4d3269b3 100644
--- a/Mage/src/mage/abilities/effects/common/combat/CantBlockAllEffect.java
+++ b/Mage/src/mage/abilities/effects/common/combat/CantBlockAllEffect.java
@@ -27,10 +27,10 @@
  */
 package mage.abilities.effects.common.combat;
 
-import mage.constants.Duration;
 import mage.abilities.Ability;
 import mage.abilities.Mode;
 import mage.abilities.effects.RestrictionEffect;
+import mage.constants.Duration;
 import mage.filter.common.FilterCreaturePermanent;
 import mage.game.Game;
 import mage.game.permanent.Permanent;
@@ -41,7 +41,7 @@ import mage.game.permanent.Permanent;
  */
 public class CantBlockAllEffect extends RestrictionEffect<CantBlockAllEffect> {
 
-    private FilterCreaturePermanent filter;
+    private final FilterCreaturePermanent filter;
 
     public CantBlockAllEffect(FilterCreaturePermanent filter, Duration duration) {
         super(duration);
diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java
index 9f49f78025..97db95c684 100644
--- a/Mage/src/mage/players/PlayerImpl.java
+++ b/Mage/src/mage/players/PlayerImpl.java
@@ -1585,6 +1585,10 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
         if (blocker != null && group != null && group.canBlock(blocker, game)) {
             group.addBlocker(blockerId, playerId, game);
             game.getCombat().addBlockingGroup(blockerId, attackerId, playerId, game);
+        } else {
+            if (this.isHuman()) {
+                game.informPlayer(this, "You can't block this creature.");
+            }
         }
     }