diff --git a/.gitignore b/.gitignore
index e1956605db..0c1f55de65 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ Mage.Plugins/Mage.Card.Plugin/target
Mage.Plugins/Mage.Counter.Plugin/target
Mage.Plugins/Mage.Theme.Plugin/target
Mage.Plugins/Mage.Rating.Plugin/target
+Mage.Server.Console/target/
Mage.Server.Plugins/Mage.Deck.Constructed/target
Mage.Server.Plugins/Mage.Deck.Limited/target
Mage.Server.Plugins/Mage.Game.FreeForAll/target
@@ -16,6 +17,7 @@ Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target
Mage.Server.Plugins/Mage.Player.AI/target
Mage.Server.Plugins/Mage.Player.AIMinimax/target
Mage.Server.Plugins/Mage.Player.AI.MA/target
+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
@@ -24,6 +26,7 @@ Mage.Server/target
Mage.Sets/target
Mage.Tests/target
Mage/target
+Utils/GathererCrawler/target
releases
Utils/author.txt
@@ -40,7 +43,6 @@ syntax: regexp
nbactions.xml
glob:Mage.Client/cheat.dck
glob:Mage.Client/test.dck
-glob:Mage.Server.Console/target/
Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target
\.orig\..*$
@@ -49,4 +51,4 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target
\.rej$
\.conflict\~$
/Mage.Server.Plugins/Mage.Player.AIMCTS/target/
-/Mage.Server.Console/target/
\ No newline at end of file
+/Mage.Server.Console/target/
diff --git a/Mage.Client/release/sample-decks/World Championship 2011/Tommy Ashton – 12 points.dck b/Mage.Client/release/sample-decks/World Championship 2011/Tommy Ashton - 12 points.dck
similarity index 100%
rename from Mage.Client/release/sample-decks/World Championship 2011/Tommy Ashton – 12 points.dck
rename to Mage.Client/release/sample-decks/World Championship 2011/Tommy Ashton - 12 points.dck
diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml
index b54b291129..c6173ac3b1 100644
--- a/Mage.Common/pom.xml
+++ b/Mage.Common/pom.xml
@@ -50,6 +50,13 @@
trove
1.0.2
+
+
+ org.sqlite
+ sqlite
+ 0.5.6
+
+
diff --git a/Mage.Common/src/mage/db/EntityManager.java b/Mage.Common/src/mage/db/EntityManager.java
new file mode 100644
index 0000000000..567bdc6213
--- /dev/null
+++ b/Mage.Common/src/mage/db/EntityManager.java
@@ -0,0 +1,35 @@
+package mage.db;
+
+import java.sql.*;
+
+/**
+ * @author noxx
+ */
+public class EntityManager {
+
+ public static void main(String[] args) throws Exception {
+ Class.forName("org.sqlite.JDBC");
+ Connection conn = DriverManager.getConnection("jdbc:sqlite:mage.db");
+ Statement stat = conn.createStatement();
+ stat.executeUpdate("drop table if exists users;");
+ stat.executeUpdate("create table users (login, password);");
+
+ PreparedStatement prep = conn.prepareStatement("insert into users values (?, ?);");
+
+ prep.setString(1, "TestUser");
+ prep.setString(2, "123");
+ prep.execute();
+
+ prep.setString(1, "TestUser2");
+ prep.setString(2, "12345");
+ prep.execute();
+
+ ResultSet rs = stat.executeQuery("select * from users;");
+ while (rs.next()) {
+ System.out.println("user = " + rs.getString("login"));
+ System.out.println("password = " + rs.getString("password"));
+ }
+ rs.close();
+ conn.close();
+ }
+}
diff --git a/Mage.Common/src/mage/db/model/User.java b/Mage.Common/src/mage/db/model/User.java
new file mode 100644
index 0000000000..2664aaad1f
--- /dev/null
+++ b/Mage.Common/src/mage/db/model/User.java
@@ -0,0 +1,11 @@
+package mage.db.model;
+
+/**
+ * @author noxx
+ */
+public class User {
+
+ private String login;
+
+ private String password;
+}
diff --git a/Mage.Common/src/mage/remote/MageVersionException.java b/Mage.Common/src/mage/remote/MageVersionException.java
index b098da6eb7..7b5b4185f2 100644
--- a/Mage.Common/src/mage/remote/MageVersionException.java
+++ b/Mage.Common/src/mage/remote/MageVersionException.java
@@ -39,7 +39,7 @@ public class MageVersionException extends MageException {
private MageVersion serverVersion;
public MageVersionException(MageVersion clientVersion, MageVersion serverVersion) {
- super("Wrong client version " + clientVersion + ", expecting version " + serverVersion);
+ super("Wrong client version " + clientVersion + ", expecting version " + serverVersion + ". \r\n\r\nPlease download new version at magefree.com.");
this.serverVersion = serverVersion;
}
diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java
index c442d8e4ea..c330fb5877 100644
--- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java
+++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java
@@ -28,43 +28,41 @@
package mage.server;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.ExecutorService;
import mage.MageException;
import mage.cards.decks.DeckCardLists;
import mage.game.GameException;
import mage.game.match.MatchOptions;
import mage.game.tournament.TournamentOptions;
+import mage.interfaces.Action;
import mage.interfaces.MageServer;
-//import mage.interfaces.Server;
import mage.interfaces.ServerState;
import mage.remote.MageVersionException;
-import mage.server.game.DeckValidatorFactory;
import mage.server.draft.DraftManager;
-import mage.server.game.GameFactory;
-import mage.server.game.GameManager;
-import mage.server.game.GamesRoomManager;
-import mage.server.game.PlayerFactory;
-import mage.server.game.ReplayManager;
+import mage.server.game.*;
import mage.server.tournament.TournamentFactory;
import mage.server.tournament.TournamentManager;
import mage.server.util.ServerMessagesUtil;
import mage.server.util.ThreadExecutor;
import mage.utils.CompressUtil;
import mage.utils.MageVersion;
-import mage.view.*;
import mage.view.ChatMessage.MessageColor;
+import mage.view.*;
import org.apache.log4j.Logger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+
+//import mage.interfaces.Server;
+
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class MageServerImpl implements MageServer {
- private final static Logger logger = Logger.getLogger("Mage Server");
+ private final static Logger logger = Logger.getLogger(MageServerImpl.class);
private static ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
private String password;
@@ -79,8 +77,10 @@ public class MageServerImpl implements MageServer {
@Override
public boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException {
try {
- if (version.compareTo(Main.getVersion()) != 0)
+ if (version.compareTo(Main.getVersion()) != 0) {
+ logger.info("MageVersionException: userName=" + userName + ", version=" + version);
throw new MageVersionException(version, Main.getVersion());
+ }
return SessionManager.getInstance().registerUser(sessionId, userName);
} catch (Exception ex) {
if (ex instanceof MageVersionException)
@@ -148,24 +148,12 @@ public class MageServerImpl implements MageServer {
@Override
public void removeTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- TableManager.getInstance().removeTable(userId, tableId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ TableManager.getInstance().removeTable(userId, tableId);
+ }
+ });
}
@Override
@@ -302,68 +290,32 @@ public class MageServerImpl implements MageServer {
@Override
public void startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
TableManager.getInstance().startMatch(userId, roomId, tableId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ }
+ });
}
@Override
public void startChallenge(final String sessionId, final UUID roomId, final UUID tableId, final UUID challengeId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- TableManager.getInstance().startChallenge(userId, roomId, tableId, challengeId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ TableManager.getInstance().startChallenge(userId, roomId, tableId, challengeId);
+ }
+ });
+ }
@Override
public void startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- TableManager.getInstance().startTournament(userId, roomId, tableId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ TableManager.getInstance().startTournament(userId, roomId, tableId);
+ }
+ });
}
@Override
@@ -396,42 +348,22 @@ public class MageServerImpl implements MageServer {
@Override
public void joinChat(final UUID chatId, final String sessionId, final String userName) throws MageException {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
ChatManager.getInstance().joinChat(chatId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
+ }
+ });
}
@Override
public void leaveChat(final UUID chatId, final String sessionId) throws MageException {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ChatManager.getInstance().leaveChat(chatId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ChatManager.getInstance().leaveChat(chatId, userId);
+ }
+ });
}
@Override
@@ -472,46 +404,22 @@ public class MageServerImpl implements MageServer {
@Override
public void swapSeats(final String sessionId, final UUID roomId, final UUID tableId, final int seatNum1, final int seatNum2) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- TableManager.getInstance().swapSeats(tableId, userId, seatNum1, seatNum2);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ TableManager.getInstance().swapSeats(tableId, userId, seatNum1, seatNum2);
+ }
+ });
}
@Override
public void leaveTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- GamesRoomManager.getInstance().getRoom(roomId).leaveTable(userId, tableId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ GamesRoomManager.getInstance().getRoom(roomId).leaveTable(userId, tableId);
+ }
+ });
}
@Override
@@ -527,68 +435,32 @@ public class MageServerImpl implements MageServer {
@Override
public void joinGame(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- GameManager.getInstance().joinGame(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ GameManager.getInstance().joinGame(gameId, userId);
+ }
+ });
}
@Override
public void joinDraft(final UUID draftId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- DraftManager.getInstance().joinDraft(draftId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ DraftManager.getInstance().joinDraft(draftId, userId);
+ }
+ });
}
@Override
public void joinTournament(final UUID tournamentId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- TournamentManager.getInstance().joinTournament(tournamentId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ TournamentManager.getInstance().joinTournament(tournamentId, userId);
+ }
+ });
}
@Override
@@ -613,91 +485,45 @@ public class MageServerImpl implements MageServer {
return null;
}
- @Override
- public void sendPlayerUUID(final UUID gameId, final String sessionId, final UUID data) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- User user = SessionManager.getInstance().getUser(sessionId);
- user.sendPlayerUUID(gameId, data);
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void sendPlayerUUID(final UUID gameId, final String sessionId, final UUID data) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ User user = SessionManager.getInstance().getUser(sessionId);
+ user.sendPlayerUUID(gameId, data);
+ }
+ });
+ }
@Override
- public void sendPlayerString(final UUID gameId, final String sessionId, final String data) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- User user = SessionManager.getInstance().getUser(sessionId);
- user.sendPlayerString(gameId, data);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ public void sendPlayerString(final UUID gameId, final String sessionId, final String data) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ User user = SessionManager.getInstance().getUser(sessionId);
+ user.sendPlayerString(gameId, data);
+ }
+ });
}
@Override
public void sendPlayerBoolean(final UUID gameId, final String sessionId, final Boolean data) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- User user = SessionManager.getInstance().getUser(sessionId);
- user.sendPlayerBoolean(gameId, data);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ User user = SessionManager.getInstance().getUser(sessionId);
+ user.sendPlayerBoolean(gameId, data);
+ }
+ });
}
@Override
public void sendPlayerInteger(final UUID gameId, final String sessionId, final Integer data) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- User user = SessionManager.getInstance().getUser(sessionId);
- user.sendPlayerInteger(gameId, data);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ User user = SessionManager.getInstance().getUser(sessionId);
+ user.sendPlayerInteger(gameId, data);
+ }
+ });
+ }
@Override
public DraftPickView sendCardPick(final UUID draftId, final String sessionId, final UUID cardPick) throws MageException {
@@ -713,27 +539,15 @@ public class MageServerImpl implements MageServer {
return null;
}
- @Override
- public void concedeGame(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- GameManager.getInstance().concedeGame(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void concedeGame(final UUID gameId, final String sessionId) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ GameManager.getInstance().concedeGame(gameId, userId);
+ }
+ });
+ }
@Override
public boolean watchTable(String sessionId, UUID roomId, UUID tableId) throws MageException {
@@ -749,181 +563,85 @@ public class MageServerImpl implements MageServer {
return false;
}
- @Override
- public void watchGame(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- GameManager.getInstance().watchGame(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void watchGame(final UUID gameId, final String sessionId) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ GameManager.getInstance().watchGame(gameId, userId);
+ }
+ });
+ }
- @Override
- public void stopWatching(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- GameManager.getInstance().stopWatching(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void stopWatching(final UUID gameId, final String sessionId) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ GameManager.getInstance().stopWatching(gameId, userId);
+ }
+ });
+ }
@Override
public void replayGame(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ReplayManager.getInstance().replayGame(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ReplayManager.getInstance().replayGame(gameId, userId);
+ }
+ });
}
- @Override
- public void startReplay(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ReplayManager.getInstance().startReplay(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void startReplay(final UUID gameId, final String sessionId) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ReplayManager.getInstance().startReplay(gameId, userId);
+ }
+ });
+ }
@Override
public void stopReplay(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ReplayManager.getInstance().stopReplay(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ReplayManager.getInstance().stopReplay(gameId, userId);
+ }
+ });
}
@Override
- public void nextPlay(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ReplayManager.getInstance().nextPlay(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ public void nextPlay(final UUID gameId, final String sessionId) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ReplayManager.getInstance().nextPlay(gameId, userId);
+ }
+ });
+ }
@Override
public void previousPlay(final UUID gameId, final String sessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ReplayManager.getInstance().previousPlay(gameId, userId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ReplayManager.getInstance().previousPlay(gameId, userId);
+ }
+ });
}
- @Override
- public void skipForward(final UUID gameId, final String sessionId, final int moves) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- ReplayManager.getInstance().skipForward(gameId, userId, moves);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void skipForward(final UUID gameId, final String sessionId, final int moves) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ ReplayManager.getInstance().skipForward(gameId, userId, moves);
+ }
+ });
+ }
@Override
public ServerState getServerState() throws MageException {
@@ -942,29 +660,17 @@ public class MageServerImpl implements MageServer {
return null;
}
- @Override
- public void cheat(final UUID gameId, final String sessionId, final UUID playerId, final DeckCardLists deckList) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (testMode) {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- GameManager.getInstance().cheat(gameId, userId, playerId, deckList);
- }
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
- }
+ @Override
+ public void cheat(final UUID gameId, final String sessionId, final UUID playerId, final DeckCardLists deckList) throws MageException {
+ execute(sessionId, new Action() {
+ public void execute() {
+ if (testMode) {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ GameManager.getInstance().cheat(gameId, userId, playerId, deckList);
+ }
+ }
+ });
+ }
@Override
public boolean cheat(final UUID gameId, final String sessionId, final UUID playerId, final String cardName) throws MageException {
@@ -1005,43 +711,21 @@ public class MageServerImpl implements MageServer {
@Override
public void disconnectUser(final String sessionId, final String userSessionId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- SessionManager.getInstance().disconnectUser(sessionId, userSessionId);
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ SessionManager.getInstance().disconnectUser(sessionId, userSessionId);
+ }
+ });
}
-
+
@Override
public void removeTable(final String sessionId, final UUID tableId) throws MageException {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- try {
- callExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- if (SessionManager.getInstance().isValidSession(sessionId)) {
- UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
- TableManager.getInstance().removeTable(userId, tableId);
- }
- }
- }
- );
- }
- catch (Exception ex) {
- handleException(ex);
- }
- }
+ execute(sessionId, new Action() {
+ public void execute() {
+ UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
+ TableManager.getInstance().removeTable(userId, tableId);
+ }
+ });
}
@Override
@@ -1056,4 +740,24 @@ public class MageServerImpl implements MageServer {
}
return null;
}
+
+ protected void execute(final String sessionId, final Action action) throws MageException {
+ if (SessionManager.getInstance().isValidSession(sessionId)) {
+ try {
+ callExecutor.execute(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (SessionManager.getInstance().isValidSession(sessionId)) {
+ action.execute();
+ }
+ }
+ }
+ );
+ }
+ catch (Exception ex) {
+ handleException(ex);
+ }
+ }
+ }
}
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java b/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java
index f8bd424494..d9f2e48ac8 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/AkkiLavarunner.java
@@ -1,5 +1,6 @@
package mage.sets.championsofkamigawa;
+import java.util.UUID;
import mage.Constants;
import mage.MageInt;
import mage.ObjectColor;
@@ -11,7 +12,6 @@ import mage.abilities.decorator.ConditionalContinousEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CopyTokenEffect;
import mage.abilities.effects.common.FlipSourceEffect;
-import mage.abilities.effects.common.UntapAllLandsControllerEffect;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.Card;
@@ -23,8 +23,6 @@ import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.token.Token;
-import java.util.UUID;
-
/**
* @author Loki
*/
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java b/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java
index 336983b76e..39adb244d0 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java
@@ -76,7 +76,8 @@ public class BloodthirstyOgre extends CardImpl {
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(new DevotionCounter()),new TapSourceCost()));
// {T}: Target creature gets -X/-X until end of turn, where X is the number of devotion counters on Bloodthirsty Ogre. Activate this ability only if you control a Demon.
DynamicValue devotionCounters = new SignInversionDynamicValue(new CountersCount(CounterType.DEVOTION));
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,new BoostTargetEffect(devotionCounters,devotionCounters, Duration.EndOfTurn),new TapSourceCost());
+ Ability ability;
+ ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(devotionCounters,devotionCounters, Duration.EndOfTurn, true),new TapSourceCost());
ability.addCost(new ControlPermanentCost(filter));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfCleansingFire.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfCleansingFire.java
index d2264ca594..1bd1cfa704 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfCleansingFire.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfCleansingFire.java
@@ -58,6 +58,8 @@ public class HondenOfCleansingFire extends CardImpl {
this.supertype.add("Legendary");
this.subtype.add("Shrine");
this.color.setWhite(true);
+
+ // At the beginning of your upkeep, you gain 2 life for each Shrine you control.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(new PermanentsOnBattlefieldCount(filter, 2)), Constants.TargetController.YOU, false));
}
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfInfiniteRage.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfInfiniteRage.java
index de4b2bbfe5..a8021235ac 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfInfiniteRage.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfInfiniteRage.java
@@ -29,7 +29,6 @@
package mage.sets.championsofkamigawa;
import java.util.UUID;
-
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
@@ -60,7 +59,9 @@ public class HondenOfInfiniteRage extends CardImpl {
this.expansionSetCode = "CHK";
this.supertype.add("Legendary");
this.subtype.add("Shrine");
- this.color.setRed(true);
+ this.color.setRed(true);
+
+ // At the beginning of your upkeep, Honden of Infinite Rage deals damage to target creature or player equal to the number of Shrines you control.
Ability ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(new PermanentsOnBattlefieldCount(filter)), Constants.TargetController.YOU, false);
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfNightsReach.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfNightsReach.java
index 12bb71ff35..2cb62296ac 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfNightsReach.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfNightsReach.java
@@ -29,7 +29,6 @@
package mage.sets.championsofkamigawa;
import java.util.UUID;
-
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
@@ -47,7 +46,7 @@ import mage.target.common.TargetOpponent;
*/
public class HondenOfNightsReach extends CardImpl {
- final static FilterControlledPermanent filter = new FilterControlledPermanent("shrine");
+ final static FilterControlledPermanent filter = new FilterControlledPermanent("Shrine");
static {
filter.getSubtype().add("Shrine");
@@ -60,6 +59,8 @@ public class HondenOfNightsReach extends CardImpl {
this.supertype.add("Legendary");
this.subtype.add("Shrine");
this.color.setBlack(true);
+
+ // At the beginning of your upkeep, target opponent discards a card for each Shrine you control.
Ability ability = new BeginningOfUpkeepTriggeredAbility(new DiscardTargetEffect(new PermanentsOnBattlefieldCount(filter)), Constants.TargetController.YOU, false);
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfSeeingWinds.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfSeeingWinds.java
index e04df636b5..814fb4387f 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfSeeingWinds.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HondenOfSeeingWinds.java
@@ -58,6 +58,8 @@ public class HondenOfSeeingWinds extends CardImpl {
this.supertype.add("Legendary");
this.subtype.add("Shrine");
this.color.setBlue(true);
+
+ // At the beginning of your upkeep, draw a card for each Shrine you control.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardControllerEffect(new PermanentsOnBattlefieldCount(filter)), Constants.TargetController.YOU, false));
}
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java
new file mode 100644
index 0000000000..d44dffb56c
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeReaver.java
@@ -0,0 +1,77 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.Constants.Zone;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.RegenerateSourceEffect;
+import mage.abilities.effects.common.SkipNextUntapTargetEffect;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.cards.CardImpl;
+
+/**
+ *
+ * @author LevelX
+ */
+public class KashiTribeReaver extends CardImpl {
+
+ public KashiTribeReaver(UUID ownerId) {
+ super(ownerId, 220, "Kashi-Tribe Reaver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{G}");
+ this.expansionSetCode = "CHK";
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // Whenever Kashi-Tribe Reaver deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step.
+ Ability ability;
+ ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true);
+ ability.addEffect(new SkipNextUntapTargetEffect("and it"));
+ this.addAbility(ability);
+ // {1}{G}: Regenerate Kashi-Tribe Reaver.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{G}")));
+ }
+
+ public KashiTribeReaver(final KashiTribeReaver card) {
+ super(card);
+ }
+
+ @Override
+ public KashiTribeReaver copy() {
+ return new KashiTribeReaver(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java
new file mode 100644
index 0000000000..cfe32a1f6d
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KashiTribeWarriors.java
@@ -0,0 +1,72 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
+import mage.abilities.effects.common.SkipNextUntapTargetEffect;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.cards.CardImpl;
+
+/**
+ *
+ * @author LevelX
+ */
+public class KashiTribeWarriors extends CardImpl {
+
+ public KashiTribeWarriors(UUID ownerId) {
+ super(ownerId, 221, "Kashi-Tribe Warriors", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
+ this.expansionSetCode = "CHK";
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(4);
+
+ // Whenever Kashi-Tribe Reaver deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step.
+ Ability ability;
+ ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true);
+ ability.addEffect(new SkipNextUntapTargetEffect("and it"));
+ this.addAbility(ability);
+ }
+
+ public KashiTribeWarriors(final KashiTribeWarriors card) {
+ super(card);
+ }
+
+ @Override
+ public KashiTribeWarriors copy() {
+ return new KashiTribeWarriors(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KikuNightsFlower.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KikuNightsFlower.java
new file mode 100644
index 0000000000..8773bb717e
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KikuNightsFlower.java
@@ -0,0 +1,111 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.Constants.Zone;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ *
+ * @author LevelX
+ */
+public class KikuNightsFlower extends CardImpl {
+
+ public KikuNightsFlower (UUID ownerId) {
+ super(ownerId, 121, "Kiku, Night's Flower", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{B}{B}");
+ this.expansionSetCode = "CHK";
+ this.supertype.add("Legendary");
+ this.subtype.add("Human");
+ this.subtype.add("Assassin");
+ this.color.setBlack(true);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // {2}{B}{B}, {T}: Target creature deals damage to itself equal to its power.
+ Ability ability;
+ ability = new SimpleActivatedAbility(
+ Zone.BATTLEFIELD,
+ new KikuNightsFlowerEffect(),
+ new ManaCostsImpl("{2}{B}{B}")
+ );
+ ability.addTarget(new TargetCreaturePermanent());
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability);
+ }
+
+ public KikuNightsFlower (final KikuNightsFlower card) {
+ super(card);
+ }
+
+ @Override
+ public KikuNightsFlower copy() {
+ return new KikuNightsFlower(this);
+ }
+}
+
+class KikuNightsFlowerEffect extends OneShotEffect {
+
+ public KikuNightsFlowerEffect() {
+ super(Constants.Outcome.Damage);
+ this.staticText = "Target creature deals damage to itself equal to its power";
+ }
+
+ public KikuNightsFlowerEffect(final KikuNightsFlowerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public KikuNightsFlowerEffect copy() {
+ return new KikuNightsFlowerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(targetPointer.getFirst(source));
+ if (permanent != null) {
+ permanent.damage(permanent.getPower().getValue(), permanent.getId(), game, true, false);
+ return true;
+ }
+ return false;
+ }
+}
+
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java
index d48ff522b8..c42806d12d 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java
@@ -69,10 +69,10 @@ public class KondasBanner extends CardImpl {
this.subtype.add("Equipment");
// Creatures that share a color with equipped creature get +1/+1.
- this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new KodasBannerColorBoostEffect()));
+ this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new KondasBannerColorBoostEffect()));
// Creatures that share a creature type with equipped creature get +1/+1.
- this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new KodasBannerTypeBoostEffect()));
+ this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new KondasBannerTypeBoostEffect()));
// Konda's Banner can be attached only to a legendary creature.
// Equip {2}
@@ -93,16 +93,16 @@ public class KondasBanner extends CardImpl {
}
}
-class KodasBannerTypeBoostEffect extends BoostAllEffect {
+class KondasBannerTypeBoostEffect extends BoostAllEffect {
private static final String effectText = "Creatures that share a creature type with equipped creature get +1/+1";
- KodasBannerTypeBoostEffect() {
+ KondasBannerTypeBoostEffect() {
super(1,1, Constants.Duration.WhileOnBattlefield, new FilterCreaturePermanent(), false);
staticText = effectText;
}
- KodasBannerTypeBoostEffect(KodasBannerTypeBoostEffect effect) {
+ KondasBannerTypeBoostEffect(KondasBannerTypeBoostEffect effect) {
super(effect);
}
@@ -113,38 +113,40 @@ class KodasBannerTypeBoostEffect extends BoostAllEffect {
if (equipment != null && equipment.getAttachedTo() != null)
{
Permanent equipedCreature = game.getPermanent(equipment.getAttachedTo());
- for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
- if (CardUtil.shareSubtypes(perm, equipedCreature) || perm.getAbilities().contains(ChangelingAbility.getInstance())) {
- if (!this.affectedObjectsSet || objects.contains(perm.getId())) {
- perm.addPower(power.calculate(game, source));
- perm.addToughness(toughness.calculate(game, source));
- }
-
- }
- }
- return true;
+ if (equipedCreature != null) {
+ for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
+ if (CardUtil.shareSubtypes(perm, equipedCreature) || perm.getAbilities().contains(ChangelingAbility.getInstance())) {
+ if (!this.affectedObjectsSet || objects.contains(perm.getId())) {
+ perm.addPower(power.calculate(game, source));
+ perm.addToughness(toughness.calculate(game, source));
+ }
+
+ }
+ }
+ return true;
+ }
}
return false;
}
@Override
- public KodasBannerTypeBoostEffect copy() {
- return new KodasBannerTypeBoostEffect(this);
+ public KondasBannerTypeBoostEffect copy() {
+ return new KondasBannerTypeBoostEffect(this);
}
}
-class KodasBannerColorBoostEffect extends BoostAllEffect {
+class KondasBannerColorBoostEffect extends BoostAllEffect {
private static final String effectText = "Creatures that share a color with equipped creature get +1/+1.";
- KodasBannerColorBoostEffect() {
+ KondasBannerColorBoostEffect() {
super(1,1, Constants.Duration.WhileOnBattlefield, new FilterCreaturePermanent(), false);
staticText = effectText;
}
- KodasBannerColorBoostEffect(KodasBannerColorBoostEffect effect) {
+ KondasBannerColorBoostEffect(KondasBannerColorBoostEffect effect) {
super(effect);
}
@@ -170,8 +172,8 @@ class KodasBannerColorBoostEffect extends BoostAllEffect {
}
@Override
- public KodasBannerColorBoostEffect copy() {
- return new KodasBannerColorBoostEffect(this);
+ public KondasBannerColorBoostEffect copy() {
+ return new KondasBannerColorBoostEffect(this);
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MarrowGnawer.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MarrowGnawer.java
new file mode 100644
index 0000000000..3cc133fba7
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MarrowGnawer.java
@@ -0,0 +1,110 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.Constants.Zone;
+import mage.MageInt;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.continious.GainAbilityAllEffect;
+import mage.abilities.keyword.FearAbility;
+import mage.cards.CardImpl;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.game.permanent.token.Token;
+import mage.target.common.TargetControlledPermanent;
+
+/**
+ *
+ * @author LevelX
+ */
+public class MarrowGnawer extends CardImpl {
+
+ private static final FilterCreaturePermanent filterFear = new FilterCreaturePermanent("Rat creatures");
+ private static final FilterControlledCreaturePermanent filterSacrifice = new FilterControlledCreaturePermanent("a Rat");
+ private static final FilterControlledCreaturePermanent filter3 = new FilterControlledCreaturePermanent("Rats you control");
+
+ static {
+ filterFear.getSubtype().add("Rat");
+ filterSacrifice.getSubtype().add("Rat");
+ filter3.getSubtype().add("Rat");
+ }
+
+ public MarrowGnawer (UUID ownerId) {
+ super(ownerId, 124, "Marrow-Gnawer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
+ this.expansionSetCode = "CHK";
+ this.subtype.add("Rat");
+ this.subtype.add("Rogue");
+ this.color.setBlack(true);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Rat creatures have fear. (They can't be blocked except by artifact creatures and/or black creatures.)
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(FearAbility.getInstance(), Constants.Duration.WhileOnBattlefield, filterFear)));
+
+ // {T}, Sacrifice a Rat: Put X 1/1 black Rat creature tokens onto the battlefield, where X is the number of Rats you control.
+ Ability ability;
+ ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new RatToken(),new PermanentsOnBattlefieldCount(filter3)), new SacrificeTargetCost(new TargetControlledPermanent(filterSacrifice)));
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability);
+ }
+
+ public MarrowGnawer (final MarrowGnawer card) {
+ super(card);
+ }
+
+ @Override
+ public MarrowGnawer copy() {
+ return new MarrowGnawer(this);
+ }
+
+}
+
+class RatToken extends Token {
+
+ public RatToken() {
+ super("Rat", "1/1 black Rat creature token");
+ cardType.add(CardType.CREATURE);
+ color = ObjectColor.BLACK;
+ subtype.add("Rat");
+ power = new MageInt(1);
+ toughness = new MageInt(1);
+ }
+
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java b/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java
new file mode 100644
index 0000000000..d3bd058d79
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/MatsuTribeDecoy.java
@@ -0,0 +1,82 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.Constants.Zone;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.MustBlockSourceTargetEffect;
+import mage.abilities.effects.common.SkipNextUntapTargetEffect;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.cards.CardImpl;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author LevelX
+ */
+public class MatsuTribeDecoy extends CardImpl {
+
+ public MatsuTribeDecoy(UUID ownerId) {
+ super(ownerId, 227, "Matsu-Tribe Decoy", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
+ this.expansionSetCode = "CHK";
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(3);
+
+ // {2}{G}: Target creature blocks Matsu-Tribe Decoy this turn if able.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBlockSourceTargetEffect(), new ManaCostsImpl("{2}{G}"));
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ // Whenever Kashi-Tribe Reaver deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step.
+ Ability ability2;
+ ability2 = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true);
+ ability2.addEffect(new SkipNextUntapTargetEffect("and it"));
+ this.addAbility(ability2);
+ }
+
+ public MatsuTribeDecoy(final MatsuTribeDecoy card) {
+ super(card);
+ }
+
+ @Override
+ public MatsuTribeDecoy copy() {
+ return new MatsuTribeDecoy(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiEggwatcher.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiEggwatcher.java
new file mode 100644
index 0000000000..0fdefc0022
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiEggwatcher.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Duration;
+import mage.Constants.Rarity;
+import mage.Constants.Zone;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.ControlsPermanentCondition;
+import mage.abilities.condition.common.FlippedCondition;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalContinousEffect;
+import mage.abilities.decorator.ConditionalOneShotEffect;
+import mage.abilities.effects.common.CopyTokenEffect;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.FlipSourceEffect;
+import mage.abilities.effects.common.continious.BoostTargetEffect;
+import mage.cards.CardImpl;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.game.permanent.token.SnakeToken;
+import mage.game.permanent.token.Token;
+import mage.target.common.TargetControlledCreaturePermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ * @author LevelX
+ */
+public class OrochiEggwatcher extends CardImpl {
+
+ public OrochiEggwatcher(UUID ownerId) {
+ super(ownerId, 233, "Orochi Eggwatcher", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}");
+ this.expansionSetCode = "CHK";
+ this.subtype.add("Snake");
+ this.subtype.add("Shaman");
+ this.color.setGreen(true);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // {2}{G}, {T}: Put a 1/1 green Snake creature token onto the battlefield. If you control ten or more creatures, flip Orochi Eggwatcher.
+ Ability ability;
+ ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SnakeToken()),new ManaCostsImpl("{2}{G}"));
+ ability.addCost(new TapSourceCost());
+ ability.addEffect(new ConditionalOneShotEffect(new FlipSourceEffect(),
+ new ControlsPermanentCondition(new FilterControlledCreaturePermanent(),ControlsPermanentCondition.CountType.MORE_THAN, 9),"If you control ten or more creatures, flip {this}"));
+ this.addAbility(ability);
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new CopyTokenEffect(new ShidakoBroodmistress()), FlippedCondition.getInstance(), "")));
+ }
+
+ public OrochiEggwatcher(final OrochiEggwatcher card) {
+ super(card);
+ }
+
+ @Override
+ public OrochiEggwatcher copy() {
+ return new OrochiEggwatcher(this);
+ }
+}
+
+class ShidakoBroodmistress extends Token {
+
+ ShidakoBroodmistress() {
+ super("Shidako, Broodmistress", "");
+ supertype.add("Legendary");
+ cardType.add(Constants.CardType.CREATURE);
+ color.setGreen(true);
+ subtype.add("Snake");
+ subtype.add("Shaman");
+ power = new MageInt(3);
+ toughness = new MageInt(3);
+ // {G}, Sacrifice a creature: Target creature gets +3/+3 until end of turn.
+ Ability ability;
+ ability = new SimpleActivatedAbility(
+ Zone.BATTLEFIELD,
+ new BoostTargetEffect(3,3, Duration.EndOfTurn),
+ new ManaCostsImpl("{G}"));
+ ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent()));
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+}
+
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java
new file mode 100644
index 0000000000..36425bbb5a
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiRanger.java
@@ -0,0 +1,72 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
+import mage.abilities.effects.common.SkipNextUntapTargetEffect;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.cards.CardImpl;
+
+/**
+ *
+ * @author LevelX
+ */
+public class OrochiRanger extends CardImpl {
+
+ public OrochiRanger(UUID ownerId) {
+ super(ownerId, 235, "Orochi Ranger", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{G}");
+ this.expansionSetCode = "CHK";
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Whenever Orochi Ranger deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step.
+ Ability ability;
+ ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true);
+ ability.addEffect(new SkipNextUntapTargetEffect("and it"));
+ this.addAbility(ability);
+ }
+
+ public OrochiRanger(final OrochiRanger card) {
+ super(card);
+ }
+
+ @Override
+ public OrochiRanger copy() {
+ return new OrochiRanger(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/ShisatoWhisperingHunter.java b/Mage.Sets/src/mage/sets/championsofkamigawa/ShisatoWhisperingHunter.java
new file mode 100644
index 0000000000..4e1199f9d1
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/ShisatoWhisperingHunter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.Constants.TargetController;
+import mage.MageInt;
+import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
+import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
+import mage.abilities.effects.common.SacrificeControllerEffect;
+import mage.abilities.effects.common.SkipNextPlayerUntapStepEffect;
+import mage.cards.CardImpl;
+import mage.filter.common.FilterControlledCreaturePermanent;
+
+/**
+ *
+ * @author LevelX
+ */
+public class ShisatoWhisperingHunter extends CardImpl {
+
+
+ private final static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Snake");
+
+ static {
+ filter.getSubtype().add("Snake");
+ filter.setTargetController(TargetController.YOU);
+ }
+
+ public ShisatoWhisperingHunter(UUID ownerId) {
+ super(ownerId, 242, "Shisato, Whispering Hunter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}");
+ this.expansionSetCode = "CHK";
+ this.supertype.add("Legendary");
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // At the beginning of your upkeep, sacrifice a Snake.
+ this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeControllerEffect(filter, 1,""), Constants.TargetController.YOU, false));
+ // Whenever Shisato, Whispering Hunter deals combat damage to a player, that player skips his or her next untap step.
+ this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new SkipNextPlayerUntapStepEffect("that "),false, true));
+ }
+
+ public ShisatoWhisperingHunter(final ShisatoWhisperingHunter card) {
+ super(card);
+ }
+
+ @Override
+ public ShisatoWhisperingHunter copy() {
+ return new ShisatoWhisperingHunter(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java b/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java
new file mode 100644
index 0000000000..248eef79a7
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java
@@ -0,0 +1,158 @@
+/*
+ * 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.championsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Outcome;
+import mage.Constants.Rarity;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.abilities.effects.common.continious.BoostControlledEffect;
+import mage.cards.CardImpl;
+import mage.filter.Filter;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.game.Game;
+import mage.game.events.DamagedCreatureEvent;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author LevelX
+ */
+public class SosukeSonOfSeshiro extends CardImpl {
+
+ private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("Snake creatures");
+
+ static {
+ filter.getSubtype().add("Snake");
+ filter.setScopeSubtype(Filter.ComparisonScope.Any);
+ }
+
+ public SosukeSonOfSeshiro(UUID ownerId) {
+ super(ownerId, 244, "Sosuke, Son of Seshiro", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
+ this.expansionSetCode = "CHK";
+ this.supertype.add("Legendary");
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(4);
+
+ // Other Snake creatures you control get +1/+0.
+ this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new BoostControlledEffect(1, 0, Constants.Duration.WhileOnBattlefield, filter, true)));
+ // Whenever a Warrior you control deals combat damage to a creature, destroy that creature at end of combat.
+ this.addAbility(new SosukeSonOfSeshiroTriggeredAbility());
+ }
+
+ public SosukeSonOfSeshiro(final SosukeSonOfSeshiro card) {
+ super(card);
+ }
+
+ @Override
+ public SosukeSonOfSeshiro copy() {
+ return new SosukeSonOfSeshiro(this);
+ }
+}
+
+class SosukeSonOfSeshiroTriggeredAbility extends TriggeredAbilityImpl {
+
+ SosukeSonOfSeshiroTriggeredAbility() {
+ super(Constants.Zone.BATTLEFIELD, new SosukeSonOfSeshiroEffect());
+ }
+
+ SosukeSonOfSeshiroTriggeredAbility(final SosukeSonOfSeshiroTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public SosukeSonOfSeshiroTriggeredAbility copy() {
+ return new SosukeSonOfSeshiroTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event instanceof DamagedCreatureEvent) {
+ if (((DamagedCreatureEvent) event).isCombatDamage()) {
+ Permanent sourceCreature = game.getPermanent(event.getSourceId());
+ Permanent targetCreature = game.getPermanent(event.getTargetId());
+ if (sourceCreature != null && sourceCreature.getControllerId().equals(this.getControllerId())
+ && targetCreature != null && sourceCreature.getSubtype().contains("Warrior")) {
+ this.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId()));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever a Warrior you control deals combat damage to a creature, destroy that creature at end of combat.";
+ }
+}
+
+class SosukeSonOfSeshiroEffect extends OneShotEffect {
+
+ SosukeSonOfSeshiroEffect() {
+ super(Outcome.DestroyPermanent);
+ staticText = "destroy that creature at end of combat";
+ }
+
+ SosukeSonOfSeshiroEffect(final SosukeSonOfSeshiroEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(source));
+ if (targetCreature != null) {
+ AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect());
+ delayedAbility.setSourceId(source.getSourceId());
+ delayedAbility.setControllerId(source.getControllerId());
+ delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId()));
+ game.addDelayedTriggeredAbility(delayedAbility);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public SosukeSonOfSeshiroEffect copy() {
+ return new SosukeSonOfSeshiroEffect(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/StrengthOfCedars.java b/Mage.Sets/src/mage/sets/championsofkamigawa/StrengthOfCedars.java
index 5b3b8c790b..75c35cb831 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/StrengthOfCedars.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/StrengthOfCedars.java
@@ -59,7 +59,7 @@ public class StrengthOfCedars extends CardImpl {
this.subtype.add("Arcane");
this.color.setGreen(true);
this.getSpellAbility().addEffect(new BoostTargetEffect(new PermanentsOnBattlefieldCount(filter),
- new PermanentsOnBattlefieldCount(filter), Constants.Duration.EndOfTurn));
+ new PermanentsOnBattlefieldCount(filter), Constants.Duration.EndOfTurn, true));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/YoseiTheMorningStar.java b/Mage.Sets/src/mage/sets/championsofkamigawa/YoseiTheMorningStar.java
index 96601a1e9e..2c2e8bdb7d 100644
--- a/Mage.Sets/src/mage/sets/championsofkamigawa/YoseiTheMorningStar.java
+++ b/Mage.Sets/src/mage/sets/championsofkamigawa/YoseiTheMorningStar.java
@@ -28,23 +28,20 @@
package mage.sets.championsofkamigawa;
import java.util.UUID;
-import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Outcome;
-import mage.Constants.PhaseStep;
import mage.Constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.effects.common.SkipNextPlayerUntapStepEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.game.turn.TurnMod;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
@@ -69,7 +66,7 @@ public class YoseiTheMorningStar extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Yosei, the Morning Star dies, target player skips his or her next untap step. Tap up to five target permanents that player controls.
- Ability ability = new DiesTriggeredAbility(new SkipNextUntapStepTargetEffect());
+ Ability ability = new DiesTriggeredAbility(new SkipNextPlayerUntapStepEffect());
ability.addTarget(new TargetPlayer());
ability.addTarget(new YoseiTheMorningStarTarget());
ability.addEffect(new YoseiTheMorningStarTapEffect());
@@ -86,33 +83,6 @@ public class YoseiTheMorningStar extends CardImpl {
}
}
-class SkipNextUntapStepTargetEffect extends OneShotEffect {
-
- public SkipNextUntapStepTargetEffect() {
- super(Constants.Outcome.Detriment);
- staticText = "target player skips his or her next untap step";
- }
-
- public SkipNextUntapStepTargetEffect(SkipNextUntapStepTargetEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- UUID playerId = source.getFirstTarget();
- if (playerId != null) {
- game.getState().getTurnMods().add(new TurnMod(playerId, PhaseStep.UNTAP));
- return true;
- }
- return false;
- }
-
- @Override
- public SkipNextUntapStepTargetEffect copy() {
- return new SkipNextUntapStepTargetEffect();
- }
-}
-
class YoseiTheMorningStarTarget extends TargetPermanent {
public YoseiTheMorningStarTarget() {
diff --git a/Mage.Sets/src/mage/sets/conflux/DragDown.java b/Mage.Sets/src/mage/sets/conflux/DragDown.java
index cc9bf6af9f..13045084e4 100644
--- a/Mage.Sets/src/mage/sets/conflux/DragDown.java
+++ b/Mage.Sets/src/mage/sets/conflux/DragDown.java
@@ -49,7 +49,7 @@ public class DragDown extends CardImpl {
this.color.setBlack(true);
// Domain - Target creature gets -1/-1 until end of turn for each basic land type among lands you control.
- this.getSpellAbility().addEffect(new BoostTargetEffect(new DomainValue(-1), new DomainValue(-1), Duration.EndOfTurn));
+ this.getSpellAbility().addEffect(new BoostTargetEffect(new DomainValue(-1), new DomainValue(-1), Duration.EndOfTurn, true));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage.Sets/src/mage/sets/conflux/MightOfAlara.java b/Mage.Sets/src/mage/sets/conflux/MightOfAlara.java
index a132de6be9..aad1baf79a 100644
--- a/Mage.Sets/src/mage/sets/conflux/MightOfAlara.java
+++ b/Mage.Sets/src/mage/sets/conflux/MightOfAlara.java
@@ -50,7 +50,7 @@ public class MightOfAlara extends CardImpl {
this.color.setGreen(true);
// Domain - Target creature gets +1/+1 until end of turn for each basic land type among lands you control.
- this.getSpellAbility().addEffect(new BoostTargetEffect(new DomainValue(), new DomainValue(), Constants.Duration.EndOfTurn));
+ this.getSpellAbility().addEffect(new BoostTargetEffect(new DomainValue(), new DomainValue(), Constants.Duration.EndOfTurn, true));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage.Sets/src/mage/sets/eventide/CreakwoodGhoul.java b/Mage.Sets/src/mage/sets/eventide/CreakwoodGhoul.java
index 7db5986ee8..7fbb5b3a72 100644
--- a/Mage.Sets/src/mage/sets/eventide/CreakwoodGhoul.java
+++ b/Mage.Sets/src/mage/sets/eventide/CreakwoodGhoul.java
@@ -28,7 +28,6 @@
package mage.sets.eventide;
import java.util.UUID;
-
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
@@ -41,6 +40,7 @@ import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.target.common.TargetCardInGraveyard;
+
/**
*
* @author Loki
diff --git a/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java b/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java
index 4b5a456d72..f3811f9003 100644
--- a/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java
+++ b/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java
@@ -27,6 +27,8 @@
*/
package mage.sets.innistrad;
+
+import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
@@ -40,14 +42,8 @@ import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.counters.CounterType;
import mage.filter.Filter;
-import mage.filter.FilterPermanent;
-import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.common.FilterControlledPermanent;
-import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
-import java.util.UUID;
-
/**
* @author nantuko
*/
diff --git a/Mage.Sets/src/mage/sets/innistrad/ElderOfLaurels.java b/Mage.Sets/src/mage/sets/innistrad/ElderOfLaurels.java
index ab5647abb9..62e66500cf 100644
--- a/Mage.Sets/src/mage/sets/innistrad/ElderOfLaurels.java
+++ b/Mage.Sets/src/mage/sets/innistrad/ElderOfLaurels.java
@@ -60,7 +60,7 @@ public class ElderOfLaurels extends CardImpl {
// {3}{G}: Target creature gets +X/+X until end of turn, where X is the number of creatures you control.
PermanentsOnBattlefieldCount amount = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent());
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
- new BoostTargetEffect(amount, amount, Duration.EndOfTurn),
+ new BoostTargetEffect(amount, amount, Duration.EndOfTurn, true),
new ManaCostsImpl("{3}{G}"));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/sets/mirrodin/ClockworkBeetle.java b/Mage.Sets/src/mage/sets/mirrodin/ClockworkBeetle.java
index fb8e36a572..73778208c2 100644
--- a/Mage.Sets/src/mage/sets/mirrodin/ClockworkBeetle.java
+++ b/Mage.Sets/src/mage/sets/mirrodin/ClockworkBeetle.java
@@ -58,7 +58,7 @@ public class ClockworkBeetle extends CardImpl {
this.power = new MageInt(0);
this.toughness = new MageInt(0);
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), "{this} enters the battlefield with two +1/+1 counters on it"));
- this.addAbility(new AttacksOrBlocksTriggeredAbility(new ClockworkCondorEffect(), false));
+ this.addAbility(new AttacksOrBlocksTriggeredAbility(new ClockworkBeetleEffect(), false));
}
public ClockworkBeetle(final ClockworkBeetle card) {
@@ -87,8 +87,8 @@ class ClockworkBeetleEffect extends OneShotEffect {
if (p != null) {
AtTheEndOfCombatDelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P1.createInstance()));
ability.setSourceId(source.getSourceId());
- ability.setControllerId(source.getControllerId());
- game.addDelayedTriggeredAbility(ability);
+ ability.setControllerId(source.getControllerId());
+ game.addDelayedTriggeredAbility(ability);
}
return false;
}
diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/MightOfTheMasses.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/MightOfTheMasses.java
index f933e29c53..4c3de2144a 100644
--- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/MightOfTheMasses.java
+++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/MightOfTheMasses.java
@@ -51,7 +51,7 @@ public class MightOfTheMasses extends CardImpl {
PermanentsOnBattlefieldCount value = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- this.getSpellAbility().addEffect(new BoostTargetEffect(value, value, Duration.EndOfTurn));
+ this.getSpellAbility().addEffect(new BoostTargetEffect(value, value, Duration.EndOfTurn, true));
}
public MightOfTheMasses(final MightOfTheMasses card) {
diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java
new file mode 100644
index 0000000000..1ece33843b
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KashiTribeElite.java
@@ -0,0 +1,91 @@
+/*
+ * 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.saviorsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.SkipNextUntapTargetEffect;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.effects.common.continious.GainAbilityControlledEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.ShroudAbility;
+import mage.cards.CardImpl;
+import mage.filter.Filter;
+import mage.filter.common.FilterControlledPermanent;
+
+/**
+ *
+ * @author LevelX
+ */
+public class KashiTribeElite extends CardImpl {
+
+ private final static FilterControlledPermanent filter = new FilterControlledPermanent("Legendary Snakes");
+
+ static {
+ filter.getSupertype().add("Legendary");
+ filter.setScopeSupertype(Filter.ComparisonScope.Any);
+ filter.getSubtype().add("Snake");
+ filter.setScopeSubtype(Filter.ComparisonScope.Any);
+ }
+
+ public KashiTribeElite(UUID ownerId) {
+ super(ownerId, 135, "Kashi-Tribe Elite", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}{G}");
+ this.expansionSetCode = "SOK";
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Legendary Snakes you control have shroud. (They can't be the targets of spells or abilities.)
+ this.addAbility(new SimpleStaticAbility(Constants.Zone.BATTLEFIELD, new GainAbilityControlledEffect(ShroudAbility.getInstance(), Constants.Duration.WhileOnBattlefield, filter, false)));
+
+ // Whenever Kashi-Tribe Elite deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step.
+ Ability ability;
+ ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true);
+ ability.addEffect(new SkipNextUntapTargetEffect("and it"));
+ this.addAbility(ability);
+
+ }
+
+ public KashiTribeElite(final KashiTribeElite card) {
+ super(card);
+ }
+
+ @Override
+ public KashiTribeElite copy() {
+ return new KashiTribeElite(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java
new file mode 100644
index 0000000000..df6983909a
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MatsuTribeBirdstalker.java
@@ -0,0 +1,86 @@
+/*
+ * 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.saviorsofkamigawa;
+
+import java.util.UUID;
+import mage.Constants;
+import mage.Constants.CardType;
+import mage.Constants.Rarity;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.SkipNextUntapTargetEffect;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.effects.common.continious.GainAbilityControlledEffect;
+import mage.abilities.effects.common.continious.GainAbilitySourceEffect;
+import mage.abilities.keyword.ReachAbility;
+import mage.abilities.keyword.ShroudAbility;
+import mage.cards.CardImpl;
+import mage.filter.Filter;
+import mage.filter.common.FilterControlledPermanent;
+
+/**
+ *
+ * @author LevelX
+ */
+public class MatsuTribeBirdstalker extends CardImpl {
+
+ public MatsuTribeBirdstalker(UUID ownerId) {
+ super(ownerId, 137, "Matsu-Tribe Birdstalker", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
+ this.expansionSetCode = "SOK";
+ this.subtype.add("Snake");
+ this.subtype.add("Warrior");
+
+ this.color.setGreen(true);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Whenever Kashi-Tribe Elite deals combat damage to a creature, tap that creature and it doesn't untap during its controller's next untap step.
+ Ability ability;
+ ability = new DealsCombatDamageToACreatureTriggeredAbility(new TapTargetEffect("that creature"), false, true);
+ ability.addEffect(new SkipNextUntapTargetEffect("and it"));
+ this.addAbility(ability);
+
+ // {G}: Matsu-Tribe Birdstalker gains reach until end of turn. (It can block creatures with flying.)
+ this.addAbility(new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD,
+ new GainAbilitySourceEffect(ReachAbility.getInstance(), Constants.Duration.EndOfTurn),
+ new ManaCostsImpl("{G}")));
+ }
+
+ public MatsuTribeBirdstalker(final MatsuTribeBirdstalker card) {
+ super(card);
+ }
+
+ @Override
+ public MatsuTribeBirdstalker copy() {
+ return new MatsuTribeBirdstalker(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage/src/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java b/Mage/src/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java
index 3d8bb53995..877257bfa6 100644
--- a/Mage/src/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java
+++ b/Mage/src/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java
@@ -42,7 +42,7 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
+
+ private boolean setTargetPointer;
+
+ public DealsCombatDamageToACreatureTriggeredAbility(Effect effect, boolean optional) {
+ this(effect, optional, false);
+ }
+
+ public DealsCombatDamageToACreatureTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer) {
+ super(Zone.BATTLEFIELD, effect, optional);
+ this.setTargetPointer = setTargetPointer;
+ }
+
+ public DealsCombatDamageToACreatureTriggeredAbility(final DealsCombatDamageToACreatureTriggeredAbility ability) {
+ super(ability);
+ this.setTargetPointer = ability.setTargetPointer;
+ }
+
+ @Override
+ public DealsCombatDamageToACreatureTriggeredAbility copy() {
+ return new DealsCombatDamageToACreatureTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event.getType() == EventType.DAMAGED_CREATURE) {
+ if (event.getSourceId().equals(this.sourceId)
+ && ((DamagedCreatureEvent) event).isCombatDamage()) {
+ if (setTargetPointer) {
+ for (Effect effect : this.getEffects()) {
+ effect.setTargetPointer(new FixedTarget(event.getTargetId()));
+ effect.setValue("damage", event.getAmount());
+ }
+ }
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever {this} deals combat damage to a creature, " + super.getRule();
+ }
+
+}
diff --git a/Mage/src/mage/abilities/condition/common/CardsInHandCondition.java b/Mage/src/mage/abilities/condition/common/CardsInHandCondition.java
new file mode 100644
index 0000000000..fdb5aaf363
--- /dev/null
+++ b/Mage/src/mage/abilities/condition/common/CardsInHandCondition.java
@@ -0,0 +1,85 @@
+/*
+ * 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.condition.common;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.game.Game;
+
+/**
+ * Cards in controller hand condition. This condition can decorate other conditions
+ * as well as be used standalone.
+ *
+ *
+ * @author LevelX
+ */
+public class CardsInHandCondition implements Condition {
+
+ public static enum CountType { MORE_THAN, FEWER_THAN, EQUAL_TO };
+ private Condition condition;
+ private CountType type;
+ private int count;
+
+ public CardsInHandCondition() {
+ this(CountType.EQUAL_TO, 0);
+ }
+
+ public CardsInHandCondition (CountType type, int count ) {
+ this.type = type;
+ this.count = count;
+ }
+
+ public CardsInHandCondition (CountType type, int count, Condition conditionToDecorate ) {
+ this(type, count);
+ this.condition = conditionToDecorate;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ boolean conditionApplies = false;
+
+ switch ( this.type ) {
+ case FEWER_THAN:
+ conditionApplies = game.getPlayer(source.getControllerId()).getHand().size() < this.count;
+ break;
+ case MORE_THAN:
+ conditionApplies = game.getPlayer(source.getControllerId()).getHand().size() > this.count;
+ break;
+ case EQUAL_TO:
+ conditionApplies = game.getPlayer(source.getControllerId()).getHand().size() == this.count;
+ break;
+ }
+
+ //If a decorated condition exists, check it as well and apply them together.
+ if ( this.condition != null ) {
+ conditionApplies = conditionApplies && this.condition.apply(game, source);
+ }
+
+ return conditionApplies;
+ }
+}
diff --git a/Mage/src/mage/abilities/effects/common/SacrificeControllerEffect.java b/Mage/src/mage/abilities/effects/common/SacrificeControllerEffect.java
new file mode 100644
index 0000000000..ef495fcfca
--- /dev/null
+++ b/Mage/src/mage/abilities/effects/common/SacrificeControllerEffect.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import mage.abilities.Ability;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.filter.FilterPermanent;
+import mage.game.Game;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author LevelX
+ */
+public class SacrificeControllerEffect extends SacrificeEffect {
+
+
+ public SacrificeControllerEffect ( FilterPermanent filter, DynamicValue count, String preText ) {
+ super(filter, count, preText);
+ }
+
+ public SacrificeControllerEffect ( FilterPermanent filter, int count, String preText ) {
+ this(filter, new StaticValue(count), preText);
+ }
+
+ public SacrificeControllerEffect (final SacrificeControllerEffect effect ) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ this.targetPointer = new FixedTarget(source.getControllerId());
+ return super.apply(game, source);
+ }
+
+ @Override
+ public SacrificeControllerEffect copy() {
+ return new SacrificeControllerEffect(this);
+ }
+}
+
diff --git a/Mage/src/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java b/Mage/src/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java
new file mode 100644
index 0000000000..619c4a0131
--- /dev/null
+++ b/Mage/src/mage/abilities/effects/common/SkipNextPlayerUntapStepEffect.java
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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;
+
+import mage.Constants;
+import mage.Constants.PhaseStep;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.game.Game;
+import mage.game.turn.TurnMod;
+import mage.players.Player;
+
+/**
+ *
+ * @author LevelX
+ */
+public class SkipNextPlayerUntapStepEffect extends OneShotEffect {
+
+ public SkipNextPlayerUntapStepEffect() {
+ super(Constants.Outcome.Detriment);
+ }
+
+ public SkipNextPlayerUntapStepEffect(String text) {
+ this();
+ staticText = text;
+ }
+
+ public SkipNextPlayerUntapStepEffect(SkipNextPlayerUntapStepEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (targetPointer != null) {
+ Player player = game.getPlayer(targetPointer.getFirst(source));
+ if (player != null) {
+ game.getState().getTurnMods().add(new TurnMod(player.getId(), PhaseStep.UNTAP));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public SkipNextPlayerUntapStepEffect copy() {
+ return new SkipNextPlayerUntapStepEffect(this);
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ StringBuilder sb = new StringBuilder();
+ if (staticText.length() > 0) {
+ sb.append(staticText);
+ }
+ else {
+ sb.append("target");
+ }
+ sb.append("player skips his or her next untap step");
+ return sb.toString();
+ }
+}
diff --git a/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java b/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java
index ce9b4b953f..157250119d 100644
--- a/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java
+++ b/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java
@@ -54,6 +54,11 @@ public class SkipNextUntapTargetEffect extends ReplacementEffectImpl 0)
+ return staticText + " doesn't untap during its controller's next untap step";
+ else
return "Target " + mode.getTargets().get(0).getTargetName() + " doesn't untap during its controller's next untap step";
}
diff --git a/Mage/src/mage/abilities/effects/common/TapTargetEffect.java b/Mage/src/mage/abilities/effects/common/TapTargetEffect.java
index fa14df58e3..30acdaf498 100644
--- a/Mage/src/mage/abilities/effects/common/TapTargetEffect.java
+++ b/Mage/src/mage/abilities/effects/common/TapTargetEffect.java
@@ -47,6 +47,11 @@ public class TapTargetEffect extends OneShotEffect {
super(Outcome.Tap);
}
+ public TapTargetEffect(String text) {
+ this();
+ this.staticText = text;
+ }
+
public TapTargetEffect(final TapTargetEffect effect) {
super(effect);
}
@@ -71,12 +76,15 @@ public class TapTargetEffect extends OneShotEffect {
@Override
public String getText(Mode mode) {
- Target target = mode.getTargets().get(0);
+ if (staticText.length() > 0)
+ return "tap " + staticText;
+
+ Target target = mode.getTargets().get(0);
if (target.getMaxNumberOfTargets() > 1)
- if (target.getMaxNumberOfTargets() == target.getNumberOfTargets())
- return "tap " + target.getNumberOfTargets() + " target " + mode.getTargets().get(0).getTargetName() + "s";
- else
- return "tap up to " + target.getMaxNumberOfTargets() + " target " + mode.getTargets().get(0).getTargetName() + "s";
+ if (target.getMaxNumberOfTargets() == target.getNumberOfTargets())
+ return "tap " + target.getNumberOfTargets() + " target " + target.getTargetName() + "s";
+ else
+ return "tap up to " + target.getMaxNumberOfTargets() + " target " + target.getTargetName() + "s";
else
return "tap target " + mode.getTargets().get(0).getTargetName();
}
diff --git a/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java b/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java
index cd5f41d547..9f01a5fd7c 100644
--- a/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java
+++ b/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java
@@ -81,7 +81,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl 0) {
diff --git a/Mage/src/mage/abilities/effects/common/continious/BoostTargetEffect.java b/Mage/src/mage/abilities/effects/common/continious/BoostTargetEffect.java
index 8f4d0354dd..787c4f07e2 100644
--- a/Mage/src/mage/abilities/effects/common/continious/BoostTargetEffect.java
+++ b/Mage/src/mage/abilities/effects/common/continious/BoostTargetEffect.java
@@ -49,7 +49,9 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
private DynamicValue power;
private DynamicValue toughness;
-
+ // if true, all dynamic values should be calculated once
+ protected boolean isLockedIn = false;
+
public BoostTargetEffect(int power, int toughness, Duration duration) {
this(new StaticValue(power), new StaticValue(toughness), duration);
}
@@ -59,18 +61,41 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
this.power = power;
this.toughness = toughness;
}
+ /**
+ * @param power power value to boost
+ * @param toughness toughness value to boost
+ * @param duration how long does the effecct apply
+ * @param continuousCalculation true = power and toughness will be calculated continuously
+ * false = power and toughness will be calculated once during resolution
+ */
+ public BoostTargetEffect(DynamicValue power, DynamicValue toughness, Duration duration, boolean isLockedIn) {
+ super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
+ this.power = power;
+ this.toughness = toughness;
+ this.isLockedIn = isLockedIn;
+ }
public BoostTargetEffect(final BoostTargetEffect effect) {
super(effect);
this.power = effect.power.clone();
this.toughness = effect.toughness.clone();
+ this.isLockedIn = effect.isLockedIn;
}
@Override
public BoostTargetEffect copy() {
return new BoostTargetEffect(this);
}
-
+
+ @Override
+ public void init(Ability source, Game game) {
+ super.init(source, game);
+ if (isLockedIn) {
+ power = new StaticValue(power.calculate(game, source));
+ toughness = new StaticValue(toughness.calculate(game, source));
+ }
+ }
+
@Override
public boolean apply(Game game, Ability source) {
int affectedTargets = 0;
@@ -115,4 +140,8 @@ public class BoostTargetEffect extends ContinuousEffectImpl {
sb.append(message);
return sb.toString();
}
+
+ public void setLockedIn(boolean isLockedIn) {
+ this.isLockedIn =isLockedIn;
+ }
}
diff --git a/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java b/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java
index 4a35e52418..9b037a015c 100644
--- a/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java
+++ b/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java
@@ -37,7 +37,6 @@ import mage.abilities.effects.ContinuousEffectImpl;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.game.permanent.PermanentToken;
/**
*
@@ -105,7 +104,12 @@ public class GainAbilityAllEffect extends ContinuousEffectImpl {
private String rarity;
private String cardNumber;
private String artist;
+ private Card otherSide;
public Card(Integer multiverseId) {
this.multiverseId = multiverseId;
}
public Card(String card) {
- String[] split = card.split("\\|",13);
+ String[] split = card.split("\\|", 13);
if (split[0].length() > 0) {
multiverseId = Integer.parseInt(split[0]);
}
@@ -160,6 +161,14 @@ public class Card implements Comparable {
this.types = types;
}
+ public Card getOtherSide() {
+ return otherSide;
+ }
+
+ public void setOtherSide(Card otherSide) {
+ this.otherSide = otherSide;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -193,10 +202,15 @@ public class Card implements Comparable {
sb.append(rarity != null ? rarity : "").append("|");
sb.append(cardNumber != null ? cardNumber : "").append("|");
sb.append(artist != null ? artist : "");
+
+ if (otherSide != null) {
+ sb.append("\n").append(otherSide.toString());
+ }
return sb.toString();
}
public int compareTo(Card o) {
- return this.multiverseId.compareTo(o.getMultiverseId());
+ int idCompareResult = this.multiverseId.compareTo(o.getMultiverseId());
+ return idCompareResult == 0 ? this.cardNumber.compareTo(o.getCardNumber()) : idCompareResult;
}
}
diff --git a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardParser.java b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardParser.java
index 2b97ead046..448c94745a 100644
--- a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardParser.java
+++ b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardParser.java
@@ -5,6 +5,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import north.gatherercrawler.util.CardsList;
+import north.gatherercrawler.util.ParseQueue;
+import north.gatherercrawler.util.ParsedList;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@@ -22,11 +25,10 @@ public class CardParser extends Thread {
private boolean parseCard(Integer multiverseId) {
String url = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId;
- Card card = new Card(multiverseId);
+ Card card;
Document doc = null;
- int retries = 30;
boolean done = false;
- while (retries > 0 && !done) {
+ while (!done) {
try {
Connection connection = Jsoup.connect(url);
connection.timeout(20000);
@@ -41,113 +43,155 @@ public class CardParser extends Thread {
}
try {
- Elements select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContentHeader_subtitleDisplay");
- String cardName = "";
- String selectorModifier = "";
+ Elements select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_nameRow .value");
if (!select.isEmpty()) {
- cardName = select.get(0).text().trim();
- }
+ card = extractCardData(doc, "", multiverseId);
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_rightCol ul li a");
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_nameRow .value");
- if (!select.isEmpty()) {
- card.setName(select.get(0).text().trim());
+ // for multi-part cards
+ if (!select.isEmpty()) {
+ String href = select.attr("href");
+ url = "http://gatherer.wizards.com/Pages/Card/Details.aspx" + href.substring(href.indexOf("?"));
+
+ done = false;
+ while (!done) {
+ try {
+ Connection connection = Jsoup.connect(url);
+ connection.timeout(20000);
+ doc = connection.get();
+ } catch (IOException ex) {
+ }
+ done = true;
+ }
+ if (!done) {
+ System.out.println("Card get exception: " + multiverseId);
+ } else {
+ card.setCardNumber(card.getCardNumber() + "b");
+ Card cardSide = extractCardData(doc, "", multiverseId);
+ cardSide.setCardNumber(cardSide.getCardNumber() + "a");
+ cardSide.setOtherSide(card);
+ card = cardSide;
+ }
+ }
} else {
- card.setName(cardName);
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_ctl05_nameRow .value");
- if (!select.isEmpty() && select.get(0).text().trim().equals(cardName)) {
- selectorModifier = "_ctl05";
- } else {
- selectorModifier = "_ctl06";
+ // for flip / double sided cards
+ card = extractCardData(doc, "_ctl05", multiverseId);
+ if (card == null) {
+ return false;
}
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_manaRow .value img");
- List manaCost = new ArrayList();
- if (!select.isEmpty()) {
- for (Element element : select) {
- manaCost.add(element.attr("src").replace("/Handlers/Image.ashx?size=medium&name=", "").replace("&type=symbol", "").replaceAll("\" alt=\"[\\d\\w\\s]+?\" align=\"absbottom\" />", ""));
+ card.setOtherSide(extractCardData(doc, "_ctl06", multiverseId));
+ if (card.getOtherSide() == null) {
+ return false;
}
}
- card.setManaCost(manaCost);
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_cmcRow .value");
- if (!select.isEmpty()) {
- card.setConvertedManaCost(Integer.parseInt(select.get(0).text().trim()));
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_typeRow .value");
- if (!select.isEmpty()) {
- card.setTypes(select.get(0).text().trim());
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_textRow .value .cardtextbox");
- List cardText = new ArrayList();
- if (!select.isEmpty()) {
- for (Element element : select) {
- cardText.add(element.html().trim().replace("", "").replace("\n", "").replace(""", "\""));
- }
- }
- card.setCardText(cardText);
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_FlavorText .cardtextbox");
- List flavorText = new ArrayList();
- if (!select.isEmpty()) {
- for (Element element : select) {
- flavorText.add(element.html().trim().replace(""", "\"").replace("", "").replace("", ""));
- }
- }
- card.setFlavorText(flavorText);
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_ptRow .value");
- if (!select.isEmpty()) {
- card.setPowerToughness(select.get(0).text().trim());
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_currentSetSymbol a");
- if (!select.isEmpty()) {
- card.setExpansion(select.get(1).text().trim());
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_rarityRow .value span");
- if (!select.isEmpty()) {
- card.setRarity(select.get(0).text().trim());
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_otherSetsValue a");
- List otherSets = new ArrayList();
- if (!select.isEmpty()) {
- for (Element element : select) {
- otherSets.add(Integer.parseInt(element.attr("href").replace("Details.aspx?multiverseid=", "")));
- }
- }
-// card.setOtherSets(otherSets);
- for (Integer otherSet : otherSets) {
- if (!ParsedList.contains(otherSet)) {
- ParseQueue.add(otherSet);
- }
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_numberRow .value");
- if (!select.isEmpty()) {
- card.setCardNumber(select.get(0).text().trim());
- }
-
- select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_ArtistCredit a");
- if (!select.isEmpty()) {
- card.setArtist(select.get(0).text().trim());
- }
} catch (Exception e) {
return false;
}
+
+ if (card == null) {
+ return false;
+ }
+ CardsList.add(card);
+ return true;
+ }
+
+ private Card extractCardData(Document doc, String selectorModifier, Integer id) throws NumberFormatException {
+ Elements select;
+
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_cardImage");
+ Integer multiverseId = null;
+ if (!select.isEmpty()) {
+ Pattern pattern = Pattern.compile("(?<=multiverseid=)\\d+");
+ Matcher matcher = pattern.matcher(select.get(0).attr("src"));
+ if (matcher.find()) {
+ multiverseId = Integer.parseInt(matcher.group());
+ }
+ }
+ if (multiverseId == null) {
+ return null;
+ }
+
+ Card card = new Card(multiverseId);
+
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_nameRow .value");
+ if (!select.isEmpty()) {
+ card.setName(select.get(0).text().trim());
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_manaRow .value img");
+ List manaCost = new ArrayList();
+ if (!select.isEmpty()) {
+ for (Element element : select) {
+ manaCost.add(element.attr("src").replace("/Handlers/Image.ashx?size=medium&name=", "").replace("&type=symbol", "").replaceAll("\" alt=\"[\\d\\w\\s]+?\" align=\"absbottom\" />", ""));
+ }
+ }
+ card.setManaCost(manaCost);
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_cmcRow .value");
+ if (!select.isEmpty()) {
+ card.setConvertedManaCost(Integer.parseInt(select.get(0).text().trim()));
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_typeRow .value");
+ if (!select.isEmpty()) {
+ card.setTypes(select.get(0).text().trim());
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_textRow .value .cardtextbox");
+ List cardText = new ArrayList();
+ if (!select.isEmpty()) {
+ for (Element element : select) {
+ cardText.add(element.html().trim().replace("", "").replace("\n", "").replace(""", "\""));
+ }
+ }
+ card.setCardText(cardText);
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_FlavorText .cardtextbox");
+ List flavorText = new ArrayList();
+ if (!select.isEmpty()) {
+ for (Element element : select) {
+ flavorText.add(element.html().trim().replace(""", "\"").replace("", "").replace("", ""));
+ }
+ }
+ card.setFlavorText(flavorText);
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_ptRow .value");
+ if (!select.isEmpty()) {
+ card.setPowerToughness(select.get(0).text().trim());
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_currentSetSymbol a");
+ if (!select.isEmpty()) {
+ card.setExpansion(select.get(1).text().trim());
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_rarityRow .value span");
+ if (!select.isEmpty()) {
+ card.setRarity(select.get(0).text().trim());
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_otherSetsValue a");
+ List otherSets = new ArrayList();
+ if (!select.isEmpty()) {
+ for (Element element : select) {
+ otherSets.add(Integer.parseInt(element.attr("href").replace("Details.aspx?multiverseid=", "")));
+ }
+ }
+ // card.setOtherSets(otherSets);
+ for (Integer otherSet : otherSets) {
+ if (!ParsedList.contains(otherSet)) {
+ ParseQueue.add(otherSet);
+ }
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_numberRow .value");
+ if (!select.isEmpty()) {
+ card.setCardNumber(select.get(0).text().trim());
+ }
+ select = doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent" + selectorModifier + "_ArtistCredit a");
+ if (!select.isEmpty()) {
+ card.setArtist(select.get(0).text().trim());
+ }
+
if (card.getCardNumber() == null) {
- url = "http://magiccards.info/query?q=" + card.getName().replace(' ', '+');
+ String url = "http://magiccards.info/query?q=" + card.getName().replace(' ', '+');
try {
Connection connection = Jsoup.connect(url);
connection.timeout(20000);
doc = connection.get();
- Elements select = doc.select("small a:contains(" + card.getExpansion() + ")");
+ select = doc.select("small a:contains(" + card.getExpansion() + ")");
if (!select.isEmpty()) {
Matcher matcher = patternUrl.matcher(select.get(0).attr("href"));
matcher.find();
@@ -166,7 +210,7 @@ public class CardParser extends Thread {
}
if (card.getCardNumber() == null) {
- Elements select = doc.select("p a:contains(" + card.getExpansion() + ")");
+ select = doc.select("p a:contains(" + card.getExpansion() + ")");
if (!select.isEmpty()) {
Matcher matcher = patternUrl.matcher(select.get(0).attr("href"));
matcher.find();
@@ -183,8 +227,8 @@ public class CardParser extends Thread {
System.out.println("Card number missing: " + card.getName());
}
}
- CardsList.add(card);
- return true;
+
+ return card;
}
@Override
diff --git a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/Main.java b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/Main.java
index 0cae3e9dd2..8d785e612a 100644
--- a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/Main.java
+++ b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/Main.java
@@ -1,12 +1,11 @@
package north.gatherercrawler;
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.*;
import java.util.ArrayList;
import java.util.List;
+import north.gatherercrawler.util.CardsList;
+import north.gatherercrawler.util.ParseQueue;
+import north.gatherercrawler.util.ParsedList;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
diff --git a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ThreadStarter.java b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ThreadStarter.java
index 15f728e335..3fd770e29c 100644
--- a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ThreadStarter.java
+++ b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ThreadStarter.java
@@ -2,8 +2,8 @@ package north.gatherercrawler;
import java.io.BufferedWriter;
import java.io.FileWriter;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
+import north.gatherercrawler.util.CardsList;
/**
*
@@ -13,16 +13,35 @@ public class ThreadStarter extends Thread {
private static Integer threadsDone = 0;
private final Integer threads = 10;
+ private List sortedCards;
public static synchronized void threadDone() {
threadsDone++;
}
+ private void updateSortedCards() {
+ if (sortedCards == null) {
+ sortedCards = new ArrayList();
+ Iterator iterator = CardsList.iterator();
+ while (iterator.hasNext()) {
+ sortedCards.add(iterator.next());
+ }
+
+ Collections.sort(sortedCards, new Comparator() {
+
+ public int compare(Card o1, Card o2) {
+ int expansionCompare = o1.getExpansion().compareTo(o2.getExpansion());
+ return expansionCompare != 0 ? expansionCompare : o1.getCardNumber().compareTo(o2.getCardNumber());
+ }
+ });
+ }
+ }
+
private void writeCardsToFile() {
try {
FileWriter fstream = new FileWriter("cards-data.txt");
BufferedWriter out = new BufferedWriter(fstream);
- Iterator iterator = CardsList.iterator();
+ Iterator iterator = sortedCards.iterator();
while (iterator.hasNext()) {
out.write(iterator.next().toString());
out.newLine();
@@ -37,7 +56,7 @@ public class ThreadStarter extends Thread {
try {
FileWriter fstream = new FileWriter("mtg-cards-data.txt");
BufferedWriter out = new BufferedWriter(fstream);
- Iterator iterator = CardsList.iterator();
+ Iterator iterator = sortedCards.iterator();
while (iterator.hasNext()) {
Card card = iterator.next();
StringBuilder sb = new StringBuilder();
@@ -79,7 +98,7 @@ public class ThreadStarter extends Thread {
} else {
sb.append("||");
}
-
+
List cardText = card.getCardText();
for (int i = 0; i < cardText.size(); i++) {
sb.append(cardText.get(i));
@@ -114,6 +133,7 @@ public class ThreadStarter extends Thread {
}
}
+ updateSortedCards();
writeCardsToFile();
writeCardsToUtilFile();
}
diff --git a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardsList.java b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/CardsList.java
similarity index 87%
rename from Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardsList.java
rename to Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/CardsList.java
index 41bf308e03..7e6ea0086a 100644
--- a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/CardsList.java
+++ b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/CardsList.java
@@ -1,7 +1,8 @@
-package north.gatherercrawler;
+package north.gatherercrawler.util;
import java.util.Iterator;
import java.util.concurrent.ConcurrentSkipListSet;
+import north.gatherercrawler.Card;
/**
*
diff --git a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ParseQueue.java b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/ParseQueue.java
similarity index 94%
rename from Utils/GathererCrawler/src/main/java/north/gatherercrawler/ParseQueue.java
rename to Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/ParseQueue.java
index d99ea042c6..c45b763095 100644
--- a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ParseQueue.java
+++ b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/ParseQueue.java
@@ -1,4 +1,4 @@
-package north.gatherercrawler;
+package north.gatherercrawler.util;
import java.util.concurrent.ConcurrentLinkedQueue;
diff --git a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ParsedList.java b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/ParsedList.java
similarity index 93%
rename from Utils/GathererCrawler/src/main/java/north/gatherercrawler/ParsedList.java
rename to Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/ParsedList.java
index 2efe8253a7..caa39038d7 100644
--- a/Utils/GathererCrawler/src/main/java/north/gatherercrawler/ParsedList.java
+++ b/Utils/GathererCrawler/src/main/java/north/gatherercrawler/util/ParsedList.java
@@ -1,4 +1,4 @@
-package north.gatherercrawler;
+package north.gatherercrawler.util;
import java.util.concurrent.ConcurrentSkipListSet;
diff --git a/pom.xml b/pom.xml
index ed43700a5b..80d813fb7c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,16 @@
+
+
+
+ org.sqlite
+ sqlite
+ 0.5.6
+
+
+
+
0.8.2
diff --git a/repository/install-maven.bat b/repository/install-maven.bat
new file mode 100644
index 0000000000..8373a9d011
--- /dev/null
+++ b/repository/install-maven.bat
@@ -0,0 +1 @@
+mvn install:install-file -DgroupId=org.sqlite -DartifactId=sqlite -Dversion=0.5.6 -Dpackaging=jar -Dfile=./org/sqlite/sqlitejdbc-v056.jar
\ No newline at end of file
diff --git a/repository/install-maven.sh b/repository/install-maven.sh
new file mode 100644
index 0000000000..8373a9d011
--- /dev/null
+++ b/repository/install-maven.sh
@@ -0,0 +1 @@
+mvn install:install-file -DgroupId=org.sqlite -DartifactId=sqlite -Dversion=0.5.6 -Dpackaging=jar -Dfile=./org/sqlite/sqlitejdbc-v056.jar
\ No newline at end of file
diff --git a/repository/org/sqlite/sqlitejdbc-v056.jar b/repository/org/sqlite/sqlitejdbc-v056.jar
new file mode 100644
index 0000000000..f95d90eb07
Binary files /dev/null and b/repository/org/sqlite/sqlitejdbc-v056.jar differ