diff --git a/Mage.Client/serverlist.txt b/Mage.Client/serverlist.txt
index 1a756c1784..021697d81e 100644
--- a/Mage.Client/serverlist.txt
+++ b/Mage.Client/serverlist.txt
@@ -1,6 +1,7 @@
-woogerworks   (North America):xmage.woogerworks.com:17171
-XMage.info 1  (Europe)       :176.31.186.181:17171
-XMage.info 2  (Europe)       :176.31.186.181:17000
-Seedds Server (Asia)         :115.29.203.80:17171
-Felipejoys    (Brazil)       :felipejoys.no-ip.org:17171
+woogerworks   (North America/USA)       :xmage.woogerworks.com:17171
+XMage.info 1  (Europe/France)       :176.31.186.181:17171
+XMage.info 2  (Europe/France)       :176.31.186.181:17000
+IceMage       (Europe/Netherlands)  :ring0.cc:17171
+Seedds Server (Asia)                :115.29.203.80:17171
+Felipejoys    (South America/Brazil):felipejoys.no-ip.org:17171
 localhost -> connect to your local server (must be started):localhost:17171
diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java
index c737e45ca7..56959a416d 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java
@@ -387,7 +387,7 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player {
                 newPlayer.getLibrary().shuffle();
                 for (int i = 0; i < handSize; i++) {
                     Card card = newPlayer.getLibrary().removeFromTop(mcts);
-                    mcts.setZone(card.getId(), Zone.HAND);
+                    card.setZone(Zone.HAND, mcts);
                     newPlayer.getHand().add(card);
                 }
             }
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 b3e2a16e49..bebd0914a7 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
@@ -328,7 +328,7 @@ public class MCTSNode {
                 player.getLibrary().shuffle();
                 for (int i = 0; i < handSize; i++) {
                     Card card = player.getLibrary().removeFromTop(game);
-                    game.setZone(card.getId(), Zone.HAND);
+                    card.setZone(Zone.HAND, game);
                     player.getHand().add(card);
                 }
             }
diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
index e8bef838cf..2f89506bef 100644
--- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
+++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
@@ -96,7 +96,7 @@ public class SystemUtil {
                     }
 
                     Random random = new Random();
-                    Set<Card> cardsToLoad = new HashSet<Card>();
+                    Set<Card> cardsToLoad = new HashSet<>();
                     for (int i = 0; i < amount; i++) {
                         CardInfo cardInfo = cards.get(random.nextInt(cards.size()));
                         Card card = cardInfo != null ? cardInfo.getCard() : null;
@@ -128,7 +128,7 @@ public class SystemUtil {
         if (zone.equals(Zone.BATTLEFIELD)) {
             card.putOntoBattlefield(game, Zone.OUTSIDE, null, player.getId());
         } else if (zone.equals(Zone.LIBRARY)) {
-            game.setZone(card.getId(), Zone.LIBRARY);
+            card.setZone(Zone.LIBRARY, game);
             player.getLibrary().putOnTop(card, game);
         } else {
             card.moveToZone(zone, null, game, false);
diff --git a/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java b/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java
index fd7a757370..09411bfbfe 100644
--- a/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java
+++ b/Mage.Sets/src/mage/sets/worldwake/JaceTheMindSculptor.java
@@ -195,15 +195,15 @@ class JaceTheMindSculptorEffect3 extends OneShotEffect {
     @Override
     public boolean apply(Game game, Ability source) {
         Player player = game.getPlayer(source.getFirstTarget());
-        ExileZone exile = game.getExile().getPermanentExile();
         if (player != null) {
             while (true) {
                 if (player.getLibrary().getFromTop(game) == null) {
                     break;
                 }
                 Card card = player.getLibrary().removeFromTop(game);
-                exile.add(card);
-                game.setZone(card.getId(), Zone.EXILED);
+                if (card != null) {
+                    card.moveToExile(null, "", source.getSourceId(), game);
+                }
             }
             for (Card card : player.getHand().getCards(game)) {
                 card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
diff --git a/Mage/src/mage/abilities/effects/AuraReplacementEffect.java b/Mage/src/mage/abilities/effects/AuraReplacementEffect.java
index 99602f9073..6d21bb6276 100644
--- a/Mage/src/mage/abilities/effects/AuraReplacementEffect.java
+++ b/Mage/src/mage/abilities/effects/AuraReplacementEffect.java
@@ -152,7 +152,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
 
             PermanentCard permanent = new PermanentCard(card, card.getOwnerId());
             game.getBattlefield().addPermanent(permanent);
-            game.setZone(card.getId(), Zone.BATTLEFIELD);
+            card.setZone(Zone.BATTLEFIELD, game);
             game.applyEffects();
             permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
             game.applyEffects();
diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java
index e91f5ed8d1..006601129a 100644
--- a/Mage/src/mage/cards/Card.java
+++ b/Mage/src/mage/cards/Card.java
@@ -140,4 +140,12 @@ public interface Card extends MageObject {
 
     @Override
     Card copy();
+    
+    /**
+     *
+     * @return The main card of a split half card, otherwise thae card itself is returned
+     */
+    Card getMainCard();
+
+    void setZone(Zone zone, Game game);
 }
diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java
index aada14c563..03c9e90684 100644
--- a/Mage/src/mage/cards/CardImpl.java
+++ b/Mage/src/mage/cards/CardImpl.java
@@ -419,38 +419,39 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
 
     @Override
     public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
-        ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ability.getId(), controllerId, fromZone, Zone.STACK);
+        Card mainCard = getMainCard();
+        ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
         if (!game.replaceEvent(event)) {
             if (event.getFromZone() != null) {
                 switch (event.getFromZone()) {
                     case GRAVEYARD:
-                        game.getPlayer(ownerId).removeFromGraveyard(this, game);
+                        game.getPlayer(ownerId).removeFromGraveyard(mainCard, game);
                         break;
                     case HAND:
-                        game.getPlayer(ownerId).removeFromHand(this, game);
+                        game.getPlayer(ownerId).removeFromHand(mainCard, game);
                         break;
                     case LIBRARY:
-                        game.getPlayer(ownerId).removeFromLibrary(this, game);
+                        game.getPlayer(ownerId).removeFromLibrary(mainCard, game);
                         break;
                     case EXILED:
-                        game.getExile().removeCard(this, game);
+                        game.getExile().removeCard(mainCard, game);
                         break;
                     case OUTSIDE:
-                        game.getPlayer(ownerId).getSideboard().remove(this);
+                        game.getPlayer(ownerId).getSideboard().remove(mainCard);
                         break;
                         
                     case COMMAND:
-                        game.getState().getCommand().remove((Commander)game.getObject(objectId));
+                        game.getState().getCommand().remove((Commander)game.getObject(mainCard.getId()));
                         break;
                     default:
                         //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone());
                 }
-                game.rememberLKI(objectId, event.getFromZone(), this);
+                game.rememberLKI(mainCard.getId(), event.getFromZone(), this);
             }
             game.getStack().push(new Spell(this, ability.copy(), controllerId, event.getFromZone()));
-            game.setZone(objectId, event.getToZone());
+            setZone(event.getToZone(), game);
             game.fireEvent(event);
-            return game.getState().getZone(objectId) == Zone.STACK;
+            return game.getState().getZone(mainCard.getId()) == Zone.STACK;
         }
         return false;
     }
@@ -557,7 +558,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
             // make sure the controller of all continuous effects of this card are switched to the current controller
             game.getContinuousEffects().setController(objectId, event.getPlayerId());
             game.addPermanent(permanent);
-            game.setZone(objectId, Zone.BATTLEFIELD);
+            setZone(Zone.BATTLEFIELD, game);
             game.setScopeRelevant(true);
             permanent.setTapped(tapped);
             permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
@@ -777,4 +778,14 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
         }
         return name;
     }
+
+    @Override
+    public Card getMainCard() {
+        return this;
+    }
+
+    @Override
+    public void setZone(Zone zone, Game game) {
+        game.setZone(getId(), zone);
+    }
 }
diff --git a/Mage/src/mage/cards/SplitCard.java b/Mage/src/mage/cards/SplitCard.java
index bbff7f6e07..cce2b36ac0 100644
--- a/Mage/src/mage/cards/SplitCard.java
+++ b/Mage/src/mage/cards/SplitCard.java
@@ -31,15 +31,16 @@ package mage.cards;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
-
-import mage.constants.CardType;
-import mage.constants.Rarity;
-import mage.constants.SpellAbilityType;
-import mage.constants.Zone;
 import mage.abilities.Abilities;
 import mage.abilities.AbilitiesImpl;
 import mage.abilities.Ability;
 import mage.abilities.SpellAbility;
+import mage.constants.CardType;
+import mage.constants.Rarity;
+import mage.constants.SpellAbilityType;
+import static mage.constants.SpellAbilityType.SPLIT_LEFT;
+import static mage.constants.SpellAbilityType.SPLIT_RIGHT;
+import mage.constants.Zone;
 import mage.game.Game;
 import mage.watchers.Watcher;
 
@@ -90,7 +91,28 @@ public abstract class SplitCard extends CardImpl {
     public Card getRightHalfCard () {
         return rightHalfCard;
     }
-    
+
+    @Override
+    public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
+        if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) {
+            game.getState().setZone(getLeftHalfCard().getId(), toZone);
+            game.getState().setZone(getRightHalfCard().getId(), toZone);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
+        if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) {
+            Zone currentZone = game.getState().getZone(getId());
+            game.getState().setZone(getLeftHalfCard().getId(), currentZone);
+            game.getState().setZone(getRightHalfCard().getId(), currentZone);
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
         switch(ability.getSpellAbilityType()) {
@@ -103,6 +125,14 @@ public abstract class SplitCard extends CardImpl {
         }
     }
 
+    @Override
+    public void setZone(Zone zone, Game game) {
+        super.setZone(zone, game);
+        game.setZone(getLeftHalfCard().getId(), zone);
+        game.setZone(getRightHalfCard().getId(), zone);
+    }
+
+
     @Override
     public Abilities<Ability> getAbilities(){
         Abilities<Ability> allAbilites = new AbilitiesImpl<>();
@@ -198,7 +228,21 @@ class LeftHalfCard  extends CardImpl {
     @Override
     public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
         return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
-    }    
+    }
+
+    @Override
+    public Card getMainCard() {
+        return splitCardParent;
+    }
+
+    @Override
+    public void setZone(Zone zone, Game game) {
+        super.setZone(zone, game);
+        game.setZone(splitCardParent.getId(), zone);
+        game.setZone(splitCardParent.getRightHalfCard().getId(), zone);
+    }
+
+
 }
 
 /*
@@ -247,4 +291,17 @@ class RightHalfCard  extends CardImpl {
     public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
         return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
     }
+    
+    @Override
+    public Card getMainCard() {
+        return splitCardParent;
+    }
+
+    @Override
+    public void setZone(Zone zone, Game game) {
+        super.setZone(zone, game);
+        game.setZone(splitCardParent.getId(), zone);
+        game.setZone(splitCardParent.getLeftHalfCard().getId(), zone);
+    }
+
 }
diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java
index a16426c9a2..8200578caa 100644
--- a/Mage/src/mage/game/GameImpl.java
+++ b/Mage/src/mage/game/GameImpl.java
@@ -2328,19 +2328,18 @@ public abstract class GameImpl implements Game, Serializable {
             loadCards(ownerId, graveyard);
 
             for (Card card : library) {
-                setZone(card.getId(), Zone.LIBRARY);
                 player.getLibrary().putOnTop(card, this);
             }
             for (Card card : hand) {
-                setZone(card.getId(), Zone.HAND);
+                card.setZone(Zone.HAND, this);
                 player.getHand().add(card);
             }
             for (Card card : graveyard) {
-                setZone(card.getId(), Zone.GRAVEYARD);
+                card.setZone(Zone.GRAVEYARD, this);
                 player.getGraveyard().add(card);
             }
             for (PermanentCard card : battlefield) {
-                setZone(card.getId(), Zone.BATTLEFIELD);
+                card.setZone(Zone.BATTLEFIELD, this);
                 card.setOwnerId(ownerId);
                 PermanentCard permanent = new PermanentCard(card.getCard(), ownerId);
                 getBattlefield().addPermanent(permanent);
diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java
index 5e9a9d7530..36788c92a6 100644
--- a/Mage/src/mage/game/stack/Spell.java
+++ b/Mage/src/mage/game/stack/Spell.java
@@ -210,7 +210,7 @@ public class Spell implements StackObject, Card {
                             }
                         }
                     }
-                    if (game.getState().getZone(card.getId()) == Zone.STACK) {
+                    if (game.getState().getZone(card.getMainCard().getId()) == Zone.STACK) {
                         card.moveToZone(Zone.GRAVEYARD, ability.getSourceId(), game, false);
                     }
                 }
@@ -999,4 +999,14 @@ public class Spell implements StackObject, Card {
         return card.isMorphCard();
     }
 
+    @Override
+    public Card getMainCard() {
+        return card.getMainCard();
+    }
+
+    @Override
+    public void setZone(Zone zone, Game game) {
+        card.setZone(zone, game);
+    }
+
 }
diff --git a/Mage/src/mage/players/Library.java b/Mage/src/mage/players/Library.java
index 5b878648f7..4a920c885e 100644
--- a/Mage/src/mage/players/Library.java
+++ b/Mage/src/mage/players/Library.java
@@ -131,7 +131,7 @@ public class Library implements Serializable {
 
     public void putOnTop(Card card, Game game) {
         if (card.getOwnerId().equals(playerId)) {
-            game.setZone(card.getId(), Zone.LIBRARY);
+            card.setZone(Zone.LIBRARY, game);
             library.addFirst(card.getId());
         }
         else {
@@ -141,7 +141,7 @@ public class Library implements Serializable {
 
     public void putOnBottom(Card card, Game game) {
         if (card.getOwnerId().equals(playerId)) {
-            game.setZone(card.getId(), Zone.LIBRARY);
+            card.setZone(Zone.LIBRARY, game);
             if (library.contains(card.getId())) {
                 library.remove(card.getId());
             }
@@ -226,7 +226,7 @@ public class Library implements Serializable {
 
     public void addAll(Set<Card> cards, Game game) {
         for (Card card: cards) {
-            game.setZone(card.getId(), Zone.LIBRARY);
+            card.setZone(Zone.LIBRARY, game);
             library.add(card.getId());
         }
     }
diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java
index f1f598202c..2da315c33f 100644
--- a/Mage/src/mage/players/PlayerImpl.java
+++ b/Mage/src/mage/players/PlayerImpl.java
@@ -650,8 +650,8 @@ public abstract class PlayerImpl implements Player, Serializable {
     @Override
     public boolean putInHand(Card card, Game game) {
         if (card.getOwnerId().equals(playerId)) {
+            card.setZone(Zone.HAND, game);
             this.hand.add(card);
-            game.setZone(card.getId(), Zone.HAND);
         } else {
             return game.getPlayer(card.getOwnerId()).putInHand(card, game);
         }
@@ -924,7 +924,7 @@ public abstract class PlayerImpl implements Player, Serializable {
         if (card != null) {
             if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability.getSourceId(), playerId))) {
                 int bookmark = game.bookmarkState();
-                Zone fromZone = game.getState().getZone(card.getId());
+                Zone fromZone = game.getState().getZone(card.getMainCard().getId());
                 card.cast(game, fromZone, ability, playerId);
                 Spell spell = game.getStack().getSpell(ability.getId());
                 // some effects set sourceId to cast without paying mana costs