mirror of
https://github.com/magefree/mage.git
synced 2026-01-24 20:29:19 -08:00
Merge origin/master
This commit is contained in:
commit
6925bd6d7d
89 changed files with 1584 additions and 683 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -82,6 +82,7 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target
|
||||||
|
|
||||||
*.classpath
|
*.classpath
|
||||||
*.iml
|
*.iml
|
||||||
|
hs_err*.log
|
||||||
/submitted
|
/submitted
|
||||||
|
|
||||||
/Mage.Server/config/ai.please.cast.this.txt
|
/Mage.Server/config/ai.please.cast.this.txt
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
XMage.de 1 (Europe/Germany) fast :xmage.de:17171
|
XMage.de 1 (Europe/Germany) fast :xmage.de:17171
|
||||||
woogerworks (North America/USA) :xmage.woogerworks.info:17171
|
woogerworks (North America/USA) :xmage.woogerworks.info:17171
|
||||||
XMage.info 1 (Europe/France) new network code -> see forum :176.31.186.181:17171
|
XMage Testserver (Europe/France) 1.4.8v0 :176.31.186.181:17171
|
||||||
XMage BR (South America/Brazil) :ec2-54-233-67-0.sa-east-1.compute.amazonaws.com:17171
|
XMage BR (South America/Brazil) :ec2-54-233-67-0.sa-east-1.compute.amazonaws.com:17171
|
||||||
Seedds Server (Asia) :115.29.203.80:17171
|
Seedds Server (Asia) :115.29.203.80:17171
|
||||||
localhost -> connect to your local server (must be started):localhost:17171
|
localhost -> connect to your local server (must be started):localhost:17171
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TableWaitingDialog.java
|
* TableWaitingDialog.java
|
||||||
*
|
*
|
||||||
* Created on Dec 16, 2009, 10:27:44 AM
|
* Created on Dec 16, 2009, 10:27:44 AM
|
||||||
|
|
@ -68,7 +68,7 @@ public class TableWaitingDialog extends MageDialog {
|
||||||
private Session session;
|
private Session session;
|
||||||
private final TableWaitModel tableWaitModel;
|
private final TableWaitModel tableWaitModel;
|
||||||
private UpdateSeatsTask updateTask;
|
private UpdateSeatsTask updateTask;
|
||||||
private static final int[] defaultColumnsWidth = {20, 50, 100, 100};
|
private static final int[] defaultColumnsWidth = {20, 50, 100, 100, 100};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form TableWaitingDialog
|
* Creates new form TableWaitingDialog
|
||||||
|
|
@ -268,10 +268,8 @@ public class TableWaitingDialog extends MageDialog {
|
||||||
if (session.startMatch(roomId, tableId)) {
|
if (session.startMatch(roomId, tableId)) {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
}
|
}
|
||||||
} else {
|
} else if (session.startTournament(roomId, tableId)) {
|
||||||
if (session.startTournament(roomId, tableId)) {
|
closeDialog();
|
||||||
closeDialog();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}//GEN-LAST:event_btnStartActionPerformed
|
}//GEN-LAST:event_btnStartActionPerformed
|
||||||
|
|
||||||
|
|
@ -319,7 +317,7 @@ public class TableWaitingDialog extends MageDialog {
|
||||||
|
|
||||||
class TableWaitModel extends AbstractTableModel {
|
class TableWaitModel extends AbstractTableModel {
|
||||||
|
|
||||||
private final String[] columnNames = new String[]{"Seat", "Loc", "Player Name", "Player Type"};
|
private final String[] columnNames = new String[]{"Seat", "Loc", "Player Name", "Player Type", "History"};
|
||||||
private SeatView[] seats = new SeatView[0];
|
private SeatView[] seats = new SeatView[0];
|
||||||
|
|
||||||
public void loadData(TableView table) {
|
public void loadData(TableView table) {
|
||||||
|
|
@ -353,6 +351,8 @@ class TableWaitModel extends AbstractTableModel {
|
||||||
return seats[arg0].getPlayerName();
|
return seats[arg0].getPlayerName();
|
||||||
case 3:
|
case 3:
|
||||||
return seats[arg0].getPlayerType();
|
return seats[arg0].getPlayerType();
|
||||||
|
case 4:
|
||||||
|
return seats[arg0].getHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PlayerPanel.java
|
* PlayerPanel.java
|
||||||
*
|
*
|
||||||
* Created on Nov 18, 2009, 3:01:31 PM
|
* Created on Nov 18, 2009, 3:01:31 PM
|
||||||
|
|
@ -288,7 +288,8 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
basicTooltipText = "<HTML>Name: " + player.getName()
|
basicTooltipText = "<HTML>Name: " + player.getName()
|
||||||
+ "<br/>Country: " + countryname
|
+ "<br/>Country: " + countryname
|
||||||
+ "<br/>Deck hash code: " + player.getDeckHashCode()
|
+ "<br/>Deck hash code: " + player.getDeckHashCode()
|
||||||
+ "<br/>Wins: " + player.getWins() + " of " + player.getWinsNeeded() + " (to win the match)";
|
+ "<br/>This match wins: " + player.getWins() + " of " + player.getWinsNeeded() + " (to win the match)"
|
||||||
|
+ (player.getUserData() == null ? "" : "<br/>History: " + player.getUserData().getHistory());
|
||||||
}
|
}
|
||||||
// Extend tooltip
|
// Extend tooltip
|
||||||
StringBuilder tooltipText = new StringBuilder(basicTooltipText);
|
StringBuilder tooltipText = new StringBuilder(basicTooltipText);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ChatPanel.java
|
* ChatPanel.java
|
||||||
*
|
*
|
||||||
* Created on 15-Dec-2009, 11:04:31 PM
|
* Created on 15-Dec-2009, 11:04:31 PM
|
||||||
|
|
@ -61,7 +61,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private final List<String> players = new ArrayList<>();
|
private final List<String> players = new ArrayList<>();
|
||||||
private final UserTableModel userTableModel;
|
private final UserTableModel userTableModel;
|
||||||
private static final int[] defaultColumnsWidth = {20, 100, 100, 100, 80, 80};
|
private static final int[] DEFAULT_COLUMNS_WIDTH = {20, 100, 100, 80, 80};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -78,7 +78,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
||||||
jTablePlayers.setForeground(Color.white);
|
jTablePlayers.setForeground(Color.white);
|
||||||
jTablePlayers.setRowSorter(new MageTableRowSorter(userTableModel));
|
jTablePlayers.setRowSorter(new MageTableRowSorter(userTableModel));
|
||||||
|
|
||||||
TableUtil.setColumnWidthAndOrder(jTablePlayers, defaultColumnsWidth, KEY_USERS_COLUMNS_WIDTH, KEY_USERS_COLUMNS_ORDER);
|
TableUtil.setColumnWidthAndOrder(jTablePlayers, DEFAULT_COLUMNS_WIDTH, KEY_USERS_COLUMNS_WIDTH, KEY_USERS_COLUMNS_ORDER);
|
||||||
jTablePlayers.setDefaultRenderer(Icon.class, new CountryCellRenderer());
|
jTablePlayers.setDefaultRenderer(Icon.class, new CountryCellRenderer());
|
||||||
|
|
||||||
jScrollPaneTalk.setSystemMessagesPane(colorPaneSystem);
|
jScrollPaneTalk.setSystemMessagesPane(colorPaneSystem);
|
||||||
|
|
@ -118,7 +118,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
class UserTableModel extends AbstractTableModel {
|
class UserTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
private final String[] columnNames = new String[]{"Loc", "Players", "History", "Info", "Games", "Connection"};
|
private final String[] columnNames = new String[]{"Loc", "Players", "History", "Games", "Connection"};
|
||||||
private UsersView[] players = new UsersView[0];
|
private UsersView[] players = new UsersView[0];
|
||||||
|
|
||||||
public void loadData(Collection<RoomUsersView> roomUserInfoList) throws MageRemoteException {
|
public void loadData(Collection<RoomUsersView> roomUserInfoList) throws MageRemoteException {
|
||||||
|
|
@ -128,7 +128,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
||||||
TableColumnModel tcm = th.getColumnModel();
|
TableColumnModel tcm = th.getColumnModel();
|
||||||
|
|
||||||
tcm.getColumn(jTablePlayers.convertColumnIndexToView(1)).setHeaderValue("Players (" + this.players.length + ")");
|
tcm.getColumn(jTablePlayers.convertColumnIndexToView(1)).setHeaderValue("Players (" + this.players.length + ")");
|
||||||
tcm.getColumn(jTablePlayers.convertColumnIndexToView(4)).setHeaderValue(
|
tcm.getColumn(jTablePlayers.convertColumnIndexToView(3)).setHeaderValue(
|
||||||
"Games " + roomUserInfo.getNumberActiveGames()
|
"Games " + roomUserInfo.getNumberActiveGames()
|
||||||
+ (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (")
|
+ (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (")
|
||||||
+ " limit: " + roomUserInfo.getNumberMaxGames() + ")");
|
+ " limit: " + roomUserInfo.getNumberMaxGames() + ")");
|
||||||
|
|
@ -156,10 +156,8 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
||||||
case 2:
|
case 2:
|
||||||
return players[arg0].getHistory();
|
return players[arg0].getHistory();
|
||||||
case 3:
|
case 3:
|
||||||
return players[arg0].getInfoState();
|
|
||||||
case 4:
|
|
||||||
return players[arg0].getInfoGames();
|
return players[arg0].getInfoGames();
|
||||||
case 5:
|
case 4:
|
||||||
return players[arg0].getInfoPing();
|
return players[arg0].getInfoPing();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
/**
|
/**
|
||||||
* DownloadJob.java
|
* DownloadJob.java
|
||||||
*
|
*
|
||||||
* Created on 25.08.2010
|
* Created on 25.08.2010
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.mage.plugins.card.dl;
|
package org.mage.plugins.card.dl;
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -21,25 +19,26 @@ import org.mage.plugins.card.dl.beans.properties.Property;
|
||||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||||
import org.mage.plugins.card.utils.CardImageUtils;
|
import org.mage.plugins.card.utils.CardImageUtils;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class DownloadJob.
|
* The class DownloadJob.
|
||||||
*
|
*
|
||||||
* @version V0.0 25.08.2010
|
* @version V0.0 25.08.2010
|
||||||
* @author Clemens Koza
|
* @author Clemens Koza
|
||||||
*/
|
*/
|
||||||
public class DownloadJob extends AbstractLaternaBean {
|
public class DownloadJob extends AbstractLaternaBean {
|
||||||
|
|
||||||
public static enum State {
|
public static enum State {
|
||||||
|
|
||||||
NEW, WORKING, FINISHED, ABORTED;
|
NEW, WORKING, FINISHED, ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Source source;
|
private final Source source;
|
||||||
private final Destination destination;
|
private final Destination destination;
|
||||||
private final Property<State> state = properties.property("state", State.NEW);
|
private final Property<State> state = properties.property("state", State.NEW);
|
||||||
private final Property<String> message = properties.property("message");
|
private final Property<String> message = properties.property("message");
|
||||||
private final Property<Exception> error = properties.property("error");
|
private final Property<Exception> error = properties.property("error");
|
||||||
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
||||||
|
|
||||||
public DownloadJob(String name, Source source, Destination destination) {
|
public DownloadJob(String name, Source source, Destination destination) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
@ -48,7 +47,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the job's state. If the state is {@link State#ABORTED}, it instead sets the error to "ABORTED"
|
* Sets the job's state. If the state is {@link State#ABORTED}, it instead
|
||||||
|
* sets the error to "ABORTED"
|
||||||
|
*
|
||||||
* @param state
|
* @param state
|
||||||
*/
|
*/
|
||||||
public void setState(State state) {
|
public void setState(State state) {
|
||||||
|
|
@ -60,8 +61,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the job's state to {@link State#ABORTED} and the error message to the given message. Logs a warning
|
* Sets the job's state to {@link State#ABORTED} and the error message to
|
||||||
* with the given message.
|
* the given message. Logs a warning with the given message.
|
||||||
|
*
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
public void setError(String message) {
|
public void setError(String message) {
|
||||||
|
|
@ -69,8 +71,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the job's state to {@link State#ABORTED} and the error to the given exception. Logs a warning with the
|
* Sets the job's state to {@link State#ABORTED} and the error to the given
|
||||||
* given exception.
|
* exception. Logs a warning with the given exception.
|
||||||
|
*
|
||||||
* @param error
|
* @param error
|
||||||
*/
|
*/
|
||||||
public void setError(Exception error) {
|
public void setError(Exception error) {
|
||||||
|
|
@ -78,14 +81,15 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the job's state to {@link State#ABORTED} and the error to the given exception. Logs a warning with the
|
* Sets the job's state to {@link State#ABORTED} and the error to the given
|
||||||
* given message and exception.
|
* exception. Logs a warning with the given message and exception.
|
||||||
|
*
|
||||||
* @param message
|
* @param message
|
||||||
* @param error
|
* @param error
|
||||||
*/
|
*/
|
||||||
public void setError(String message, Exception error) {
|
public void setError(String message, Exception error) {
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
|
|
||||||
message = "Download of " + this.getName() + "from " + this.getSource().toString() + " caused error: " + error.toString();
|
message = "Download of " + this.getName() + "from " + this.getSource().toString() + " caused error: " + error.toString();
|
||||||
}
|
}
|
||||||
// log.warn(message, error);
|
// log.warn(message, error);
|
||||||
|
|
@ -97,6 +101,7 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the job's message.
|
* Sets the job's message.
|
||||||
|
*
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
public void setMessage(String message) {
|
public void setMessage(String message) {
|
||||||
|
|
@ -119,7 +124,6 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
return message.getValue();
|
return message.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
@ -163,9 +167,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return proxy != null ? proxy.type().toString()+" " :"" + url;
|
return proxy != null ? proxy.type().toString() + " " : "" + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,11 +193,11 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
public int length() throws IOException {
|
public int length() throws IOException {
|
||||||
return getConnection().getContentLength();
|
return getConnection().getContentLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return proxy != null ? proxy.type().toString()+" " :"" + url;
|
return proxy != null ? proxy.type().toString() + " " : "" + url;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,6 +217,14 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
return new FileOutputStream(file);
|
return new FileOutputStream(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() throws IOException {
|
||||||
|
if (file.isFile()) {
|
||||||
|
return file.length() > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean exists() {
|
public boolean exists() {
|
||||||
return file.isFile();
|
return file.isFile();
|
||||||
|
|
@ -228,16 +240,20 @@ public class DownloadJob extends AbstractLaternaBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Source {
|
public interface Source {
|
||||||
|
|
||||||
InputStream open() throws IOException;
|
InputStream open() throws IOException;
|
||||||
|
|
||||||
int length() throws IOException;
|
int length() throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Destination {
|
public interface Destination {
|
||||||
|
|
||||||
OutputStream open() throws IOException;
|
OutputStream open() throws IOException;
|
||||||
|
|
||||||
boolean exists() throws IOException;
|
boolean exists() throws IOException;
|
||||||
|
|
||||||
|
boolean isValid() throws IOException;
|
||||||
|
|
||||||
void delete() throws IOException;
|
void delete() throws IOException;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* Downloader.java
|
* Downloader.java
|
||||||
*
|
*
|
||||||
* Created on 25.08.2010
|
* Created on 25.08.2010
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.mage.plugins.card.dl;
|
package org.mage.plugins.card.dl;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
|
@ -29,10 +28,9 @@ import org.mage.plugins.card.dl.DownloadJob.Source;
|
||||||
import org.mage.plugins.card.dl.DownloadJob.State;
|
import org.mage.plugins.card.dl.DownloadJob.State;
|
||||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class Downloader.
|
* The class Downloader.
|
||||||
*
|
*
|
||||||
* @version V0.0 25.08.2010
|
* @version V0.0 25.08.2010
|
||||||
* @author Clemens Koza
|
* @author Clemens Koza
|
||||||
*/
|
*/
|
||||||
|
|
@ -40,16 +38,16 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Downloader.class);
|
private static final Logger logger = Logger.getLogger(Downloader.class);
|
||||||
|
|
||||||
private final List<DownloadJob> jobs = properties.list("jobs");
|
private final List<DownloadJob> jobs = properties.list("jobs");
|
||||||
private final Channel<DownloadJob> channel = new MemoryChannel<>();
|
private final Channel<DownloadJob> channel = new MemoryChannel<>();
|
||||||
|
|
||||||
private final ExecutorService pool = Executors.newCachedThreadPool();
|
private final ExecutorService pool = Executors.newCachedThreadPool();
|
||||||
private final List<Fiber> fibers = new ArrayList<>();
|
private final List<Fiber> fibers = new ArrayList<>();
|
||||||
|
|
||||||
public Downloader() {
|
public Downloader() {
|
||||||
PoolFiberFactory f = new PoolFiberFactory(pool);
|
PoolFiberFactory f = new PoolFiberFactory(pool);
|
||||||
//subscribe multiple fibers for parallel execution
|
//subscribe multiple fibers for parallel execution
|
||||||
for(int i = 0, numThreads = 10; i < numThreads; i++) {
|
for (int i = 0, numThreads = 10; i < numThreads; i++) {
|
||||||
Fiber fiber = f.create();
|
Fiber fiber = f.create();
|
||||||
fiber.start();
|
fiber.start();
|
||||||
fibers.add(fiber);
|
fibers.add(fiber);
|
||||||
|
|
@ -59,15 +57,15 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(DownloadJob j:getJobs()) {
|
for (DownloadJob j : getJobs()) {
|
||||||
switch(j.getState()) {
|
switch (j.getState()) {
|
||||||
case NEW:
|
case NEW:
|
||||||
case WORKING:
|
case WORKING:
|
||||||
j.setState(State.ABORTED);
|
j.setState(State.ABORTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Fiber f:fibers) {
|
for (Fiber f : fibers) {
|
||||||
f.dispose();
|
f.dispose();
|
||||||
}
|
}
|
||||||
pool.shutdown();
|
pool.shutdown();
|
||||||
|
|
@ -84,10 +82,10 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(DownloadJob job) {
|
public void add(DownloadJob job) {
|
||||||
if(job.getState() == State.WORKING) {
|
if (job.getState() == State.WORKING) {
|
||||||
throw new IllegalArgumentException("Job already running");
|
throw new IllegalArgumentException("Job already running");
|
||||||
}
|
}
|
||||||
if(job.getState() == State.FINISHED) {
|
if (job.getState() == State.FINISHED) {
|
||||||
throw new IllegalArgumentException("Job already finished");
|
throw new IllegalArgumentException("Job already finished");
|
||||||
}
|
}
|
||||||
job.setState(State.NEW);
|
job.setState(State.NEW);
|
||||||
|
|
@ -100,15 +98,17 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the download job: Transfers data from {@link Source} to {@link Destination} and updates the
|
* Performs the download job: Transfers data from {@link Source} to
|
||||||
* download job's state to reflect the progress.
|
* {@link Destination} and updates the download job's state to reflect the
|
||||||
|
* progress.
|
||||||
*/
|
*/
|
||||||
private class DownloadCallback implements Callback<DownloadJob> {
|
private class DownloadCallback implements Callback<DownloadJob> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(DownloadJob job) {
|
public void onMessage(DownloadJob job) {
|
||||||
//the job won't be processed by multiple threads
|
//the job won't be processed by multiple threads
|
||||||
synchronized(job) {
|
synchronized (job) {
|
||||||
if(job.getState() != State.NEW) {
|
if (job.getState() != State.NEW) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
job.setState(State.WORKING);
|
job.setState(State.WORKING);
|
||||||
|
|
@ -118,10 +118,17 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
Destination dst = job.getDestination();
|
Destination dst = job.getDestination();
|
||||||
BoundedRangeModel progress = job.getProgress();
|
BoundedRangeModel progress = job.getProgress();
|
||||||
|
|
||||||
if(dst.exists()) {
|
if (dst.isValid()) {
|
||||||
progress.setMaximum(1);
|
progress.setMaximum(1);
|
||||||
progress.setValue(1);
|
progress.setValue(1);
|
||||||
} else {
|
} else {
|
||||||
|
if (dst.exists()) {
|
||||||
|
try {
|
||||||
|
dst.delete();
|
||||||
|
} catch (IOException ex1) {
|
||||||
|
logger.warn("While deleting not valid file", ex1);
|
||||||
|
}
|
||||||
|
}
|
||||||
progress.setMaximum(src.length());
|
progress.setMaximum(src.length());
|
||||||
InputStream is = new BufferedInputStream(src.open());
|
InputStream is = new BufferedInputStream(src.open());
|
||||||
try {
|
try {
|
||||||
|
|
@ -129,45 +136,45 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
||||||
try {
|
try {
|
||||||
byte[] buf = new byte[8 * 1024];
|
byte[] buf = new byte[8 * 1024];
|
||||||
int total = 0;
|
int total = 0;
|
||||||
for(int len; (len = is.read(buf)) != -1;) {
|
for (int len; (len = is.read(buf)) != -1;) {
|
||||||
if(job.getState() == State.ABORTED) {
|
if (job.getState() == State.ABORTED) {
|
||||||
throw new IOException("Job was aborted");
|
throw new IOException("Job was aborted");
|
||||||
}
|
}
|
||||||
progress.setValue(total += len);
|
progress.setValue(total += len);
|
||||||
os.write(buf, 0, len);
|
os.write(buf, 0, len);
|
||||||
}
|
}
|
||||||
} catch(IOException ex) {
|
} catch (IOException ex) {
|
||||||
try {
|
try {
|
||||||
dst.delete();
|
dst.delete();
|
||||||
} catch(IOException ex1) {
|
} catch (IOException ex1) {
|
||||||
logger.warn("While deleting", ex1);
|
logger.warn("While deleting", ex1);
|
||||||
}
|
}
|
||||||
throw ex;
|
throw ex;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
os.close();
|
os.close();
|
||||||
} catch(IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.warn("While closing", ex);
|
logger.warn("While closing", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
} catch(IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.warn("While closing", ex);
|
logger.warn("While closing", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.setState(State.FINISHED);
|
job.setState(State.FINISHED);
|
||||||
} catch(ConnectException ex) {
|
} catch (ConnectException ex) {
|
||||||
String message;
|
String message;
|
||||||
if (ex.getMessage() != null) {
|
if (ex.getMessage() != null) {
|
||||||
message = ex.getMessage();
|
message = ex.getMessage();
|
||||||
} else {
|
} else {
|
||||||
message = "Unknown error";
|
message = "Unknown error";
|
||||||
}
|
}
|
||||||
logger.warn("Error resource download " + job.getName() +" from "+ job.getSource().toString() + ": " + message);
|
logger.warn("Error resource download " + job.getName() + " from " + job.getSource().toString() + ": " + message);
|
||||||
} catch(IOException ex) {
|
} catch (IOException ex) {
|
||||||
job.setError(ex);
|
job.setError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-common</artifactId>
|
<artifactId>mage-common</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
||||||
*/
|
*/
|
||||||
public final static int MAGE_VERSION_MAJOR = 1;
|
public final static int MAGE_VERSION_MAJOR = 1;
|
||||||
public final static int MAGE_VERSION_MINOR = 4;
|
public final static int MAGE_VERSION_MINOR = 4;
|
||||||
public final static int MAGE_VERSION_PATCH = 7;
|
public final static int MAGE_VERSION_PATCH = 8;
|
||||||
public final static String MAGE_VERSION_MINOR_PATCH = "v1";
|
public final static String MAGE_VERSION_MINOR_PATCH = "v0";
|
||||||
public final static String MAGE_VERSION_INFO = "";
|
public final static String MAGE_VERSION_INFO = "";
|
||||||
|
|
||||||
private final int major;
|
private final int major;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ public class SeatView implements Serializable {
|
||||||
private UUID playerId;
|
private UUID playerId;
|
||||||
private final String playerName;
|
private final String playerName;
|
||||||
private final String playerType;
|
private final String playerType;
|
||||||
|
private final String history;
|
||||||
|
|
||||||
public SeatView(Seat seat) {
|
public SeatView(Seat seat) {
|
||||||
if (seat.getPlayer() != null) {
|
if (seat.getPlayer() != null) {
|
||||||
|
|
@ -51,13 +52,16 @@ public class SeatView implements Serializable {
|
||||||
this.playerName = seat.getPlayer().getName();
|
this.playerName = seat.getPlayer().getName();
|
||||||
if (seat.getPlayer().getUserData() == null) {
|
if (seat.getPlayer().getUserData() == null) {
|
||||||
this.flagName = UserData.getDefaultFlagName();
|
this.flagName = UserData.getDefaultFlagName();
|
||||||
|
this.history = "";
|
||||||
} else {
|
} else {
|
||||||
this.flagName = seat.getPlayer().getUserData().getFlagName();
|
this.flagName = seat.getPlayer().getUserData().getFlagName();
|
||||||
|
this.history = seat.getPlayer().getUserData().getHistory();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Empty seat
|
// Empty seat
|
||||||
this.playerName = "";
|
this.playerName = "";
|
||||||
this.flagName = "";
|
this.flagName = "";
|
||||||
|
this.history = "";
|
||||||
}
|
}
|
||||||
this.playerType = seat.getPlayerType();
|
this.playerType = seat.getPlayerType();
|
||||||
}
|
}
|
||||||
|
|
@ -78,4 +82,8 @@ public class SeatView implements Serializable {
|
||||||
return flagName;
|
return flagName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHistory() {
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
package mage.view;
|
package mage.view;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -40,15 +40,13 @@ public class UsersView implements Serializable {
|
||||||
private final String flagName;
|
private final String flagName;
|
||||||
private final String userName;
|
private final String userName;
|
||||||
private final String history;
|
private final String history;
|
||||||
private final String infoState;
|
|
||||||
private final String infoGames;
|
private final String infoGames;
|
||||||
private final String infoPing;
|
private final String infoPing;
|
||||||
|
|
||||||
public UsersView(String flagName, String userName, String history, String infoState, String infoGames, String infoPing) {
|
public UsersView(String flagName, String userName, String history, String infoGames, String infoPing) {
|
||||||
this.flagName = flagName;
|
this.flagName = flagName;
|
||||||
this.history = history;
|
this.history = history;
|
||||||
this.userName = userName;
|
this.userName = userName;
|
||||||
this.infoState = infoState;
|
|
||||||
this.infoGames = infoGames;
|
this.infoGames = infoGames;
|
||||||
this.infoPing = infoPing;
|
this.infoPing = infoPing;
|
||||||
}
|
}
|
||||||
|
|
@ -65,10 +63,6 @@ public class UsersView implements Serializable {
|
||||||
return history;
|
return history;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInfoState() {
|
|
||||||
return infoState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getInfoGames() {
|
public String getInfoGames() {
|
||||||
return infoGames;
|
return infoGames;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-plugins</artifactId>
|
<artifactId>mage-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-counter-plugin</artifactId>
|
<artifactId>mage-counter-plugin</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-plugins</artifactId>
|
<artifactId>mage-plugins</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-deck-constructed</artifactId>
|
<artifactId>mage-deck-constructed</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-deck-limited</artifactId>
|
<artifactId>mage-deck-limited</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-game-commanderduel</artifactId>
|
<artifactId>mage-game-commanderduel</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-game-commanderfreeforall</artifactId>
|
<artifactId>mage-game-commanderfreeforall</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-game-freeforall</artifactId>
|
<artifactId>mage-game-freeforall</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-game-momirduel</artifactId>
|
<artifactId>mage-game-momirduel</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-game-tinyleadersduel</artifactId>
|
<artifactId>mage-game-tinyleadersduel</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-game-twoplayerduel</artifactId>
|
<artifactId>mage-game-twoplayerduel</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-player-ai-draftbot</artifactId>
|
<artifactId>mage-player-ai-draftbot</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-player-ai-ma</artifactId>
|
<artifactId>mage-player-ai-ma</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-player-ai</artifactId>
|
<artifactId>mage-player-ai</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-player-ai-mcts</artifactId>
|
<artifactId>mage-player-ai-mcts</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-player-aiminimax</artifactId>
|
<artifactId>mage-player-aiminimax</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-player-human</artifactId>
|
<artifactId>mage-player-human</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -358,15 +358,13 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (target.canTarget(response.getUUID(), game)) {
|
||||||
if (target.canTarget(response.getUUID(), game)) {
|
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
target.remove(response.getUUID());
|
||||||
target.remove(response.getUUID());
|
} else {
|
||||||
} else {
|
target.addTarget(response.getUUID(), null, game);
|
||||||
target.addTarget(response.getUUID(), null, game);
|
if (target.doneChosing()) {
|
||||||
if (target.doneChosing()) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -530,12 +528,10 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
if (response.getUUID() != null) {
|
if (response.getUUID() != null) {
|
||||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it
|
if (target.getTargets().contains(response.getUUID())) { // if already included remove it
|
||||||
target.remove(response.getUUID());
|
target.remove(response.getUUID());
|
||||||
} else {
|
} else if (target.canTarget(response.getUUID(), cards, game)) {
|
||||||
if (target.canTarget(response.getUUID(), cards, game)) {
|
target.addTarget(response.getUUID(), source, game);
|
||||||
target.addTarget(response.getUUID(), source, game);
|
if (target.doneChosing()) {
|
||||||
if (target.doneChosing()) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1065,10 +1061,8 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
// does not block yet and can block or can block more attackers
|
// does not block yet and can block or can block more attackers
|
||||||
if (filter.match(blocker, null, playerId, game)) {
|
if (filter.match(blocker, null, playerId, game)) {
|
||||||
selectCombatGroup(defendingPlayerId, blocker.getId(), game);
|
selectCombatGroup(defendingPlayerId, blocker.getId(), game);
|
||||||
} else {
|
} else if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) {
|
||||||
if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) {
|
removeBlocker = true;
|
||||||
removeBlocker = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeBlocker) {
|
if (removeBlocker) {
|
||||||
|
|
@ -1546,4 +1540,9 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
pass(game);
|
pass(game);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHistory() {
|
||||||
|
return "no available";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-tournament-boosterdraft</artifactId>
|
<artifactId>mage-tournament-boosterdraft</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-tournament-constructed</artifactId>
|
<artifactId>mage-tournament-constructed</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-tournament-sealed</artifactId>
|
<artifactId>mage-tournament-sealed</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-server-plugins</artifactId>
|
<artifactId>mage-server-plugins</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,17 @@
|
||||||
userNamePattern - pattern for user name validity check
|
userNamePattern - pattern for user name validity check
|
||||||
maxAiOpponents - number of allowed AI opponents on the server
|
maxAiOpponents - number of allowed AI opponents on the server
|
||||||
saveGameActivated - allow game save and replay options (not working correctly yet)
|
saveGameActivated - allow game save and replay options (not working correctly yet)
|
||||||
|
authenticationActivated - "true" = user have to register to signon "false" = user need not to register
|
||||||
|
* mail configs only needed if authentication is activated:
|
||||||
|
* if mailUser = "" mailgun is used otherwise nativ mail server on the system
|
||||||
|
googleAccount - not supported currently
|
||||||
|
mailgunApiKey - key from the mailgun domain e.g. = "key-12121111..."
|
||||||
|
mailgunDomain - domain for the mailgun message sending
|
||||||
|
mailSmtpHost - hostname to send the mail
|
||||||
|
mailSmtpPort - port to send the mail
|
||||||
|
mailUser - username used to send the mail
|
||||||
|
mailPassword - passworf of the used user to send the mail
|
||||||
|
mailFromAddress - sender address
|
||||||
-->
|
-->
|
||||||
<server serverAddress="0.0.0.0"
|
<server serverAddress="0.0.0.0"
|
||||||
serverName="mage-server"
|
serverName="mage-server"
|
||||||
|
|
@ -37,10 +48,15 @@
|
||||||
maxPasswordLength="100"
|
maxPasswordLength="100"
|
||||||
maxAiOpponents="15"
|
maxAiOpponents="15"
|
||||||
saveGameActivated="false"
|
saveGameActivated="false"
|
||||||
authenticationActivated="false"
|
authenticationActivated="true"
|
||||||
googleAccount=""
|
googleAccount=""
|
||||||
mailgunApiKey=""
|
mailgunApiKey="key-d93e81f19a9c9ed243ebb7cc9381385c"
|
||||||
mailgunDomain=""
|
mailgunDomain="sandbox401a433f30d445309a5e86b6c53f7812.mailgun.org"
|
||||||
|
mailSmtpHost="smtp.1und1.de"
|
||||||
|
mailSmtpPort="465"
|
||||||
|
mailUser="xmageserver@online.de"
|
||||||
|
mailPassword="24wrsfxv"
|
||||||
|
mailFromAddress="xmageserver@online.de"
|
||||||
/>
|
/>
|
||||||
<playerTypes>
|
<playerTypes>
|
||||||
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-server</artifactId>
|
<artifactId>mage-server</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,36 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
|
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
|
||||||
|
<!--
|
||||||
|
serverAddress - ip of the XMage server. Set it to "0.0.0.0" for local host or to the IP the server should use
|
||||||
|
port - the port the primary server socket is bound to
|
||||||
|
secondaryBindPort - the port to which the secondary server socket is to be bound. if "-1" is set , an arbitrary port is selected.
|
||||||
|
backlogSize - the preferred number of unaccepted incoming connections allowed at a given time. The actual number may be greater
|
||||||
|
than the specified backlog. When the queue is full, further connection requests are rejected. The JBoss default value is 200
|
||||||
|
numAcceptThreads - the number of threads listening on the ServerSocket. The JBoss default value is 1
|
||||||
|
maxPoolSize - the maximum number of ServerThreads that can exist at any given time. The JBoss default value is 300
|
||||||
|
leasePeriod - To turn on server side connection failure detection of remoting clients, it is necessary to satisfy two criteria.
|
||||||
|
The first is that the client lease period is set and is a value greater than 0. The value is represented in milliseconds.
|
||||||
|
The client lease period can be set by either the 'clientLeasePeriod' attribute within the Connector configuration or by calling the Connector method
|
||||||
|
maxGameThreads - Number of games that can be started simultanously on the server
|
||||||
|
maxSecondsIdle - Number of seconds after that a game is auto conceded by the player that was idle for such a time
|
||||||
|
minUserNameLength - minmal allowed length of a user name to connect to the server
|
||||||
|
maxUserNameLength - maximal allowed length of a user name to connect to the server
|
||||||
|
userNamePattern - pattern for user name validity check
|
||||||
|
maxAiOpponents - number of allowed AI opponents on the server
|
||||||
|
saveGameActivated - allow game save and replay options (not working correctly yet)
|
||||||
|
authenticationActivated - "true" = user have to register to signon "false" = user need not to register
|
||||||
|
* mail configs only needed if authentication is activated:
|
||||||
|
* if mailUser = "" mailgun is used otherwise nativ mail server on the system
|
||||||
|
googleAccount - not supported currently
|
||||||
|
mailgunApiKey - key from the mailgun domain e.g. = "key-12121111..."
|
||||||
|
mailgunDomain - domain for the mailgun message sending
|
||||||
|
mailSmtpHost - hostname to send the mail
|
||||||
|
mailSmtpPort - port to send the mail
|
||||||
|
mailUser - username used to send the mail
|
||||||
|
mailPassword - passworf of the used user to send the mail
|
||||||
|
mailFromAddress - sender address
|
||||||
|
-->
|
||||||
<server serverAddress="0.0.0.0"
|
<server serverAddress="0.0.0.0"
|
||||||
serverName="mage-server"
|
serverName="mage-server"
|
||||||
port="17171"
|
port="17171"
|
||||||
|
|
@ -18,6 +48,13 @@
|
||||||
saveGameActivated="false"
|
saveGameActivated="false"
|
||||||
authenticationActivated="false"
|
authenticationActivated="false"
|
||||||
googleAccount=""
|
googleAccount=""
|
||||||
|
mailgunApiKey=""
|
||||||
|
mailgunDomain=""
|
||||||
|
mailSmtpHost=""
|
||||||
|
mailSmtpPort=""
|
||||||
|
mailUser=""
|
||||||
|
mailPassword=""
|
||||||
|
mailFromAddress=""
|
||||||
/>
|
/>
|
||||||
<playerTypes>
|
<playerTypes>
|
||||||
<playerType name="Human" jar="mage-player-human-${project.version}.jar" className="mage.player.human.HumanPlayer"/>
|
<playerType name="Human" jar="mage-player-human-${project.version}.jar" className="mage.player.human.HumanPlayer"/>
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.server;
|
package mage.server;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -44,14 +43,15 @@ import org.apache.log4j.Logger;
|
||||||
public class ChatManager {
|
public class ChatManager {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ChatManager.class);
|
private static final Logger logger = Logger.getLogger(ChatManager.class);
|
||||||
|
|
||||||
private static final ChatManager INSTANCE = new ChatManager();
|
private static final ChatManager INSTANCE = new ChatManager();
|
||||||
|
|
||||||
public static ChatManager getInstance() {
|
public static ChatManager getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChatManager() {}
|
private ChatManager() {
|
||||||
|
}
|
||||||
|
|
||||||
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
@ -66,16 +66,16 @@ public class ChatManager {
|
||||||
if (chatSession != null) {
|
if (chatSession != null) {
|
||||||
chatSession.join(userId);
|
chatSession.join(userId);
|
||||||
} else {
|
} else {
|
||||||
logger.trace("Chat to join not found - chatId: " + chatId +" userId: " + userId);
|
logger.trace("Chat to join not found - chatId: " + chatId + " userId: " + userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leaveChat(UUID chatId, UUID userId) {
|
public void leaveChat(UUID chatId, UUID userId) {
|
||||||
ChatSession chatSession = chatSessions.get(chatId);
|
ChatSession chatSession = chatSessions.get(chatId);
|
||||||
if (chatSession != null && chatSession.hasUser(userId)) {
|
if (chatSession != null && chatSession.hasUser(userId)) {
|
||||||
chatSession.kill(userId, DisconnectReason.CleaningUp);
|
chatSession.kill(userId, DisconnectReason.CleaningUp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroyChatSession(UUID chatId) {
|
public void destroyChatSession(UUID chatId) {
|
||||||
|
|
@ -88,7 +88,7 @@ public class ChatManager {
|
||||||
logger.trace("Chat removed - chatId: " + chatId);
|
logger.trace("Chat removed - chatId: " + chatId);
|
||||||
} else {
|
} else {
|
||||||
logger.trace("Chat to destroy does not exist - chatId: " + chatId);
|
logger.trace("Chat to destroy does not exist - chatId: " + chatId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,63 +119,56 @@ public class ChatManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean performUserCommand(User user, String message, UUID chatId) {
|
private boolean performUserCommand(User user, String message, UUID chatId) {
|
||||||
String command = message.substring(1).trim().toUpperCase(Locale.ENGLISH);
|
String command = message.substring(1).trim().toUpperCase(Locale.ENGLISH);
|
||||||
if (command.equals("I") || command.equals("INFO")) {
|
if (command.startsWith("H ") || command.startsWith("HISTORY ")) {
|
||||||
user.setInfo("");
|
message = UserManager.getInstance().getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9));
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (command.startsWith("I ") || command.startsWith("INFO ")) {
|
|
||||||
user.setInfo(message.substring(command.startsWith("I ") ? 3 : 6));
|
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (command.startsWith("W ") || command.startsWith("WHISPER ")) {
|
if (command.startsWith("W ") || command.startsWith("WHISPER ")) {
|
||||||
String rest = message.substring(command.startsWith("W ")? 3 : 9);
|
String rest = message.substring(command.startsWith("W ") ? 3 : 9);
|
||||||
int first = rest.indexOf(" ");
|
int first = rest.indexOf(" ");
|
||||||
if (first > 1) {
|
if (first > 1) {
|
||||||
String userToName = rest.substring(0,first);
|
String userToName = rest.substring(0, first);
|
||||||
rest = rest.substring(first + 1).trim();
|
rest = rest.substring(first + 1).trim();
|
||||||
User userTo = UserManager.getInstance().getUserByName(userToName);
|
User userTo = UserManager.getInstance().getUserByName(userToName);
|
||||||
if (userTo != null) {
|
if (userTo != null) {
|
||||||
if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo, rest)) {
|
if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo, rest)) {
|
||||||
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (command.equals("L") || command.equals("LIST")) {
|
if (command.equals("L") || command.equals("LIST")) {
|
||||||
message += new StringBuilder("<br/>List of commands:")
|
message += new StringBuilder("<br/>List of commands:")
|
||||||
.append("<br/>\\info [text] - set a info text to your player")
|
.append("<br/>\\history or \\h [username] - shows the history of a player")
|
||||||
.append("<br/>\\list - Show a list of commands")
|
.append("<br/>\\list or \\l - Show a list of commands")
|
||||||
.append("<br/>\\whisper [player name] [text] - whisper to the player with the given name").toString();
|
.append("<br/>\\whisper or \\w [player name] [text] - whisper to the player with the given name").toString();
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* use mainly for announcing that a user connection was lost or that a user has reconnected
|
* use mainly for announcing that a user connection was lost or that a user
|
||||||
*
|
* has reconnected
|
||||||
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
* @param message
|
* @param message
|
||||||
* @param color
|
* @param color
|
||||||
*/
|
*/
|
||||||
public void broadcast(UUID userId, String message, MessageColor color) {
|
public void broadcast(UUID userId, String message, MessageColor color) {
|
||||||
User user = UserManager.getInstance().getUser(userId);
|
User user = UserManager.getInstance().getUser(userId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
for (ChatSession chat: chatSessions.values()) {
|
for (ChatSession chat : chatSessions.values()) {
|
||||||
if (chat.hasUser(userId)) {
|
if (chat.hasUser(userId)) {
|
||||||
chat.broadcast(user.getName(), message, color);
|
chat.broadcast(user.getName(), message, color);
|
||||||
}
|
}
|
||||||
|
|
@ -186,16 +179,16 @@ public class ChatManager {
|
||||||
public void sendReconnectMessage(UUID userId) {
|
public void sendReconnectMessage(UUID userId) {
|
||||||
User user = UserManager.getInstance().getUser(userId);
|
User user = UserManager.getInstance().getUser(userId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
for (ChatSession chat: chatSessions.values()) {
|
for (ChatSession chat : chatSessions.values()) {
|
||||||
if (chat.hasUser(userId)) {
|
if (chat.hasUser(userId)) {
|
||||||
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS);
|
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeUser(UUID userId, DisconnectReason reason) {
|
public void removeUser(UUID userId, DisconnectReason reason) {
|
||||||
for (ChatSession chatSession: chatSessions.values()) {
|
for (ChatSession chatSession : chatSessions.values()) {
|
||||||
if (chatSession.hasUser(userId)) {
|
if (chatSession.hasUser(userId)) {
|
||||||
chatSession.kill(userId, reason);
|
chatSession.kill(userId, reason);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ public class MageServerImpl implements MageServer {
|
||||||
private static final Logger logger = Logger.getLogger(MageServerImpl.class);
|
private static final Logger logger = Logger.getLogger(MageServerImpl.class);
|
||||||
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||||
private static final SecureRandom RANDOM = new SecureRandom();
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
private final String adminPassword;
|
private final String adminPassword;
|
||||||
private final boolean testMode;
|
private final boolean testMode;
|
||||||
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
||||||
|
|
@ -140,9 +140,16 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
String authToken = generateAuthToken();
|
String authToken = generateAuthToken();
|
||||||
activeAuthTokens.put(email, authToken);
|
activeAuthTokens.put(email, authToken);
|
||||||
if (!MailgunClient.sendMessage(email, "XMage Password Reset Auth Token",
|
String subject = "XMage Password Reset Auth Token";
|
||||||
"Use this auth token to reset your password: " + authToken + "\n" +
|
String text = "Use this auth token to reset your password: " + authToken + "\n"
|
||||||
"It's valid until the next server restart.")) {
|
+ "It's valid until the next server restart.";
|
||||||
|
boolean success;
|
||||||
|
if (!ConfigSettings.getInstance().getMailUser().isEmpty()) {
|
||||||
|
success = MailClient.sendMessage(email, subject, text);
|
||||||
|
} else {
|
||||||
|
success = MailgunClient.sendMessage(email, subject, text);
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
sendErrorMessageToClient(sessionId, "There was an error inside the server while emailing an auth token");
|
sendErrorMessageToClient(sessionId, "There was an error inside the server while emailing an auth token");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
53
Mage.Server/src/main/java/mage/server/MailClient.java
Normal file
53
Mage.Server/src/main/java/mage/server/MailClient.java
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
package mage.server;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import javax.mail.Message;
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.Session;
|
||||||
|
import javax.mail.Transport;
|
||||||
|
import javax.mail.internet.InternetAddress;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import mage.server.util.ConfigSettings;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
public class MailClient {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(Main.class);
|
||||||
|
|
||||||
|
public static boolean sendMessage(String email, String subject, String text) {
|
||||||
|
if (email.length() == 0) {
|
||||||
|
logger.info("Email is not sent because the address is empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ConfigSettings config = ConfigSettings.getInstance();
|
||||||
|
|
||||||
|
Properties properties = System.getProperties();
|
||||||
|
properties.setProperty("mail.smtps.host", config.getMailSmtpHost());
|
||||||
|
properties.setProperty("mail.smtps.port", config.getMailSmtpPort());
|
||||||
|
properties.setProperty("mail.smtps.auth", "true");
|
||||||
|
properties.setProperty("mail.user", config.getMailUser());
|
||||||
|
properties.setProperty("mail.password", config.getMailPassword());
|
||||||
|
|
||||||
|
Session session = Session.getDefaultInstance(properties);
|
||||||
|
|
||||||
|
try{
|
||||||
|
MimeMessage message = new MimeMessage(session);
|
||||||
|
message.setFrom(new InternetAddress(config.getMailFromAddress()));
|
||||||
|
message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
|
||||||
|
message.setSubject(subject);
|
||||||
|
message.setText(text);
|
||||||
|
|
||||||
|
Transport trnsport;
|
||||||
|
trnsport = session.getTransport("smtps");
|
||||||
|
trnsport.connect(null, properties.getProperty("mail.password"));
|
||||||
|
message.saveChanges();
|
||||||
|
trnsport.sendMessage(message, message.getAllRecipients());
|
||||||
|
trnsport.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}catch (MessagingException ex) {
|
||||||
|
logger.error("Error sending message to " + email, ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,20 +32,10 @@ import java.io.FilenameFilter;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.management.MBeanServer;
|
import javax.management.MBeanServer;
|
||||||
import mage.cards.repository.CardScanner;
|
import mage.cards.repository.CardScanner;
|
||||||
import mage.game.match.MatchType;
|
import mage.game.match.MatchType;
|
||||||
import mage.game.result.ResultProtos.MatchPlayerProto;
|
|
||||||
import mage.game.result.ResultProtos.MatchProto;
|
|
||||||
import mage.game.result.ResultProtos.TableProto;
|
|
||||||
import mage.game.result.ResultProtos.TourneyPlayerProto;
|
|
||||||
import mage.game.result.ResultProtos.TourneyProto;
|
|
||||||
import mage.game.result.ResultProtos.UserStatsProto;
|
|
||||||
import mage.game.tournament.TournamentType;
|
import mage.game.tournament.TournamentType;
|
||||||
import mage.interfaces.MageServer;
|
import mage.interfaces.MageServer;
|
||||||
import mage.remote.Connection;
|
import mage.remote.Connection;
|
||||||
|
|
@ -53,9 +43,6 @@ import mage.server.draft.CubeFactory;
|
||||||
import mage.server.game.DeckValidatorFactory;
|
import mage.server.game.DeckValidatorFactory;
|
||||||
import mage.server.game.GameFactory;
|
import mage.server.game.GameFactory;
|
||||||
import mage.server.game.PlayerFactory;
|
import mage.server.game.PlayerFactory;
|
||||||
import mage.server.record.TableRecord;
|
|
||||||
import mage.server.record.TableRecordRepository;
|
|
||||||
import mage.server.record.UserStats;
|
|
||||||
import mage.server.record.UserStatsRepository;
|
import mage.server.record.UserStatsRepository;
|
||||||
import mage.server.tournament.TournamentFactory;
|
import mage.server.tournament.TournamentFactory;
|
||||||
import mage.server.util.ConfigSettings;
|
import mage.server.util.ConfigSettings;
|
||||||
|
|
@ -102,8 +89,6 @@ public class Main {
|
||||||
protected static boolean testMode;
|
protected static boolean testMode;
|
||||||
protected static boolean fastDbMode;
|
protected static boolean fastDbMode;
|
||||||
|
|
||||||
private static final ScheduledExecutorService updateUserStatsTaskExecutor = Executors.newSingleThreadScheduledExecutor();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param args the command line arguments
|
* @param args the command line arguments
|
||||||
*/
|
*/
|
||||||
|
|
@ -132,6 +117,10 @@ public class Main {
|
||||||
}
|
}
|
||||||
logger.info("Done.");
|
logger.info("Done.");
|
||||||
|
|
||||||
|
logger.info("Updating user stats DB...");
|
||||||
|
UserStatsRepository.instance.updateUserStats();
|
||||||
|
logger.info("Done.");
|
||||||
|
|
||||||
deleteSavedGames();
|
deleteSavedGames();
|
||||||
ConfigSettings config = ConfigSettings.getInstance();
|
ConfigSettings config = ConfigSettings.getInstance();
|
||||||
for (GamePlugin plugin : config.getGameTypes()) {
|
for (GamePlugin plugin : config.getGameTypes()) {
|
||||||
|
|
@ -167,7 +156,12 @@ public class Main {
|
||||||
logger.info("Config - auth. activated : " + (config.isAuthenticationActivated() ? "true" : "false"));
|
logger.info("Config - auth. activated : " + (config.isAuthenticationActivated() ? "true" : "false"));
|
||||||
logger.info("Config - mailgun api key : " + config.getMailgunApiKey());
|
logger.info("Config - mailgun api key : " + config.getMailgunApiKey());
|
||||||
logger.info("Config - mailgun domain : " + config.getMailgunDomain());
|
logger.info("Config - mailgun domain : " + config.getMailgunDomain());
|
||||||
//logger.info("Config - google account : " + config.getGoogleAccount());
|
logger.info("Config - mail smtp Host : " + config.getMailSmtpHost());
|
||||||
|
logger.info("Config - mail smtpPort : " + config.getMailSmtpPort());
|
||||||
|
logger.info("Config - mail user : " + config.getMailUser());
|
||||||
|
logger.info("Config - mail passw. len.: " + config.getMailPassword().length());
|
||||||
|
logger.info("Config - mail from addre.: " + config.getMailFromAddress());
|
||||||
|
logger.info("Config - google account : " + config.getGoogleAccount());
|
||||||
|
|
||||||
Connection connection = new Connection("&maxPoolSize=" + config.getMaxPoolSize());
|
Connection connection = new Connection("&maxPoolSize=" + config.getMaxPoolSize());
|
||||||
connection.setHost(config.getServerAddress());
|
connection.setHost(config.getServerAddress());
|
||||||
|
|
@ -190,13 +184,6 @@ public class Main {
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.fatal("Failed to start server - " + connection.toString(), ex);
|
logger.fatal("Failed to start server - " + connection.toString(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUserStatsTaskExecutor.scheduleAtFixedRate(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updateUserStats();
|
|
||||||
}
|
|
||||||
}, 60, 60, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initStatistics() {
|
static void initStatistics() {
|
||||||
|
|
@ -391,78 +378,4 @@ public class Main {
|
||||||
public static boolean isTestMode() {
|
public static boolean isTestMode() {
|
||||||
return testMode;
|
return testMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateUserStats() {
|
|
||||||
long latestEndTimeMs = UserStatsRepository.instance.getLatestEndTimeMs();
|
|
||||||
List<TableRecord> records = TableRecordRepository.instance.getAfter(latestEndTimeMs);
|
|
||||||
for (TableRecord record : records) {
|
|
||||||
TableProto table = record.getProto();
|
|
||||||
if (table.getControllerName().equals("System")) {
|
|
||||||
// This is a sub table within a tournament, so it's already handled by the main
|
|
||||||
// tournament table.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (table.hasMatch()) {
|
|
||||||
MatchProto match = table.getMatch();
|
|
||||||
for (MatchPlayerProto player : match.getPlayersList()) {
|
|
||||||
UserStats userStats = UserStatsRepository.instance.getUser(player.getName());
|
|
||||||
UserStatsProto proto = userStats != null ? userStats.getProto() :
|
|
||||||
UserStatsProto.newBuilder().setName(player.getName()).build();
|
|
||||||
UserStatsProto.Builder builder = UserStatsProto.newBuilder(proto)
|
|
||||||
.setMatches(proto.getMatches() + 1);
|
|
||||||
switch (player.getQuit()) {
|
|
||||||
case IDLE_TIMEOUT:
|
|
||||||
builder.setMatchesIdleTimeout(proto.getMatchesIdleTimeout() + 1);
|
|
||||||
break;
|
|
||||||
case TIMER_TIMEOUT:
|
|
||||||
builder.setMatchesTimerTimeout(proto.getMatchesTimerTimeout() + 1);
|
|
||||||
break;
|
|
||||||
case QUIT:
|
|
||||||
builder.setMatchesQuit(proto.getMatchesQuit() + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (userStats == null) {
|
|
||||||
UserStatsRepository.instance.add(new UserStats(builder.build(), table.getEndTimeMs()));
|
|
||||||
} else {
|
|
||||||
UserStatsRepository.instance.update(new UserStats(builder.build(), table.getEndTimeMs()));
|
|
||||||
}
|
|
||||||
// UserStats for this player is updated, so refresh it.
|
|
||||||
User user = UserManager.getInstance().getUserByName(player.getName());
|
|
||||||
if (user != null) {
|
|
||||||
user.resetUserStats();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (table.hasTourney()) {
|
|
||||||
TourneyProto tourney = table.getTourney();
|
|
||||||
for (TourneyPlayerProto player : tourney.getPlayersList()) {
|
|
||||||
UserStats userStats = UserStatsRepository.instance.getUser(player.getName());
|
|
||||||
UserStatsProto proto = userStats != null ? userStats.getProto() :
|
|
||||||
UserStatsProto.newBuilder().setName(player.getName()).build();
|
|
||||||
UserStatsProto.Builder builder = UserStatsProto.newBuilder(proto)
|
|
||||||
.setTourneys(proto.getTourneys() + 1);
|
|
||||||
switch (player.getQuit()) {
|
|
||||||
case DURING_ROUND:
|
|
||||||
builder.setTourneysQuitDuringRound(proto.getTourneysQuitDuringRound() + 1);
|
|
||||||
break;
|
|
||||||
case DURING_DRAFTING:
|
|
||||||
builder.setTourneysQuitDuringDrafting(proto.getTourneysQuitDuringDrafting() + 1);
|
|
||||||
break;
|
|
||||||
case DURING_CONSTRUCTION:
|
|
||||||
builder.setTourneysQuitDuringConstruction(proto.getTourneysQuitDuringConstruction() + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (userStats == null) {
|
|
||||||
UserStatsRepository.instance.add(new UserStats(builder.build(), table.getEndTimeMs()));
|
|
||||||
} else {
|
|
||||||
UserStatsRepository.instance.update(new UserStats(builder.build(), table.getEndTimeMs()));
|
|
||||||
}
|
|
||||||
// UserStats for this player is updated, so refresh it.
|
|
||||||
User user = UserManager.getInstance().getUserByName(player.getName());
|
|
||||||
if (user != null) {
|
|
||||||
user.resetUserStats();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,8 +99,15 @@ public class Session {
|
||||||
return returnMessage;
|
return returnMessage;
|
||||||
}
|
}
|
||||||
AuthorizedUserRepository.instance.add(userName, password, email);
|
AuthorizedUserRepository.instance.add(userName, password, email);
|
||||||
if (MailgunClient.sendMessage(email, "XMage Registration Completed",
|
String subject = "XMage Registration Completed";
|
||||||
"You are successfully registered as " + userName + ".")) {
|
String text = "You are successfully registered as " + userName + ".";
|
||||||
|
boolean success;
|
||||||
|
if (!ConfigSettings.getInstance().getMailUser().isEmpty()) {
|
||||||
|
success = MailClient.sendMessage(email, subject, text);
|
||||||
|
} else {
|
||||||
|
success = MailgunClient.sendMessage(email, subject, text);
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
logger.info("Sent a registration confirmation email to " + email + " for " + userName);
|
logger.info("Sent a registration confirmation email to " + email + " for " + userName);
|
||||||
} else {
|
} else {
|
||||||
logger.error("Failed sending a registration confirmation email to " + email + " for " + userName);
|
logger.error("Failed sending a registration confirmation email to " + email + " for " + userName);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import mage.cards.decks.Deck;
|
import mage.cards.decks.Deck;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.game.Table;
|
import mage.game.Table;
|
||||||
|
import mage.game.result.ResultProtos;
|
||||||
import mage.game.tournament.TournamentPlayer;
|
import mage.game.tournament.TournamentPlayer;
|
||||||
import mage.interfaces.callback.ClientCallback;
|
import mage.interfaces.callback.ClientCallback;
|
||||||
import mage.players.net.UserData;
|
import mage.players.net.UserData;
|
||||||
|
|
@ -61,7 +62,7 @@ import org.apache.log4j.Logger;
|
||||||
*/
|
*/
|
||||||
public class User {
|
public class User {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(User.class);
|
private static final Logger LOGGER = Logger.getLogger(User.class);
|
||||||
|
|
||||||
public enum UserState {
|
public enum UserState {
|
||||||
|
|
||||||
|
|
@ -81,7 +82,6 @@ public class User {
|
||||||
private final Map<UUID, Deck> sideboarding;
|
private final Map<UUID, Deck> sideboarding;
|
||||||
private final List<UUID> watchedGames;
|
private final List<UUID> watchedGames;
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
private String info = "";
|
|
||||||
private String pingInfo = "";
|
private String pingInfo = "";
|
||||||
private Date lastActivity;
|
private Date lastActivity;
|
||||||
private UserState userState;
|
private UserState userState;
|
||||||
|
|
@ -106,6 +106,7 @@ public class User {
|
||||||
this.watchedGames = new ArrayList<>();
|
this.watchedGames = new ArrayList<>();
|
||||||
this.tablesToDelete = new ArrayList<>();
|
this.tablesToDelete = new ArrayList<>();
|
||||||
this.sessionId = "";
|
this.sessionId = "";
|
||||||
|
this.userStats = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
|
@ -129,15 +130,15 @@ public class User {
|
||||||
if (sessionId.isEmpty()) {
|
if (sessionId.isEmpty()) {
|
||||||
userState = UserState.Disconnected;
|
userState = UserState.Disconnected;
|
||||||
lostConnection();
|
lostConnection();
|
||||||
logger.trace("USER - lost connection: " + userName + " id: " + userId);
|
LOGGER.trace("USER - lost connection: " + userName + " id: " + userId);
|
||||||
|
|
||||||
} else if (userState == UserState.Created) {
|
} else if (userState == UserState.Created) {
|
||||||
userState = UserState.Connected;
|
userState = UserState.Connected;
|
||||||
logger.trace("USER - created: " + userName + " id: " + userId);
|
LOGGER.trace("USER - created: " + userName + " id: " + userId);
|
||||||
} else {
|
} else {
|
||||||
userState = UserState.Reconnected;
|
userState = UserState.Reconnected;
|
||||||
reconnect();
|
reconnect();
|
||||||
logger.trace("USER - reconnected: " + userName + " id: " + userId);
|
LOGGER.trace("USER - reconnected: " + userName + " id: " + userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,12 +274,13 @@ public class User {
|
||||||
|
|
||||||
public boolean isExpired(Date expired) {
|
public boolean isExpired(Date expired) {
|
||||||
if (lastActivity.before(expired)) {
|
if (lastActivity.before(expired)) {
|
||||||
logger.trace(userName + " is expired!");
|
LOGGER.trace(userName + " is expired!");
|
||||||
userState = UserState.Expired;
|
userState = UserState.Expired;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logger.trace(new StringBuilder("isExpired: User ").append(userName).append(" lastActivity: ").append(lastActivity).append(" expired: ").append(expired).toString());
|
LOGGER.trace(new StringBuilder("isExpired: User ").append(userName).append(" lastActivity: ").append(lastActivity).append(" expired: ").append(expired).toString());
|
||||||
return false; /*userState == UserState.Disconnected && */
|
return false;
|
||||||
|
/*userState == UserState.Disconnected && */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,35 +362,35 @@ public class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(DisconnectReason reason) {
|
public void remove(DisconnectReason reason) {
|
||||||
logger.trace("REMOVE " + getName() + " Draft sessions " + draftSessions.size());
|
LOGGER.trace("REMOVE " + getName() + " Draft sessions " + draftSessions.size());
|
||||||
for (DraftSession draftSession : draftSessions.values()) {
|
for (DraftSession draftSession : draftSessions.values()) {
|
||||||
draftSession.setKilled();
|
draftSession.setKilled();
|
||||||
}
|
}
|
||||||
draftSessions.clear();
|
draftSessions.clear();
|
||||||
logger.trace("REMOVE " + getName() + " Tournament sessions " + userTournaments.size());
|
LOGGER.trace("REMOVE " + getName() + " Tournament sessions " + userTournaments.size());
|
||||||
for (UUID tournamentId : userTournaments.values()) {
|
for (UUID tournamentId : userTournaments.values()) {
|
||||||
TournamentManager.getInstance().quit(tournamentId, getId());
|
TournamentManager.getInstance().quit(tournamentId, getId());
|
||||||
}
|
}
|
||||||
userTournaments.clear();
|
userTournaments.clear();
|
||||||
logger.trace("REMOVE " + getName() + " Tables " + tables.size());
|
LOGGER.trace("REMOVE " + getName() + " Tables " + tables.size());
|
||||||
for (Entry<UUID, Table> entry : tables.entrySet()) {
|
for (Entry<UUID, Table> entry : tables.entrySet()) {
|
||||||
logger.debug("-- leave tableId: " + entry.getValue().getId());
|
LOGGER.debug("-- leave tableId: " + entry.getValue().getId());
|
||||||
TableManager.getInstance().leaveTable(userId, entry.getValue().getId());
|
TableManager.getInstance().leaveTable(userId, entry.getValue().getId());
|
||||||
}
|
}
|
||||||
tables.clear();
|
tables.clear();
|
||||||
logger.trace("REMOVE " + getName() + " Game sessions: " + gameSessions.size());
|
LOGGER.trace("REMOVE " + getName() + " Game sessions: " + gameSessions.size());
|
||||||
for (GameSessionPlayer gameSessionPlayer : gameSessions.values()) {
|
for (GameSessionPlayer gameSessionPlayer : gameSessions.values()) {
|
||||||
logger.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId());
|
LOGGER.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId());
|
||||||
GameManager.getInstance().quitMatch(gameSessionPlayer.getGameId(), userId);
|
GameManager.getInstance().quitMatch(gameSessionPlayer.getGameId(), userId);
|
||||||
gameSessionPlayer.quitGame();
|
gameSessionPlayer.quitGame();
|
||||||
}
|
}
|
||||||
gameSessions.clear();
|
gameSessions.clear();
|
||||||
logger.trace("REMOVE " + getName() + " watched Games " + watchedGames.size());
|
LOGGER.trace("REMOVE " + getName() + " watched Games " + watchedGames.size());
|
||||||
for (UUID gameId : watchedGames) {
|
for (UUID gameId : watchedGames) {
|
||||||
GameManager.getInstance().stopWatching(gameId, userId);
|
GameManager.getInstance().stopWatching(gameId, userId);
|
||||||
}
|
}
|
||||||
watchedGames.clear();
|
watchedGames.clear();
|
||||||
logger.trace("REMOVE " + getName() + " Chats ");
|
LOGGER.trace("REMOVE " + getName() + " Chats ");
|
||||||
ChatManager.getInstance().removeUser(userId, reason);
|
ChatManager.getInstance().removeUser(userId, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -397,6 +399,12 @@ public class User {
|
||||||
this.userData.update(userData);
|
this.userData.update(userData);
|
||||||
} else {
|
} else {
|
||||||
this.userData = userData;
|
this.userData = userData;
|
||||||
|
this.userStats = UserStatsRepository.instance.getUser(this.userName);
|
||||||
|
if (userStats != null) {
|
||||||
|
this.userData.setHistory(userStatsToString(userStats.getProto()));
|
||||||
|
} else {
|
||||||
|
this.userData.setHistory("<new player>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -446,11 +454,11 @@ public class User {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// can happen if tournamet has just ended
|
// can happen if tournamet has just ended
|
||||||
logger.debug(getName() + " tournament player missing - tableId:" + table.getId(), null);
|
LOGGER.debug(getName() + " tournament player missing - tableId:" + table.getId(), null);
|
||||||
tablesToDelete.add(tableEntry.getKey());
|
tablesToDelete.add(tableEntry.getKey());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error(getName() + " tournament key missing - tableId: " + table.getId(), null);
|
LOGGER.error(getName() + " tournament key missing - tableId: " + table.getId(), null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (table.getState()) {
|
switch (table.getState()) {
|
||||||
|
|
@ -500,14 +508,6 @@ public class User {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInfo() {
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInfo(String Info) {
|
|
||||||
this.info = Info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addGameWatchInfo(UUID gameId) {
|
public void addGameWatchInfo(UUID gameId) {
|
||||||
watchedGames.add(gameId);
|
watchedGames.add(gameId);
|
||||||
}
|
}
|
||||||
|
|
@ -540,5 +540,84 @@ public class User {
|
||||||
// resetUserStats loads UserStats from DB.
|
// resetUserStats loads UserStats from DB.
|
||||||
public void resetUserStats() {
|
public void resetUserStats() {
|
||||||
this.userStats = UserStatsRepository.instance.getUser(this.userName);
|
this.userStats = UserStatsRepository.instance.getUser(this.userName);
|
||||||
|
if (userData != null) {
|
||||||
|
userData.setHistory(userStatsToString(userStats.getProto()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHistory() {
|
||||||
|
if (userData != null) {
|
||||||
|
return userData.getHistory();
|
||||||
|
}
|
||||||
|
return "<not available>";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String userStatsToString(ResultProtos.UserStatsProto proto) {
|
||||||
|
List<StringBuilder> builders = new ArrayList<>();
|
||||||
|
if (proto.getMatches() > 0) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("Matches:");
|
||||||
|
builder.append(proto.getMatches());
|
||||||
|
List<String> quit = new ArrayList<>();
|
||||||
|
if (proto.getMatchesIdleTimeout() > 0) {
|
||||||
|
quit.add("I:" + Integer.toString(proto.getMatchesIdleTimeout()));
|
||||||
|
}
|
||||||
|
if (proto.getMatchesTimerTimeout() > 0) {
|
||||||
|
quit.add("T:" + Integer.toString(proto.getMatchesTimerTimeout()));
|
||||||
|
}
|
||||||
|
if (proto.getMatchesQuit() > 0) {
|
||||||
|
quit.add("Q:" + Integer.toString(proto.getMatchesQuit()));
|
||||||
|
}
|
||||||
|
if (quit.size() > 0) {
|
||||||
|
builder.append(" (");
|
||||||
|
joinStrings(builder, quit, " ");
|
||||||
|
builder.append(")");
|
||||||
|
}
|
||||||
|
builders.add(builder);
|
||||||
|
}
|
||||||
|
if (proto.getTourneys() > 0) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("Tourneys:");
|
||||||
|
builder.append(proto.getTourneys());
|
||||||
|
List<String> quit = new ArrayList<>();
|
||||||
|
if (proto.getTourneysQuitDuringDrafting() > 0) {
|
||||||
|
quit.add("D:" + Integer.toString(proto.getTourneysQuitDuringDrafting()));
|
||||||
|
}
|
||||||
|
if (proto.getTourneysQuitDuringConstruction() > 0) {
|
||||||
|
quit.add("C:" + Integer.toString(proto.getTourneysQuitDuringConstruction()));
|
||||||
|
}
|
||||||
|
if (proto.getTourneysQuitDuringRound() > 0) {
|
||||||
|
quit.add("R:" + Integer.toString(proto.getTourneysQuitDuringRound()));
|
||||||
|
}
|
||||||
|
if (quit.size() > 0) {
|
||||||
|
builder.append(" (");
|
||||||
|
joinStrings(builder, quit, " ");
|
||||||
|
builder.append(")");
|
||||||
|
}
|
||||||
|
builders.add(builder);
|
||||||
|
}
|
||||||
|
return joinBuilders(builders);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String joinBuilders(List<StringBuilder> builders) {
|
||||||
|
if (builders.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StringBuilder builder = builders.get(0);
|
||||||
|
for (int i = 1; i < builders.size(); ++i) {
|
||||||
|
builder.append(" ");
|
||||||
|
builder.append(builders.get(i));
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void joinStrings(StringBuilder joined, List<String> strings, String separator) {
|
||||||
|
for (int i = 0; i < strings.size(); ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
joined.append(separator);
|
||||||
|
}
|
||||||
|
joined.append(strings.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 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
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 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
|
* 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
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* 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
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
|
@ -38,6 +38,8 @@ import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import mage.server.User.UserState;
|
import mage.server.User.UserState;
|
||||||
|
import mage.server.record.UserStats;
|
||||||
|
import mage.server.record.UserStatsRepository;
|
||||||
import mage.server.util.ThreadExecutor;
|
import mage.server.util.ThreadExecutor;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
@ -45,7 +47,7 @@ import org.apache.log4j.Logger;
|
||||||
*
|
*
|
||||||
* manages users - if a user is disconnected and 10 minutes have passed with no
|
* manages users - if a user is disconnected and 10 minutes have passed with no
|
||||||
* activity the user is removed
|
* activity the user is removed
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class UserManager {
|
public class UserManager {
|
||||||
|
|
@ -56,7 +58,7 @@ public class UserManager {
|
||||||
|
|
||||||
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentHashMap<String, User> usersByName = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, User> usersByName = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||||
|
|
||||||
private static final UserManager INSTANCE = new UserManager();
|
private static final UserManager INSTANCE = new UserManager();
|
||||||
|
|
@ -64,8 +66,8 @@ public class UserManager {
|
||||||
public static UserManager getInstance() {
|
public static UserManager getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserManager() {
|
private UserManager() {
|
||||||
expireExecutor.scheduleAtFixedRate(new Runnable() {
|
expireExecutor.scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
@ -113,7 +115,7 @@ public class UserManager {
|
||||||
public void disconnect(UUID userId, DisconnectReason reason) {
|
public void disconnect(UUID userId, DisconnectReason reason) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
User user = users.get(userId);
|
User user = users.get(userId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.setSessionId(""); // Session will be set again with new id if user reconnects
|
user.setSessionId(""); // Session will be set again with new id if user reconnects
|
||||||
}
|
}
|
||||||
ChatManager.getInstance().removeUser(userId, reason);
|
ChatManager.getInstance().removeUser(userId, reason);
|
||||||
|
|
@ -123,44 +125,44 @@ public class UserManager {
|
||||||
public boolean isAdmin(UUID userId) {
|
public boolean isAdmin(UUID userId) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
User user = users.get(userId);
|
User user = users.get(userId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
return user.getName().equals("Admin");
|
return user.getName().equals("Admin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeUser(final UUID userId, final DisconnectReason reason) {
|
public void removeUser(final UUID userId, final DisconnectReason reason) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
final User user = users.get(userId);
|
final User user = users.get(userId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId);
|
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId);
|
||||||
user.remove(reason);
|
user.remove(reason);
|
||||||
logger.debug("USER REMOVE END - " + user.getName());
|
logger.debug("USER REMOVE END - " + user.getName());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
} finally {
|
} finally {
|
||||||
users.remove(userId);
|
users.remove(userId);
|
||||||
usersByName.remove(user.getName());
|
usersByName.remove(user.getName());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Trying to remove userId: " + userId + " - but it does not exist.");
|
logger.warn("Trying to remove userId: " + userId + " - but it does not exist.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean extendUserSession(UUID userId, String pingInfo) {
|
public boolean extendUserSession(UUID userId, String pingInfo) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
User user = users.get(userId);
|
User user = users.get(userId);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.updateLastActivity(pingInfo);
|
user.updateLastActivity(pingInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +171,8 @@ public class UserManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the connection lost for more than 3 minutes, the user will be removed (within 3 minutes the user can reconnect)
|
* Is the connection lost for more than 3 minutes, the user will be removed
|
||||||
|
* (within 3 minutes the user can reconnect)
|
||||||
*/
|
*/
|
||||||
private void checkExpired() {
|
private void checkExpired() {
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
|
@ -185,13 +188,39 @@ public class UserManager {
|
||||||
|
|
||||||
public void handleException(Exception ex) {
|
public void handleException(Exception ex) {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
logger.fatal("User manager exception " + (ex.getMessage() == null ? "null":ex.getMessage()));
|
logger.fatal("User manager exception " + (ex.getMessage() == null ? "null" : ex.getMessage()));
|
||||||
if (ex.getCause() != null) {
|
if (ex.getCause() != null) {
|
||||||
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null":ex.getCause().getMessage()));
|
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null" : ex.getCause().getMessage()));
|
||||||
}
|
}
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}else {
|
} else {
|
||||||
logger.fatal("User manager exception - null");
|
logger.fatal("User manager exception - null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUserHistory(String userName) {
|
||||||
|
User user = getUserByName(userName);
|
||||||
|
if (user == null) {
|
||||||
|
UserStats userStats = UserStatsRepository.instance.getUser(userName);
|
||||||
|
if (userStats == null) {
|
||||||
|
return "User " + userName + " not found";
|
||||||
|
}
|
||||||
|
return User.userStatsToString(userStats.getProto());
|
||||||
|
}
|
||||||
|
return "History of user " + userName + ": " + user.getUserData().getHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUserHistory() {
|
||||||
|
callExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (String updatedUser : UserStatsRepository.instance.updateUserStats()) {
|
||||||
|
User user = getUserByName(updatedUser);
|
||||||
|
if (user != null) {
|
||||||
|
user.resetUserStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,11 @@ import mage.constants.TableState;
|
||||||
import mage.game.GameException;
|
import mage.game.GameException;
|
||||||
import mage.game.Table;
|
import mage.game.Table;
|
||||||
import mage.game.match.MatchOptions;
|
import mage.game.match.MatchOptions;
|
||||||
import mage.game.result.ResultProtos.UserStatsProto;
|
|
||||||
import mage.game.tournament.TournamentOptions;
|
import mage.game.tournament.TournamentOptions;
|
||||||
import mage.server.RoomImpl;
|
import mage.server.RoomImpl;
|
||||||
import mage.server.TableManager;
|
import mage.server.TableManager;
|
||||||
import mage.server.User;
|
import mage.server.User;
|
||||||
import mage.server.UserManager;
|
import mage.server.UserManager;
|
||||||
import mage.server.record.UserStats;
|
|
||||||
import mage.server.tournament.TournamentManager;
|
import mage.server.tournament.TournamentManager;
|
||||||
import mage.server.util.ConfigSettings;
|
import mage.server.util.ConfigSettings;
|
||||||
import mage.server.util.ThreadExecutor;
|
import mage.server.util.ThreadExecutor;
|
||||||
|
|
@ -93,74 +91,6 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
return tableView;
|
return tableView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void joinStrings(StringBuilder joined, List<String> strings, String separator) {
|
|
||||||
for (int i = 0; i < strings.size(); ++i) {
|
|
||||||
if (i > 0) {
|
|
||||||
joined.append(separator);
|
|
||||||
}
|
|
||||||
joined.append(strings.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String joinBuilders(List<StringBuilder> builders) {
|
|
||||||
if (builders.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
StringBuilder builder = builders.get(0);
|
|
||||||
for (int i = 1; i < builders.size(); ++i) {
|
|
||||||
builder.append(" ");
|
|
||||||
builder.append(builders.get(i));
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String userStatsToString(UserStatsProto proto) {
|
|
||||||
List<StringBuilder> builders = new ArrayList<>();
|
|
||||||
if (proto.getMatches() > 0) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("Matches:");
|
|
||||||
builder.append(proto.getMatches());
|
|
||||||
List<String> quit = new ArrayList<>();
|
|
||||||
if (proto.getMatchesIdleTimeout() > 0) {
|
|
||||||
quit.add("I:" + Integer.toString(proto.getMatchesIdleTimeout()));
|
|
||||||
}
|
|
||||||
if (proto.getMatchesTimerTimeout() > 0) {
|
|
||||||
quit.add("T:" + Integer.toString(proto.getMatchesTimerTimeout()));
|
|
||||||
}
|
|
||||||
if (proto.getMatchesQuit() > 0) {
|
|
||||||
quit.add("Q:" + Integer.toString(proto.getMatchesQuit()));
|
|
||||||
}
|
|
||||||
if (quit.size() > 0) {
|
|
||||||
builder.append(" (");
|
|
||||||
joinStrings(builder, quit, " ");
|
|
||||||
builder.append(")");
|
|
||||||
}
|
|
||||||
builders.add(builder);
|
|
||||||
}
|
|
||||||
if (proto.getTourneys() > 0) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("Tourneys:");
|
|
||||||
builder.append(proto.getTourneys());
|
|
||||||
List<String> quit = new ArrayList<>();
|
|
||||||
if (proto.getTourneysQuitDuringDrafting() > 0) {
|
|
||||||
quit.add("D:" + Integer.toString(proto.getTourneysQuitDuringDrafting()));
|
|
||||||
}
|
|
||||||
if (proto.getTourneysQuitDuringConstruction() > 0) {
|
|
||||||
quit.add("C:" + Integer.toString(proto.getTourneysQuitDuringConstruction()));
|
|
||||||
}
|
|
||||||
if (proto.getTourneysQuitDuringRound() > 0) {
|
|
||||||
quit.add("R:" + Integer.toString(proto.getTourneysQuitDuringRound()));
|
|
||||||
}
|
|
||||||
if (quit.size() > 0) {
|
|
||||||
builder.append(" (");
|
|
||||||
joinStrings(builder, quit, " ");
|
|
||||||
builder.append(")");
|
|
||||||
}
|
|
||||||
builders.add(builder);
|
|
||||||
}
|
|
||||||
return joinBuilders(builders);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
ArrayList<TableView> tableList = new ArrayList<>();
|
ArrayList<TableView> tableList = new ArrayList<>();
|
||||||
ArrayList<MatchView> matchList = new ArrayList<>();
|
ArrayList<MatchView> matchList = new ArrayList<>();
|
||||||
|
|
@ -183,20 +113,14 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
matchView = matchList;
|
matchView = matchList;
|
||||||
List<UsersView> users = new ArrayList<>();
|
List<UsersView> users = new ArrayList<>();
|
||||||
for (User user : UserManager.getInstance().getUsers()) {
|
for (User user : UserManager.getInstance().getUsers()) {
|
||||||
String history = null;
|
|
||||||
UserStats stats = user.getUserStats();
|
|
||||||
if (stats != null) {
|
|
||||||
history = userStatsToString(stats.getProto());
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), history, user.getInfo(), user.getGameInfo(), user.getPingInfo()));
|
users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), user.getHistory(), user.getGameInfo(), user.getPingInfo()));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex);
|
logger.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex);
|
||||||
users.add(new UsersView(
|
users.add(new UsersView(
|
||||||
(user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world",
|
(user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world",
|
||||||
user.getName() != null ? user.getName() : "<no name>",
|
user.getName() != null ? user.getName() : "<no name>",
|
||||||
history != null ? history : "<no history>",
|
user.getHistory() != null ? user.getHistory() : "<no history>",
|
||||||
user.getInfo() != null ? user.getInfo() : "<no info>",
|
|
||||||
"[exception]",
|
"[exception]",
|
||||||
user.getPingInfo() != null ? user.getPingInfo() : "<no ping>"));
|
user.getPingInfo() != null ? user.getPingInfo() : "<no ping>"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package mage.server.record;
|
||||||
import mage.game.Table;
|
import mage.game.Table;
|
||||||
import mage.game.Table.TableRecorder;
|
import mage.game.Table.TableRecorder;
|
||||||
import mage.game.result.ResultProtos.TableProto;
|
import mage.game.result.ResultProtos.TableProto;
|
||||||
|
import mage.server.UserManager;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
public class TableRecorderImpl implements TableRecorder {
|
public class TableRecorderImpl implements TableRecorder {
|
||||||
|
|
@ -17,5 +18,6 @@ public class TableRecorderImpl implements TableRecorder {
|
||||||
public void record(Table table) {
|
public void record(Table table) {
|
||||||
TableProto proto = table.toProto();
|
TableProto proto = table.toProto();
|
||||||
TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs()));
|
TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs()));
|
||||||
|
UserManager.getInstance().updateUserHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,11 @@ import com.j256.ormlite.support.DatabaseConnection;
|
||||||
import com.j256.ormlite.table.TableUtils;
|
import com.j256.ormlite.table.TableUtils;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import mage.cards.repository.RepositoryUtil;
|
import mage.cards.repository.RepositoryUtil;
|
||||||
|
import mage.game.result.ResultProtos;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
public enum UserStatsRepository {
|
public enum UserStatsRepository {
|
||||||
|
|
@ -98,6 +101,79 @@ public enum UserStatsRepository {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateUserStats reads tables finished after the last DB update and reflects it to the DB.
|
||||||
|
// It returns the list of user names that are upated.
|
||||||
|
public List<String> updateUserStats() {
|
||||||
|
HashSet<String> updatedUsers = new HashSet();
|
||||||
|
// Lock the DB so that no other updateUserStats runs at the same time.
|
||||||
|
synchronized(this) {
|
||||||
|
long latestEndTimeMs = this.getLatestEndTimeMs();
|
||||||
|
List<TableRecord> records = TableRecordRepository.instance.getAfter(latestEndTimeMs);
|
||||||
|
for (TableRecord record : records) {
|
||||||
|
ResultProtos.TableProto table = record.getProto();
|
||||||
|
if (table.getControllerName().equals("System")) {
|
||||||
|
// This is a sub table within a tournament, so it's already handled by the main
|
||||||
|
// tournament table.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (table.hasMatch()) {
|
||||||
|
ResultProtos.MatchProto match = table.getMatch();
|
||||||
|
for (ResultProtos.MatchPlayerProto player : match.getPlayersList()) {
|
||||||
|
UserStats userStats = this.getUser(player.getName());
|
||||||
|
ResultProtos.UserStatsProto proto = userStats != null ? userStats.getProto()
|
||||||
|
: ResultProtos.UserStatsProto.newBuilder().setName(player.getName()).build();
|
||||||
|
ResultProtos.UserStatsProto.Builder builder = ResultProtos.UserStatsProto.newBuilder(proto)
|
||||||
|
.setMatches(proto.getMatches() + 1);
|
||||||
|
switch (player.getQuit()) {
|
||||||
|
case IDLE_TIMEOUT:
|
||||||
|
builder.setMatchesIdleTimeout(proto.getMatchesIdleTimeout() + 1);
|
||||||
|
break;
|
||||||
|
case TIMER_TIMEOUT:
|
||||||
|
builder.setMatchesTimerTimeout(proto.getMatchesTimerTimeout() + 1);
|
||||||
|
break;
|
||||||
|
case QUIT:
|
||||||
|
builder.setMatchesQuit(proto.getMatchesQuit() + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (userStats == null) {
|
||||||
|
this.add(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||||
|
} else {
|
||||||
|
this.update(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||||
|
}
|
||||||
|
updatedUsers.add(player.getName());
|
||||||
|
}
|
||||||
|
} else if (table.hasTourney()) {
|
||||||
|
ResultProtos.TourneyProto tourney = table.getTourney();
|
||||||
|
for (ResultProtos.TourneyPlayerProto player : tourney.getPlayersList()) {
|
||||||
|
UserStats userStats = this.getUser(player.getName());
|
||||||
|
ResultProtos.UserStatsProto proto = userStats != null ? userStats.getProto()
|
||||||
|
: ResultProtos.UserStatsProto.newBuilder().setName(player.getName()).build();
|
||||||
|
ResultProtos.UserStatsProto.Builder builder = ResultProtos.UserStatsProto.newBuilder(proto)
|
||||||
|
.setTourneys(proto.getTourneys() + 1);
|
||||||
|
switch (player.getQuit()) {
|
||||||
|
case DURING_ROUND:
|
||||||
|
builder.setTourneysQuitDuringRound(proto.getTourneysQuitDuringRound() + 1);
|
||||||
|
break;
|
||||||
|
case DURING_DRAFTING:
|
||||||
|
builder.setTourneysQuitDuringDrafting(proto.getTourneysQuitDuringDrafting() + 1);
|
||||||
|
break;
|
||||||
|
case DURING_CONSTRUCTION:
|
||||||
|
builder.setTourneysQuitDuringConstruction(proto.getTourneysQuitDuringConstruction() + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (userStats == null) {
|
||||||
|
this.add(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||||
|
} else {
|
||||||
|
this.update(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||||
|
}
|
||||||
|
updatedUsers.add(player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList(updatedUsers);
|
||||||
|
}
|
||||||
|
|
||||||
public void closeDB() {
|
public void closeDB() {
|
||||||
try {
|
try {
|
||||||
if (dao != null && dao.getConnectionSource() != null) {
|
if (dao != null && dao.getConnectionSource() != null) {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,26 @@ public class ConfigSettings {
|
||||||
return config.getServer().getMailgunDomain();
|
return config.getServer().getMailgunDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMailSmtpHost() {
|
||||||
|
return config.getServer().getMailSmtpHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMailSmtpPort() {
|
||||||
|
return config.getServer().getMailSmtpPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMailUser() {
|
||||||
|
return config.getServer().getMailUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMailPassword() {
|
||||||
|
return config.getServer().getMailPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMailFromAddress() {
|
||||||
|
return config.getServer().getMailFromAddress();
|
||||||
|
}
|
||||||
|
|
||||||
public List<Plugin> getPlayerTypes() {
|
public List<Plugin> getPlayerTypes() {
|
||||||
return config.getPlayerTypes().getPlayerType();
|
return config.getPlayerTypes().getPlayerType();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,11 @@
|
||||||
<xs:attribute name="googleAccount" type="xs:string" use="optional"/>
|
<xs:attribute name="googleAccount" type="xs:string" use="optional"/>
|
||||||
<xs:attribute name="mailgunApiKey" type="xs:string" use="optional"/>
|
<xs:attribute name="mailgunApiKey" type="xs:string" use="optional"/>
|
||||||
<xs:attribute name="mailgunDomain" type="xs:string" use="optional"/>
|
<xs:attribute name="mailgunDomain" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="mailSmtpHost" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="mailSmtpPort" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="mailUser" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="mailPassword" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="mailFromAddress" type="xs:string" use="optional"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ import mage.constants.Layer;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SubLayer;
|
import mage.constants.SubLayer;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
@ -54,8 +56,17 @@ public class ConsumeStrength extends CardImpl {
|
||||||
|
|
||||||
// Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn.
|
// Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn.
|
||||||
this.getSpellAbility().addEffect(new ConsumeStrengthEffect());
|
this.getSpellAbility().addEffect(new ConsumeStrengthEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2));
|
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature to get +2/+2");
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature to get -2/-2");
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConsumeStrength(final ConsumeStrength card) {
|
public ConsumeStrength(final ConsumeStrength card) {
|
||||||
|
|
@ -91,7 +102,7 @@ class ConsumeStrengthEffect extends ContinuousEffectImpl {
|
||||||
permanent.addPower(2);
|
permanent.addPower(2);
|
||||||
permanent.addToughness(2);
|
permanent.addToughness(2);
|
||||||
}
|
}
|
||||||
permanent = game.getPermanent(source.getTargets().get(0).getTargets().get(1));
|
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.addPower(-2);
|
permanent.addPower(-2);
|
||||||
permanent.addToughness(-2);
|
permanent.addToughness(-2);
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ public class DreamFracture extends CardImpl {
|
||||||
super(ownerId, 19, "Dream Fracture", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}");
|
super(ownerId, 19, "Dream Fracture", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{U}{U}");
|
||||||
this.expansionSetCode = "EVE";
|
this.expansionSetCode = "EVE";
|
||||||
|
|
||||||
|
|
||||||
// Counter target spell. Its controller draws a card.
|
// Counter target spell. Its controller draws a card.
|
||||||
this.getSpellAbility().addEffect(new DreamFractureEffect());
|
this.getSpellAbility().addEffect(new DreamFractureEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetSpell());
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
|
|
@ -73,7 +72,7 @@ class DreamFractureEffect extends OneShotEffect {
|
||||||
|
|
||||||
public DreamFractureEffect() {
|
public DreamFractureEffect() {
|
||||||
super(Outcome.Neutral);
|
super(Outcome.Neutral);
|
||||||
this.staticText = "Counter target spell. Its controller draws a card";
|
this.staticText = "Counter target spell. Its controller draws a card";
|
||||||
}
|
}
|
||||||
|
|
||||||
public DreamFractureEffect(final DreamFractureEffect effect) {
|
public DreamFractureEffect(final DreamFractureEffect effect) {
|
||||||
|
|
@ -102,4 +101,4 @@ class DreamFractureEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
return countered;
|
return countered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
52
Mage.Sets/src/mage/sets/fifthedition/LibraryOfLeng.java
Normal file
52
Mage.Sets/src/mage/sets/fifthedition/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.fifthedition;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends mage.sets.limitedbeta.LibraryOfLeng {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 387;
|
||||||
|
this.expansionSetCode = "5ED";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Mage.Sets/src/mage/sets/fourthedition/LibraryOfLeng.java
Normal file
52
Mage.Sets/src/mage/sets/fourthedition/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.fourthedition;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends mage.sets.limitedbeta.LibraryOfLeng {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 351;
|
||||||
|
this.expansionSetCode = "4ED";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ public class Bioshift extends CardImpl {
|
||||||
// Move any number of +1/+1 counters from target creature onto another target creature with the same controller.
|
// Move any number of +1/+1 counters from target creature onto another target creature with the same controller.
|
||||||
getSpellAbility().addEffect(new MoveCounterFromTargetToTargetEffect());
|
getSpellAbility().addEffect(new MoveCounterFromTargetToTargetEffect());
|
||||||
getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (you take counters from)")));
|
getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (you take counters from)")));
|
||||||
getSpellAbility().addTarget(new BioshiftSecondTargetPermanent());
|
getSpellAbility().addTarget(new BioshiftSecondTargetCreaturePermanent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -113,14 +113,15 @@ class MoveCounterFromTargetToTargetEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BioshiftSecondTargetPermanent extends TargetPermanent {
|
class BioshiftSecondTargetCreaturePermanent extends TargetCreaturePermanent {
|
||||||
|
|
||||||
BioshiftSecondTargetPermanent() {
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature with the same controller (counters go to)");
|
||||||
super();
|
|
||||||
this.filter = new FilterCreaturePermanent("another target creature with the same controller (counters go to)");
|
BioshiftSecondTargetCreaturePermanent() {
|
||||||
|
super(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
BioshiftSecondTargetPermanent(final BioshiftSecondTargetPermanent target) {
|
BioshiftSecondTargetCreaturePermanent(final BioshiftSecondTargetCreaturePermanent target) {
|
||||||
super(target);
|
super(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +138,7 @@ class BioshiftSecondTargetPermanent extends TargetPermanent {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BioshiftSecondTargetPermanent copy() {
|
public BioshiftSecondTargetCreaturePermanent copy() {
|
||||||
return new BioshiftSecondTargetPermanent(this);
|
return new BioshiftSecondTargetCreaturePermanent(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ import mage.constants.Layer;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SubLayer;
|
import mage.constants.SubLayer;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
@ -53,7 +55,17 @@ public class Schismotivate extends CardImpl {
|
||||||
|
|
||||||
// Target creature gets +4/+0 until end of turn. Another target creature gets -4/-0 until end of turn.
|
// Target creature gets +4/+0 until end of turn. Another target creature gets -4/-0 until end of turn.
|
||||||
this.getSpellAbility().addEffect(new SchismotivateEffect());
|
this.getSpellAbility().addEffect(new SchismotivateEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2));
|
|
||||||
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets +4/+0 until end of turn)");
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets -4/-0 until end of turn)");
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Schismotivate(final Schismotivate card) {
|
public Schismotivate(final Schismotivate card) {
|
||||||
|
|
@ -88,7 +100,7 @@ class SchismotivateEffect extends ContinuousEffectImpl {
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.addPower(4);
|
permanent.addPower(4);
|
||||||
}
|
}
|
||||||
permanent = game.getPermanent(source.getTargets().get(0).getTargets().get(1));
|
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.addPower(-4);
|
permanent.addPower(-4);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
121
Mage.Sets/src/mage/sets/legions/ElvishSoultiller.java
Normal file
121
Mage.Sets/src/mage/sets/legions/ElvishSoultiller.java
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* 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.legions;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DiesTriggeredAbility;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.Cards;
|
||||||
|
import mage.cards.CardsImpl;
|
||||||
|
import mage.cards.repository.CardRepository;
|
||||||
|
import mage.choices.Choice;
|
||||||
|
import mage.choices.ChoiceImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class ElvishSoultiller extends CardImpl {
|
||||||
|
|
||||||
|
public ElvishSoultiller(UUID ownerId) {
|
||||||
|
super(ownerId, 124, "Elvish Soultiller", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
|
||||||
|
this.expansionSetCode = "LGN";
|
||||||
|
this.subtype.add("Elf");
|
||||||
|
this.subtype.add("Mutant");
|
||||||
|
this.power = new MageInt(5);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// When Elvish Soultiller dies, choose a creature type. Shuffle all creature cards of that type from your graveyard into your library.
|
||||||
|
addAbility(new DiesTriggeredAbility(new ElvishSoultillerEffect()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElvishSoultiller(final ElvishSoultiller card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElvishSoultiller copy() {
|
||||||
|
return new ElvishSoultiller(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElvishSoultillerEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public ElvishSoultillerEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "choose a creature type. Shuffle all creature cards of that type from your graveyard into your library";
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElvishSoultillerEffect(final ElvishSoultillerEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElvishSoultillerEffect copy() {
|
||||||
|
return new ElvishSoultillerEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
MageObject mageObject = game.getObject(source.getSourceId());
|
||||||
|
if (controller != null && mageObject != null) {
|
||||||
|
Choice typeChoice = new ChoiceImpl(true);
|
||||||
|
typeChoice.setMessage("Choose creature type");
|
||||||
|
typeChoice.setChoices(CardRepository.instance.getCreatureTypes());
|
||||||
|
while (!controller.choose(outcome, typeChoice, game)) {
|
||||||
|
if (!controller.canRespond()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!game.isSimulation()) {
|
||||||
|
game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice());
|
||||||
|
}
|
||||||
|
Cards cardsToLibrary = new CardsImpl();
|
||||||
|
FilterCreatureCard filter = new FilterCreatureCard();
|
||||||
|
filter.add(new SubtypePredicate(typeChoice.getChoice()));
|
||||||
|
cardsToLibrary.addAll(controller.getGraveyard().getCards(filter, source.getSourceId(), source.getControllerId(), game));
|
||||||
|
controller.putCardsOnTopOfLibrary(cardsToLibrary, game, source, false);
|
||||||
|
controller.shuffleLibrary(game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Mage.Sets/src/mage/sets/limitedalpha/LibraryOfLeng.java
Normal file
52
Mage.Sets/src/mage/sets/limitedalpha/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.limitedalpha;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends mage.sets.limitedbeta.LibraryOfLeng {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 257;
|
||||||
|
this.expansionSetCode = "LEA";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
149
Mage.Sets/src/mage/sets/limitedbeta/LibraryOfLeng.java
Normal file
149
Mage.Sets/src/mage/sets/limitedbeta/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* 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.limitedbeta;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
|
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.Cards;
|
||||||
|
import mage.cards.CardsImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.events.GameEvent.EventType;
|
||||||
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends CardImpl {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId, 259, "Library of Leng", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{1}");
|
||||||
|
this.expansionSetCode = "LEB";
|
||||||
|
|
||||||
|
// You have no maximum hand size.
|
||||||
|
Effect effect = new MaximumHandSizeControllerEffect(Integer.MAX_VALUE, Duration.WhileOnBattlefield, MaximumHandSizeControllerEffect.HandSizeModification.SET);
|
||||||
|
addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||||
|
|
||||||
|
// If an effect causes you to discard a card, discard it, but you may put it on top of your library instead of into your graveyard.
|
||||||
|
addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LibraryOfLengEffect()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LibraryOfLengEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
|
private UUID cardId;
|
||||||
|
private int zoneChangeCounter;
|
||||||
|
|
||||||
|
public LibraryOfLengEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||||
|
staticText = "If an effect causes you to discard a card, discard it, but you may put it on top of your library instead of into your graveyard";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLengEffect(final LibraryOfLengEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.cardId = effect.cardId;
|
||||||
|
this.zoneChangeCounter = effect.zoneChangeCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLengEffect copy() {
|
||||||
|
return new LibraryOfLengEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType().equals(EventType.DISCARD_CARD)
|
||||||
|
|| event.getType().equals(EventType.ZONE_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
if (event.getType().equals(EventType.DISCARD_CARD)) {
|
||||||
|
return event.getPlayerId().equals(source.getControllerId());
|
||||||
|
}
|
||||||
|
if (event.getType().equals(EventType.ZONE_CHANGE)) {
|
||||||
|
if (event.getTargetId().equals(cardId) && game.getState().getZoneChangeCounter(event.getTargetId()) == zoneChangeCounter) {
|
||||||
|
if (((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND) && ((ZoneChangeEvent) event).getToZone().equals(Zone.GRAVEYARD)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
|
if (event.getType().equals(EventType.DISCARD_CARD)) {
|
||||||
|
// only save card info
|
||||||
|
Card card = game.getCard(event.getTargetId());
|
||||||
|
if (card != null) {
|
||||||
|
cardId = card.getId();
|
||||||
|
zoneChangeCounter = game.getState().getZoneChangeCounter(cardId);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (event.getType().equals(EventType.ZONE_CHANGE)) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
Card card = game.getCard(event.getTargetId());
|
||||||
|
if (controller != null && card != null) {
|
||||||
|
cardId = null;
|
||||||
|
zoneChangeCounter = 0;
|
||||||
|
if (controller.chooseUse(outcome, "Put " + card.getIdName() + " on top of your library instead?", source, game)) {
|
||||||
|
Cards cardsToLibrary = new CardsImpl(card);
|
||||||
|
controller.putCardsOnTopOfLibrary(cardsToLibrary, game, source, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -50,7 +50,6 @@ import mage.filter.predicate.permanent.AnotherPredicate;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nantuko
|
* @author nantuko
|
||||||
|
|
@ -87,8 +86,8 @@ public class AdaptiveAutomaton extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AdaptiveAutomatonAddSubtypeEffect extends ContinuousEffectImpl {
|
class AdaptiveAutomatonAddSubtypeEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
public AdaptiveAutomatonAddSubtypeEffect() {
|
public AdaptiveAutomatonAddSubtypeEffect() {
|
||||||
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||||
staticText = "{this} is the chosen type in addition to its other types";
|
staticText = "{this} is the chosen type in addition to its other types";
|
||||||
|
|
|
||||||
54
Mage.Sets/src/mage/sets/masterseditioniv/LibraryOfLeng.java
Normal file
54
Mage.Sets/src/mage/sets/masterseditioniv/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.masterseditioniv;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends mage.sets.limitedbeta.LibraryOfLeng {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 211;
|
||||||
|
this.expansionSetCode = "ME4";
|
||||||
|
this.rarity = Rarity.COMMON;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -35,6 +35,8 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
|
|
@ -53,8 +55,23 @@ public class IncrementalGrowth extends CardImpl {
|
||||||
|
|
||||||
// Put a +1/+1 counter on target creature, two +1/+1 counters on another target creature, and three +1/+1 counters on a third target creature.
|
// Put a +1/+1 counter on target creature, two +1/+1 counters on another target creature, and three +1/+1 counters on a third target creature.
|
||||||
this.getSpellAbility().addEffect(new IncrementalGrowthEffect());
|
this.getSpellAbility().addEffect(new IncrementalGrowthEffect());
|
||||||
Target target = new TargetCreaturePermanent(3,3);
|
|
||||||
this.getSpellAbility().addTarget(target);
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets a +1/+1 counter)");
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets two +1/+1 counter)");
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter3 = new FilterCreaturePermanent("another creature (gets three +1/+1 counters)");
|
||||||
|
filter3.add(new AnotherTargetPredicate(3));
|
||||||
|
TargetCreaturePermanent target3 = new TargetCreaturePermanent(filter3);
|
||||||
|
target3.setTargetTag(3);
|
||||||
|
this.getSpellAbility().addTarget(target3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncrementalGrowth(final IncrementalGrowth card) {
|
public IncrementalGrowth(final IncrementalGrowth card) {
|
||||||
|
|
@ -86,9 +103,9 @@ class IncrementalGrowthEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
for (Target target : source.getTargets()) {
|
||||||
i++;
|
i++;
|
||||||
Permanent creature = game.getPermanent(targetId);
|
Permanent creature = game.getPermanent(target.getFirstTarget());
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
creature.addCounters(CounterType.P1P1.createInstance(i), game);
|
creature.addCounters(CounterType.P1P1.createInstance(i), game);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,20 @@
|
||||||
package mage.sets.newphyrexia;
|
package mage.sets.newphyrexia;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Layer;
|
||||||
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.SubLayer;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
import mage.target.targetpointer.SecondTargetPointer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -48,16 +53,20 @@ public class LeechingBite extends CardImpl {
|
||||||
super(ownerId, 113, "Leeching Bite", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{G}");
|
super(ownerId, 113, "Leeching Bite", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{G}");
|
||||||
this.expansionSetCode = "NPH";
|
this.expansionSetCode = "NPH";
|
||||||
|
|
||||||
|
|
||||||
// Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn.
|
// Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn.
|
||||||
Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn);
|
this.getSpellAbility().addEffect(new LeechingBiteEffect());
|
||||||
effect.setText("Target creature gets +1/+1 until end of turn");
|
|
||||||
this.getSpellAbility().addEffect(effect);
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature to get +1/+1");
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (getting the +1/+1 counter)")));
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
effect = new BoostTargetEffect(-1, -1, Duration.EndOfTurn);
|
target1.setTargetTag(1);
|
||||||
effect.setText("Another target creature gets -1/-1 until end of turn");
|
this.getSpellAbility().addTarget(target1);
|
||||||
effect.setTargetPointer(new SecondTargetPointer());
|
|
||||||
this.getSpellAbility().addEffect(effect);
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature to get -1/-1");
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (getting the -1/-1 counter)")));
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LeechingBite(final LeechingBite card) {
|
public LeechingBite(final LeechingBite card) {
|
||||||
|
|
@ -69,3 +78,35 @@ public class LeechingBite extends CardImpl {
|
||||||
return new LeechingBite(this);
|
return new LeechingBite(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LeechingBiteEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
|
public LeechingBiteEffect() {
|
||||||
|
super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
|
||||||
|
this.staticText = "Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeechingBiteEffect(final LeechingBiteEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LeechingBiteEffect copy() {
|
||||||
|
return new LeechingBiteEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.addPower(1);
|
||||||
|
permanent.addToughness(1);
|
||||||
|
}
|
||||||
|
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.addPower(-1);
|
||||||
|
permanent.addToughness(-1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
99
Mage.Sets/src/mage/sets/planarchaos/DismalFailure.java
Normal file
99
Mage.Sets/src/mage/sets/planarchaos/DismalFailure.java
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* 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.planarchaos;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetSpell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class DismalFailure extends CardImpl {
|
||||||
|
|
||||||
|
public DismalFailure(UUID ownerId) {
|
||||||
|
super(ownerId, 39, "Dismal Failure", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
|
||||||
|
this.expansionSetCode = "PLC";
|
||||||
|
|
||||||
|
// Counter target spell. Its controller discards a card.
|
||||||
|
this.getSpellAbility().addEffect(new DismalFailureEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetSpell());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DismalFailure(final DismalFailure card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DismalFailure copy() {
|
||||||
|
return new DismalFailure(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DismalFailureEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public DismalFailureEffect() {
|
||||||
|
super(Outcome.Neutral);
|
||||||
|
this.staticText = "Counter target spell. Its controller discards a card";
|
||||||
|
}
|
||||||
|
|
||||||
|
public DismalFailureEffect(final DismalFailureEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DismalFailureEffect copy() {
|
||||||
|
return new DismalFailureEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
UUID targetId = source.getFirstTarget();
|
||||||
|
Player controller = null;
|
||||||
|
boolean countered = false;
|
||||||
|
if (targetId != null) {
|
||||||
|
controller = game.getPlayer(game.getControllerId(targetId));
|
||||||
|
}
|
||||||
|
if (targetId != null
|
||||||
|
&& game.getStack().counter(targetId, source.getSourceId(), game)) {
|
||||||
|
countered = true;
|
||||||
|
}
|
||||||
|
if (controller != null) {
|
||||||
|
controller.discard(1, false, source, game);
|
||||||
|
}
|
||||||
|
return countered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,8 @@ import mage.constants.Layer;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SubLayer;
|
import mage.constants.SubLayer;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
@ -53,7 +55,17 @@ public class StealStrength extends CardImpl {
|
||||||
|
|
||||||
// Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn.
|
// Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn.
|
||||||
this.getSpellAbility().addEffect(new StealStrengthEffect());
|
this.getSpellAbility().addEffect(new StealStrengthEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2));
|
|
||||||
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets +1/+1 until end of turn)");
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets -1/-1 until end of turn)");
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StealStrength(final StealStrength card) {
|
public StealStrength(final StealStrength card) {
|
||||||
|
|
@ -89,7 +101,7 @@ class StealStrengthEffect extends ContinuousEffectImpl {
|
||||||
permanent.addPower(1);
|
permanent.addPower(1);
|
||||||
permanent.addToughness(1);
|
permanent.addToughness(1);
|
||||||
}
|
}
|
||||||
permanent = game.getPermanent(source.getTargets().get(0).getTargets().get(1));
|
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.addPower(-1);
|
permanent.addPower(-1);
|
||||||
permanent.addToughness(-1);
|
permanent.addToughness(-1);
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ import mage.constants.SubLayer;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.ContinuousEffectImpl;
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
@ -54,7 +56,17 @@ public class RitesOfReaping extends CardImpl {
|
||||||
|
|
||||||
// Target creature gets +3/+3 until end of turn. Another target creature gets -3/-3 until end of turn.
|
// Target creature gets +3/+3 until end of turn. Another target creature gets -3/-3 until end of turn.
|
||||||
this.getSpellAbility().addEffect(new RitesOfReapingEffect());
|
this.getSpellAbility().addEffect(new RitesOfReapingEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2));
|
|
||||||
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets +3/+3 until end of turn)");
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets -3/-3 until end of turn)");
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RitesOfReaping(final RitesOfReaping card) {
|
public RitesOfReaping(final RitesOfReaping card) {
|
||||||
|
|
@ -90,7 +102,7 @@ class RitesOfReapingEffect extends ContinuousEffectImpl {
|
||||||
permanent.addPower(3);
|
permanent.addPower(3);
|
||||||
permanent.addToughness(3);
|
permanent.addToughness(3);
|
||||||
}
|
}
|
||||||
permanent = game.getPermanent(source.getTargets().get(0).getTargets().get(1));
|
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.addPower(-3);
|
permanent.addPower(-3);
|
||||||
permanent.addToughness(-3);
|
permanent.addToughness(-3);
|
||||||
|
|
|
||||||
52
Mage.Sets/src/mage/sets/revisededition/LibraryOfLeng.java
Normal file
52
Mage.Sets/src/mage/sets/revisededition/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.revisededition;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends mage.sets.limitedbeta.LibraryOfLeng {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 261;
|
||||||
|
this.expansionSetCode = "3ED";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,9 +31,7 @@ import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.discard.DiscardTargetEffect;
|
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -42,7 +40,6 @@ import mage.constants.Rarity;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetPlayer;
|
import mage.target.TargetPlayer;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -94,14 +91,17 @@ class CragganwickCrematorEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player you = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Player targetedPlayer = game.getPlayer(source.getFirstTarget());
|
|
||||||
if (you != null && targetedPlayer != null) {
|
if (controller != null) {
|
||||||
Card discardedCard = targetedPlayer.discardOne(true, source, game);
|
Card discardedCard = controller.discardOne(true, source, game);
|
||||||
if (discardedCard != null
|
if (discardedCard != null
|
||||||
&& discardedCard.getCardType().contains(CardType.CREATURE)) {
|
&& discardedCard.getCardType().contains(CardType.CREATURE)) {
|
||||||
int damage = discardedCard.getPower().getValue();
|
Player targetedPlayer = game.getPlayer(source.getFirstTarget());
|
||||||
targetedPlayer.damage(damage, source.getSourceId(), game, false, true);
|
if (targetedPlayer != null) {
|
||||||
|
int damage = discardedCard.getPower().getValue();
|
||||||
|
targetedPlayer.damage(damage, source.getSourceId(), game, false, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.counters.Counter;
|
import mage.counters.Counter;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
@ -47,7 +48,7 @@ import mage.target.common.TargetCreaturePermanent;
|
||||||
public class FateTransfer extends CardImpl {
|
public class FateTransfer extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature to move all counters from");
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature to move all counters from");
|
||||||
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("target creature to move all counters to");
|
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another target creature to move all counters to");
|
||||||
|
|
||||||
public FateTransfer(UUID ownerId) {
|
public FateTransfer(UUID ownerId) {
|
||||||
super(ownerId, 161, "Fate Transfer", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U/B}");
|
super(ownerId, 161, "Fate Transfer", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U/B}");
|
||||||
|
|
@ -55,8 +56,15 @@ public class FateTransfer extends CardImpl {
|
||||||
|
|
||||||
// Move all counters from target creature onto another target creature.
|
// Move all counters from target creature onto another target creature.
|
||||||
this.getSpellAbility().addEffect(new FateTransferEffect());
|
this.getSpellAbility().addEffect(new FateTransferEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
|
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter2));
|
TargetCreaturePermanent fromTarget = new TargetCreaturePermanent(filter);
|
||||||
|
fromTarget.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(fromTarget);
|
||||||
|
|
||||||
|
TargetCreaturePermanent toTarget = new TargetCreaturePermanent(filter2);
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
toTarget.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(toTarget);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
|
|
@ -53,8 +55,23 @@ public class IncrementalBlight extends CardImpl {
|
||||||
|
|
||||||
// Put a -1/-1 counter on target creature, two -1/-1 counters on another target creature, and three -1/-1 counters on a third target creature.
|
// Put a -1/-1 counter on target creature, two -1/-1 counters on another target creature, and three -1/-1 counters on a third target creature.
|
||||||
this.getSpellAbility().addEffect(new IncrementalBlightEffect());
|
this.getSpellAbility().addEffect(new IncrementalBlightEffect());
|
||||||
Target target = new TargetCreaturePermanent(3,3);
|
|
||||||
this.getSpellAbility().addTarget(target);
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets a -1/-1 counter)");
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets two -1/-1 counters)");
|
||||||
|
filter2.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
|
|
||||||
|
FilterCreaturePermanent filter3 = new FilterCreaturePermanent("another creature (gets three -1/-1 counters)");
|
||||||
|
filter3.add(new AnotherTargetPredicate(3));
|
||||||
|
TargetCreaturePermanent target3 = new TargetCreaturePermanent(filter3);
|
||||||
|
target3.setTargetTag(3);
|
||||||
|
this.getSpellAbility().addTarget(target3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncrementalBlight(final IncrementalBlight card) {
|
public IncrementalBlight(final IncrementalBlight card) {
|
||||||
|
|
@ -85,9 +102,9 @@ class IncrementalBlightEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
for (Target target : source.getTargets()) {
|
||||||
i++;
|
i++;
|
||||||
Permanent creature = game.getPermanent(targetId);
|
Permanent creature = game.getPermanent(target.getFirstTarget());
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
creature.addCounters(CounterType.M1M1.createInstance(i), game);
|
creature.addCounters(CounterType.M1M1.createInstance(i), game);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ class RealmRazerEffect extends OneShotEffect {
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
ExileZone exZone = game.getExile().getExileZone(source.getSourceId());
|
ExileZone exZone = game.getExile().getExileZone(source.getSourceId());
|
||||||
if (exZone != null) {
|
if (exZone != null) {
|
||||||
return controller.moveCards(exZone.getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null);
|
return controller.moveCards(exZone.getCards(game), Zone.BATTLEFIELD, source, game, true, false, true, null);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
52
Mage.Sets/src/mage/sets/unlimitededition/LibraryOfLeng.java
Normal file
52
Mage.Sets/src/mage/sets/unlimitededition/LibraryOfLeng.java
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.unlimitededition;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class LibraryOfLeng extends mage.sets.limitedbeta.LibraryOfLeng {
|
||||||
|
|
||||||
|
public LibraryOfLeng(UUID ownerId) {
|
||||||
|
super(ownerId);
|
||||||
|
this.cardNumber = 258;
|
||||||
|
this.expansionSetCode = "2ED";
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryOfLeng(final LibraryOfLeng card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LibraryOfLeng copy() {
|
||||||
|
return new LibraryOfLeng(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,8 @@ import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
|
|
@ -54,10 +56,18 @@ public class FeralContest extends CardImpl {
|
||||||
|
|
||||||
// Put a +1/+1 counter on target creature you control.
|
// Put a +1/+1 counter on target creature you control.
|
||||||
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
||||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
|
|
||||||
|
TargetControlledCreaturePermanent target1 = new TargetControlledCreaturePermanent();
|
||||||
|
target1.setTargetTag(1);
|
||||||
|
this.getSpellAbility().addTarget(target1);
|
||||||
|
|
||||||
// Another target creature blocks it this turn if able.
|
// Another target creature blocks it this turn if able.
|
||||||
this.getSpellAbility().addEffect(new FeralContestEffect());
|
this.getSpellAbility().addEffect(new FeralContestEffect());
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature (must block this turn)");
|
||||||
|
filter.add(new AnotherTargetPredicate(2));
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter);
|
||||||
|
target2.setTargetTag(2);
|
||||||
|
this.getSpellAbility().addTarget(target2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeralContest(final FeralContest card) {
|
public FeralContest(final FeralContest card) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage-tests</artifactId>
|
<artifactId>mage-tests</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -2077,4 +2077,8 @@ public class TestPlayer implements Player {
|
||||||
return AIPlayer;
|
return AIPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHistory() {
|
||||||
|
return computerPlayer.getHistory();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,19 @@
|
||||||
package org.mage.test.serverside.base;
|
package org.mage.test.serverside.base;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.repository.CardInfo;
|
import mage.cards.repository.CardInfo;
|
||||||
import mage.cards.repository.CardRepository;
|
import mage.cards.repository.CardRepository;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.RangeOfInfluence;
|
import mage.constants.RangeOfInfluence;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
@ -25,19 +35,13 @@ import org.junit.BeforeClass;
|
||||||
import org.mage.test.player.RandomPlayer;
|
import org.mage.test.player.RandomPlayer;
|
||||||
import org.mage.test.player.TestPlayer;
|
import org.mage.test.player.TestPlayer;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FilenameFilter;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all tests.
|
* Base class for all tests.
|
||||||
*
|
*
|
||||||
* @author ayratn
|
* @author ayratn
|
||||||
*/
|
*/
|
||||||
public abstract class MageTestBase {
|
public abstract class MageTestBase {
|
||||||
|
|
||||||
protected static Logger logger = Logger.getLogger(MageTestBase.class);
|
protected static Logger logger = Logger.getLogger(MageTestBase.class);
|
||||||
|
|
||||||
public static PluginClassLoader classLoader = new PluginClassLoader();
|
public static PluginClassLoader classLoader = new PluginClassLoader();
|
||||||
|
|
@ -46,17 +50,17 @@ public abstract class MageTestBase {
|
||||||
|
|
||||||
protected Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)(:\\{tapped\\})?");
|
protected Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)(:\\{tapped\\})?");
|
||||||
|
|
||||||
protected List<Card> handCardsA = new ArrayList<Card>();
|
protected List<Card> handCardsA = new ArrayList<>();
|
||||||
protected List<Card> handCardsB = new ArrayList<Card>();
|
protected List<Card> handCardsB = new ArrayList<>();
|
||||||
protected List<PermanentCard> battlefieldCardsA = new ArrayList<PermanentCard>();
|
protected List<PermanentCard> battlefieldCardsA = new ArrayList<>();
|
||||||
protected List<PermanentCard> battlefieldCardsB = new ArrayList<PermanentCard>();
|
protected List<PermanentCard> battlefieldCardsB = new ArrayList<>();
|
||||||
protected List<Card> graveyardCardsA = new ArrayList<Card>();
|
protected List<Card> graveyardCardsA = new ArrayList<>();
|
||||||
protected List<Card> graveyardCardsB = new ArrayList<Card>();
|
protected List<Card> graveyardCardsB = new ArrayList<>();
|
||||||
protected List<Card> libraryCardsA = new ArrayList<Card>();
|
protected List<Card> libraryCardsA = new ArrayList<>();
|
||||||
protected List<Card> libraryCardsB = new ArrayList<Card>();
|
protected List<Card> libraryCardsB = new ArrayList<>();
|
||||||
|
|
||||||
protected Map<Zone, String> commandsA = new HashMap<Zone, String>();
|
protected Map<Zone, String> commandsA = new HashMap<>();
|
||||||
protected Map<Zone, String> commandsB = new HashMap<Zone, String>();
|
protected Map<Zone, String> commandsB = new HashMap<>();
|
||||||
|
|
||||||
protected TestPlayer playerA;
|
protected TestPlayer playerA;
|
||||||
protected TestPlayer playerB;
|
protected TestPlayer playerB;
|
||||||
|
|
@ -67,8 +71,7 @@ public abstract class MageTestBase {
|
||||||
protected static Game currentGame = null;
|
protected static Game currentGame = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player thats starts the game first.
|
* Player thats starts the game first. By default, it is ComputerA.
|
||||||
* By default, it is ComputerA.
|
|
||||||
*/
|
*/
|
||||||
protected static Player activePlayer = null;
|
protected static Player activePlayer = null;
|
||||||
|
|
||||||
|
|
@ -77,6 +80,7 @@ public abstract class MageTestBase {
|
||||||
protected PhaseStep stopAtStep = PhaseStep.UNTAP;
|
protected PhaseStep stopAtStep = PhaseStep.UNTAP;
|
||||||
|
|
||||||
protected enum ParserState {
|
protected enum ParserState {
|
||||||
|
|
||||||
INIT,
|
INIT,
|
||||||
OPTIONS,
|
OPTIONS,
|
||||||
EXPECTED
|
EXPECTED
|
||||||
|
|
@ -85,18 +89,13 @@ public abstract class MageTestBase {
|
||||||
protected ParserState parserState;
|
protected ParserState parserState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected results of the test.
|
* Expected results of the test. Read from test case in {@link String} based
|
||||||
* Read from test case in {@link String} based format:
|
* format:
|
||||||
* <p/>
|
* <p/>
|
||||||
* Example:
|
* Example: turn:1 result:won:ComputerA life:ComputerA:20 life:ComputerB:0
|
||||||
* turn:1
|
* battlefield:ComputerB:Tine Shrike:0 graveyard:ComputerB:Tine Shrike:1
|
||||||
* result:won:ComputerA
|
|
||||||
* life:ComputerA:20
|
|
||||||
* life:ComputerB:0
|
|
||||||
* battlefield:ComputerB:Tine Shrike:0
|
|
||||||
* graveyard:ComputerB:Tine Shrike:1
|
|
||||||
*/
|
*/
|
||||||
protected List<String> expectedResults = new ArrayList<String>();
|
protected List<String> expectedResults = new ArrayList<>();
|
||||||
|
|
||||||
protected static final String TESTS_PATH = "tests" + File.separator;
|
protected static final String TESTS_PATH = "tests" + File.separator;
|
||||||
|
|
||||||
|
|
@ -163,8 +162,9 @@ public abstract class MageTestBase {
|
||||||
|
|
||||||
private static void deleteSavedGames() {
|
private static void deleteSavedGames() {
|
||||||
File directory = new File("saved/");
|
File directory = new File("saved/");
|
||||||
if (!directory.exists())
|
if (!directory.exists()) {
|
||||||
directory.mkdirs();
|
directory.mkdirs();
|
||||||
|
}
|
||||||
File[] files = directory.listFiles(
|
File[] files = directory.listFiles(
|
||||||
new FilenameFilter() {
|
new FilenameFilter() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -185,7 +185,9 @@ public abstract class MageTestBase {
|
||||||
try {
|
try {
|
||||||
while (scanner.hasNextLine()) {
|
while (scanner.hasNextLine()) {
|
||||||
String line = scanner.nextLine().trim();
|
String line = scanner.nextLine().trim();
|
||||||
if (line == null || line.isEmpty() || line.startsWith("#")) continue;
|
if (line == null || line.isEmpty() || line.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (line.startsWith("$include")) {
|
if (line.startsWith("$include")) {
|
||||||
includeFrom(line);
|
includeFrom(line);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -1237,4 +1237,10 @@ public class PlayerStub implements Player {
|
||||||
public boolean addTargets(Ability ability, Game game) {
|
public boolean addTargets(Ability ability, Game game) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHistory() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mage</artifactId>
|
<artifactId>mage</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ public enum CardRepository {
|
||||||
// raise this if db structure was changed
|
// raise this if db structure was changed
|
||||||
private static final long CARD_DB_VERSION = 43;
|
private static final long CARD_DB_VERSION = 43;
|
||||||
// raise this if new cards were added to the server
|
// raise this if new cards were added to the server
|
||||||
private static final long CARD_CONTENT_VERSION = 44;
|
private static final long CARD_CONTENT_VERSION = 45;
|
||||||
|
|
||||||
private final Random random = new Random();
|
private final Random random = new Random();
|
||||||
private Dao<CardInfo, Object> cardDao;
|
private Dao<CardInfo, Object> cardDao;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.game;
|
package mage.game;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -38,7 +37,6 @@ import mage.players.Player;
|
||||||
public class Seat implements Serializable {
|
public class Seat implements Serializable {
|
||||||
|
|
||||||
// private static final Logger logger = Logger.getLogger(Seat.class);
|
// private static final Logger logger = Logger.getLogger(Seat.class);
|
||||||
|
|
||||||
private String playerType;
|
private String playerType;
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ public class GameEvent implements Serializable {
|
||||||
DRAW_CARD, DREW_CARD,
|
DRAW_CARD, DREW_CARD,
|
||||||
MIRACLE_CARD_REVEALED,
|
MIRACLE_CARD_REVEALED,
|
||||||
MADNESS_CARD_EXILED,
|
MADNESS_CARD_EXILED,
|
||||||
|
DISCARD_CARD,
|
||||||
DISCARDED_CARD,
|
DISCARDED_CARD,
|
||||||
CYCLE_CARD, CYCLED_CARD,
|
CYCLE_CARD, CYCLED_CARD,
|
||||||
CLASH, CLASHED,
|
CLASH, CLASHED,
|
||||||
|
|
|
||||||
|
|
@ -824,4 +824,6 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean addTargets(Ability ability, Game game);
|
boolean addTargets(Ability ability, Game game);
|
||||||
|
|
||||||
|
String getHistory();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,14 @@ import mage.constants.ManaType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.PlayerAction;
|
import mage.constants.PlayerAction;
|
||||||
|
import static mage.constants.PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS;
|
||||||
|
import static mage.constants.PlayerAction.PASS_PRIORITY_UNTIL_MY_NEXT_TURN;
|
||||||
|
import static mage.constants.PlayerAction.PASS_PRIORITY_UNTIL_NEXT_MAIN_PHASE;
|
||||||
|
import static mage.constants.PlayerAction.PASS_PRIORITY_UNTIL_NEXT_TURN;
|
||||||
|
import static mage.constants.PlayerAction.PASS_PRIORITY_UNTIL_STACK_RESOLVED;
|
||||||
|
import static mage.constants.PlayerAction.PASS_PRIORITY_UNTIL_TURN_END_STEP;
|
||||||
|
import static mage.constants.PlayerAction.PERMISSION_REQUESTS_ALLOWED_OFF;
|
||||||
|
import static mage.constants.PlayerAction.PERMISSION_REQUESTS_ALLOWED_ON;
|
||||||
import mage.constants.RangeOfInfluence;
|
import mage.constants.RangeOfInfluence;
|
||||||
import mage.constants.SpellAbilityType;
|
import mage.constants.SpellAbilityType;
|
||||||
import mage.constants.TimingRule;
|
import mage.constants.TimingRule;
|
||||||
|
|
@ -516,31 +524,29 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
inRange.add(player.getId());
|
inRange.add(player.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if ((range.getRange() * 2) + 1 >= game.getPlayers().size()) {
|
||||||
|
for (Player player : game.getPlayers().values()) {
|
||||||
|
if (!player.hasLeft()) {
|
||||||
|
inRange.add(player.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((range.getRange() * 2) + 1 >= game.getPlayers().size()) {
|
inRange.add(playerId);
|
||||||
for (Player player : game.getPlayers().values()) {
|
PlayerList players = game.getState().getPlayerList(playerId);
|
||||||
if (!player.hasLeft()) {
|
for (int i = 0; i < range.getRange(); i++) {
|
||||||
inRange.add(player.getId());
|
Player player = players.getNext(game);
|
||||||
}
|
while (player.hasLeft()) {
|
||||||
|
player = players.getNext(game);
|
||||||
}
|
}
|
||||||
} else {
|
inRange.add(player.getId());
|
||||||
inRange.add(playerId);
|
}
|
||||||
PlayerList players = game.getState().getPlayerList(playerId);
|
players = game.getState().getPlayerList(playerId);
|
||||||
for (int i = 0; i < range.getRange(); i++) {
|
for (int i = 0; i < range.getRange(); i++) {
|
||||||
Player player = players.getNext(game);
|
Player player = players.getPrevious(game);
|
||||||
while (player.hasLeft()) {
|
while (player.hasLeft()) {
|
||||||
player = players.getNext(game);
|
player = players.getPrevious(game);
|
||||||
}
|
|
||||||
inRange.add(player.getId());
|
|
||||||
}
|
|
||||||
players = game.getState().getPlayerList(playerId);
|
|
||||||
for (int i = 0; i < range.getRange(); i++) {
|
|
||||||
Player player = players.getPrevious(game);
|
|
||||||
while (player.hasLeft()) {
|
|
||||||
player = players.getPrevious(game);
|
|
||||||
}
|
|
||||||
inRange.add(player.getId());
|
|
||||||
}
|
}
|
||||||
|
inRange.add(player.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -760,7 +766,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
about the discarded card, that cost payment is illegal; the game returns to
|
about the discarded card, that cost payment is illegal; the game returns to
|
||||||
the moment before the cost was paid (see rule 717, "Handling Illegal Actions").
|
the moment before the cost was paid (see rule 717, "Handling Illegal Actions").
|
||||||
*/
|
*/
|
||||||
if (card != null) {
|
if (card != null
|
||||||
|
&& !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD, card.getId(), source == null ? null : source.getSourceId(), playerId), source)) {
|
||||||
// write info to game log first so game log infos from triggered or replacement effects follow in the game log
|
// write info to game log first so game log infos from triggered or replacement effects follow in the game log
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
game.informPlayers(getLogName() + " discards " + card.getLogName());
|
game.informPlayers(getLogName() + " discards " + card.getLogName());
|
||||||
|
|
@ -2089,7 +2096,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!opponentInGame || // if no more opponent is in game the wins event may no longer be replaced
|
if (!opponentInGame
|
||||||
|
|| // if no more opponent is in game the wins event may no longer be replaced
|
||||||
!game.replaceEvent(new GameEvent(GameEvent.EventType.WINS, null, null, playerId))) {
|
!game.replaceEvent(new GameEvent(GameEvent.EventType.WINS, null, null, playerId))) {
|
||||||
logger.debug("player won -> start: " + this.getName());
|
logger.debug("player won -> start: " + this.getName());
|
||||||
if (!this.loses) {
|
if (!this.loses) {
|
||||||
|
|
@ -2169,10 +2177,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
if (blocker != null && group != null && group.canBlock(blocker, game)) {
|
if (blocker != null && group != null && group.canBlock(blocker, game)) {
|
||||||
group.addBlocker(blockerId, playerId, game);
|
group.addBlocker(blockerId, playerId, game);
|
||||||
game.getCombat().addBlockingGroup(blockerId, attackerId, playerId, game);
|
game.getCombat().addBlockingGroup(blockerId, attackerId, playerId, game);
|
||||||
} else {
|
} else if (this.isHuman() && !game.isSimulation()) {
|
||||||
if (this.isHuman() && !game.isSimulation()) {
|
game.informPlayer(this, "You can't block this creature.");
|
||||||
game.informPlayer(this, "You can't block this creature.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2793,14 +2799,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
if (targetNum < option.getTargets().size() - 2) {
|
if (targetNum < option.getTargets().size() - 2) {
|
||||||
addTargetOptions(options, newOption, targetNum + 1, game);
|
addTargetOptions(options, newOption, targetNum + 1, game);
|
||||||
|
} else if (option.getChoices().size() > 0) {
|
||||||
|
addChoiceOptions(options, newOption, 0, game);
|
||||||
|
} else if (option.getCosts().getTargets().size() > 0) {
|
||||||
|
addCostTargetOptions(options, newOption, 0, game);
|
||||||
} else {
|
} else {
|
||||||
if (option.getChoices().size() > 0) {
|
options.add(newOption);
|
||||||
addChoiceOptions(options, newOption, 0, game);
|
|
||||||
} else if (option.getCosts().getTargets().size() > 0) {
|
|
||||||
addCostTargetOptions(options, newOption, 0, game);
|
|
||||||
} else {
|
|
||||||
options.add(newOption);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2811,12 +2815,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
newOption.getChoices().get(choiceNum).setChoice(choice);
|
newOption.getChoices().get(choiceNum).setChoice(choice);
|
||||||
if (choiceNum < option.getChoices().size() - 1) {
|
if (choiceNum < option.getChoices().size() - 1) {
|
||||||
addChoiceOptions(options, newOption, choiceNum + 1, game);
|
addChoiceOptions(options, newOption, choiceNum + 1, game);
|
||||||
|
} else if (option.getCosts().getTargets().size() > 0) {
|
||||||
|
addCostTargetOptions(options, newOption, 0, game);
|
||||||
} else {
|
} else {
|
||||||
if (option.getCosts().getTargets().size() > 0) {
|
options.add(newOption);
|
||||||
addCostTargetOptions(options, newOption, 0, game);
|
|
||||||
} else {
|
|
||||||
options.add(newOption);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3503,4 +3505,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHistory() {
|
||||||
|
return "no available";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ public class UserData implements Serializable {
|
||||||
protected boolean passPriorityActivation;
|
protected boolean passPriorityActivation;
|
||||||
protected boolean autoOrderTrigger;
|
protected boolean autoOrderTrigger;
|
||||||
|
|
||||||
|
protected String history;
|
||||||
|
|
||||||
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
|
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
|
||||||
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
|
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
|
||||||
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted,
|
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted,
|
||||||
|
|
@ -40,6 +42,7 @@ public class UserData implements Serializable {
|
||||||
this.passPriorityCast = passPriorityCast;
|
this.passPriorityCast = passPriorityCast;
|
||||||
this.passPriorityActivation = passPriorityActivation;
|
this.passPriorityActivation = passPriorityActivation;
|
||||||
this.autoOrderTrigger = autoOrderTrigger;
|
this.autoOrderTrigger = autoOrderTrigger;
|
||||||
|
this.history = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(UserData userData) {
|
public void update(UserData userData) {
|
||||||
|
|
@ -166,7 +169,16 @@ public class UserData implements Serializable {
|
||||||
this.autoOrderTrigger = autoOrderTrigger;
|
this.autoOrderTrigger = autoOrderTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHistory(String history) {
|
||||||
|
this.history = history;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHistory() {
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getDefaultFlagName() {
|
public static String getDefaultFlagName() {
|
||||||
return "world.png";
|
return "world.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,9 @@ git log 2ad15bbd48d5ae34b0cb5d709895d406b977d104..head --diff-filter=A --name-st
|
||||||
since 1.4.7v0
|
since 1.4.7v0
|
||||||
git log 8b37d0b989ba19f0dfccc81db66f5a21cc71fb94..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
git log 8b37d0b989ba19f0dfccc81db66f5a21cc71fb94..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||||
|
|
||||||
|
since 1.4.8v0
|
||||||
|
git log 804f9e7fc2b481f7f784943409f558a671088372..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||||
|
|
||||||
3. Copy added_cards.txt to trunk\Utils folder
|
3. Copy added_cards.txt to trunk\Utils folder
|
||||||
4. Run script:
|
4. Run script:
|
||||||
> perl extract_in_wiki_format.perl
|
> perl extract_in_wiki_format.perl
|
||||||
|
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
#
|
|
||||||
# There is insufficient memory for the Java Runtime Environment to continue.
|
|
||||||
# Native memory allocation (malloc) failed to allocate 1048576 bytes for AllocateHeap
|
|
||||||
# Possible reasons:
|
|
||||||
# The system is out of physical RAM or swap space
|
|
||||||
# In 32 bit mode, the process size limit was hit
|
|
||||||
# Possible solutions:
|
|
||||||
# Reduce memory load on the system
|
|
||||||
# Increase physical memory or swap space
|
|
||||||
# Check if swap backing store is full
|
|
||||||
# Use 64 bit Java on a 64 bit OS
|
|
||||||
# Decrease Java heap size (-Xmx/-Xms)
|
|
||||||
# Decrease number of Java threads
|
|
||||||
# Decrease Java thread stack sizes (-Xss)
|
|
||||||
# Set larger code cache with -XX:ReservedCodeCacheSize=
|
|
||||||
# This output file may be truncated or incomplete.
|
|
||||||
#
|
|
||||||
# Out of Memory Error (memory/allocation.inline.hpp:61), pid=4700, tid=4912
|
|
||||||
#
|
|
||||||
# JRE version: (7.0_71-b14) (build )
|
|
||||||
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.71-b01 mixed mode windows-amd64 compressed oops)
|
|
||||||
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
|
|
||||||
#
|
|
||||||
|
|
||||||
--------------- T H R E A D ---------------
|
|
||||||
|
|
||||||
Current thread (0x000000000223f000): JavaThread "Unknown thread" [_thread_in_vm, id=4912, stack(0x00000000025b0000,0x00000000026b0000)]
|
|
||||||
|
|
||||||
Stack: [0x00000000025b0000,0x00000000026b0000]
|
|
||||||
[error occurred during error reporting (printing stack bounds), id 0xc0000005]
|
|
||||||
|
|
||||||
|
|
||||||
--------------- P R O C E S S ---------------
|
|
||||||
|
|
||||||
Java Threads: ( => current thread )
|
|
||||||
|
|
||||||
Other Threads:
|
|
||||||
|
|
||||||
=>0x000000000223f000 (exited) JavaThread "Unknown thread" [_thread_in_vm, id=4912, stack(0x00000000025b0000,0x00000000026b0000)]
|
|
||||||
|
|
||||||
VM state:not at safepoint (normal execution)
|
|
||||||
|
|
||||||
VM Mutex/Monitor currently owned by a thread: None
|
|
||||||
|
|
||||||
Heap
|
|
||||||
PSYoungGen total 612352K, used 10506K [0x00000007d5500000, 0x0000000800000000, 0x0000000800000000)
|
|
||||||
eden space 525312K, 2% used [0x00000007d5500000,0x00000007d5f42948,0x00000007f5600000)
|
|
||||||
from space 87040K, 0% used [0x00000007fab00000,0x00000007fab00000,0x0000000800000000)
|
|
||||||
to space 87040K, 0% used [0x00000007f5600000,0x00000007f5600000,0x00000007fab00000)
|
|
||||||
ParOldGen total 1398272K, used 0K [0x000000077ff80000, 0x00000007d5500000, 0x00000007d5500000)
|
|
||||||
object space 1398272K, 0% used [0x000000077ff80000,0x000000077ff80000,0x00000007d5500000)
|
|
||||||
PSPermGen total 21504K, used 694K [0x000000077ad80000, 0x000000077c280000, 0x000000077ff80000)
|
|
||||||
object space 21504K, 3% used [0x000000077ad80000,0x000000077ae2d9f8,0x000000077c280000)
|
|
||||||
|
|
||||||
Card table byte_map: [0x00000000056b0000,0x0000000005ae0000] byte_map_base: 0x0000000001ad9400
|
|
||||||
|
|
||||||
Polling page: 0x0000000000240000
|
|
||||||
|
|
||||||
Code Cache [0x00000000026b0000, 0x0000000002920000, 0x00000000056b0000)
|
|
||||||
total_blobs=37 nmethods=0 adapters=20 free_code_cache=48890Kb largest_free_block=50063104
|
|
||||||
|
|
||||||
Compilation events (0 events):
|
|
||||||
No events
|
|
||||||
|
|
||||||
GC Heap History (0 events):
|
|
||||||
No events
|
|
||||||
|
|
||||||
Deoptimization events (0 events):
|
|
||||||
No events
|
|
||||||
|
|
||||||
Internal exceptions (0 events):
|
|
||||||
No events
|
|
||||||
|
|
||||||
Events (10 events):
|
|
||||||
Event: 0.029 loading class 0x00000000022bed40
|
|
||||||
Event: 0.029 loading class 0x00000000022bed40 done
|
|
||||||
Event: 0.029 loading class 0x00000000022bed90
|
|
||||||
Event: 0.029 loading class 0x00000000022bed90 done
|
|
||||||
Event: 0.029 loading class 0x00000000022bede0
|
|
||||||
Event: 0.029 loading class 0x00000000022bede0 done
|
|
||||||
Event: 0.030 loading class 0x00000000022bfb40
|
|
||||||
Event: 0.030 loading class 0x00000000022bfb40 done
|
|
||||||
Event: 0.030 loading class 0x00000000022bf760
|
|
||||||
Event: 0.030 loading class 0x00000000022bf760 done
|
|
||||||
|
|
||||||
|
|
||||||
Dynamic libraries:
|
|
||||||
0x000000013f320000 - 0x000000013f353000 C:\Program Files\Java\jdk1.7.0_71\bin\java.exe
|
|
||||||
0x00000000770c0000 - 0x0000000077269000 C:\Windows\SYSTEM32\ntdll.dll
|
|
||||||
0x0000000076ea0000 - 0x0000000076fbf000 C:\Windows\system32\kernel32.dll
|
|
||||||
0x000007fefd170000 - 0x000007fefd1dc000 C:\Windows\system32\KERNELBASE.dll
|
|
||||||
0x000007fefd7c0000 - 0x000007fefd89b000 C:\Windows\system32\ADVAPI32.dll
|
|
||||||
0x000007feff300000 - 0x000007feff39f000 C:\Windows\system32\msvcrt.dll
|
|
||||||
0x000007fefe7e0000 - 0x000007fefe7ff000 C:\Windows\SYSTEM32\sechost.dll
|
|
||||||
0x000007fefd8a0000 - 0x000007fefd9cd000 C:\Windows\system32\RPCRT4.dll
|
|
||||||
0x0000000076fc0000 - 0x00000000770ba000 C:\Windows\system32\USER32.dll
|
|
||||||
0x000007fefd230000 - 0x000007fefd297000 C:\Windows\system32\GDI32.dll
|
|
||||||
0x000007fefef50000 - 0x000007fefef5e000 C:\Windows\system32\LPK.dll
|
|
||||||
0x000007feff230000 - 0x000007feff2f9000 C:\Windows\system32\USP10.dll
|
|
||||||
0x000007fefb490000 - 0x000007fefb684000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.18837_none_fa3b1e3d17594757\COMCTL32.dll
|
|
||||||
0x000007fefe760000 - 0x000007fefe7d1000 C:\Windows\system32\SHLWAPI.dll
|
|
||||||
0x000007feff3a0000 - 0x000007feff3ce000 C:\Windows\system32\IMM32.DLL
|
|
||||||
0x000007fefe9f0000 - 0x000007fefeaf9000 C:\Windows\system32\MSCTF.dll
|
|
||||||
0x000000006ab40000 - 0x000000006ac12000 C:\Program Files\Java\jdk1.7.0_71\jre\bin\msvcr100.dll
|
|
||||||
0x0000000067b10000 - 0x00000000682e3000 C:\Program Files\Java\jdk1.7.0_71\jre\bin\server\jvm.dll
|
|
||||||
0x000007fefa970000 - 0x000007fefa979000 C:\Windows\system32\WSOCK32.dll
|
|
||||||
0x000007fefd690000 - 0x000007fefd6dd000 C:\Windows\system32\WS2_32.dll
|
|
||||||
0x000007fefe9e0000 - 0x000007fefe9e8000 C:\Windows\system32\NSI.dll
|
|
||||||
0x000007fefaf60000 - 0x000007fefaf9b000 C:\Windows\system32\WINMM.dll
|
|
||||||
0x0000000077290000 - 0x0000000077297000 C:\Windows\system32\PSAPI.DLL
|
|
||||||
0x000000006f510000 - 0x000000006f51f000 C:\Program Files\Java\jdk1.7.0_71\jre\bin\verify.dll
|
|
||||||
0x000000006c820000 - 0x000000006c848000 C:\Program Files\Java\jdk1.7.0_71\jre\bin\java.dll
|
|
||||||
0x000000006c860000 - 0x000000006c875000 C:\Program Files\Java\jdk1.7.0_71\jre\bin\zip.dll
|
|
||||||
|
|
||||||
VM Arguments:
|
|
||||||
jvm_args: -Xms2048m -Xmx2048m -Dclassworlds.conf=C:\Program Files\NetBeans 8.0.2\java\maven\bin\m2.conf -Dmaven.home=C:\Program Files\NetBeans 8.0.2\java\maven
|
|
||||||
java_command: org.codehaus.plexus.classworlds.launcher.Launcher -Dmaven.ext.class.path=C:\Users\fireshoes\AppData\Roaming\NetBeans\8.0.2\maven-nblib\netbeans-eventspy.jar -Dfile.encoding=UTF-8 clean install
|
|
||||||
Launcher Type: SUN_STANDARD
|
|
||||||
|
|
||||||
Environment Variables:
|
|
||||||
JAVA_HOME=C:\Program Files\Java\jdk1.7.0_71
|
|
||||||
PATH=c:\Program FIles\Apache Software Foundation\apache-maven-3.2.3\bin;C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\AMD APP\bin\x86_64;C:\Program Files (x86)\AMD APP\bin\x86;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Windows Live\Shared;C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;C:\Program FIles\Java\jdk1.7.0_71\bin;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin;C:\Program Files (x86)\Git\cmd;C:\apache-maven-3.3.9-src\apache-maven-3.3.9\apache-maven\src
|
|
||||||
USERNAME=fireshoes
|
|
||||||
OS=Windows_NT
|
|
||||||
PROCESSOR_IDENTIFIER=AMD64 Family 18 Model 1 Stepping 0, AuthenticAMD
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------- S Y S T E M ---------------
|
|
||||||
|
|
||||||
OS: Windows 7 , 64 bit Build 7601 Service Pack 1
|
|
||||||
|
|
||||||
CPU:total 4 (4 cores per cpu, 1 threads per core) family 18 model 1 stepping 0, cmov, cx8, fxsr, mmx, sse, sse2, sse3, popcnt, mmxext, 3dnowpref, lzcnt, sse4a, tsc, tscinvbit, tscinv
|
|
||||||
|
|
||||||
Memory: 4k page, physical 3559120k(796500k free), swap 7967852k(857396k free)
|
|
||||||
|
|
||||||
vm_info: Java HotSpot(TM) 64-Bit Server VM (24.71-b01) for windows-amd64 JRE (1.7.0_71-b14), built on Sep 26 2014 16:16:12 by "java_re" with unknown MS VC++:1600
|
|
||||||
|
|
||||||
time: Wed Jan 20 09:21:37 2016
|
|
||||||
elapsed time: 0 seconds
|
|
||||||
|
|
||||||
4
pom.xml
4
pom.xml
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<groupId>org.mage</groupId>
|
<groupId>org.mage</groupId>
|
||||||
<artifactId>mage-root</artifactId>
|
<artifactId>mage-root</artifactId>
|
||||||
<version>1.4.7</version>
|
<version>1.4.8</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Mage Root</name>
|
<name>Mage Root</name>
|
||||||
<description>Mage Root POM</description>
|
<description>Mage Root POM</description>
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<mage-version>1.4.7</mage-version>
|
<mage-version>1.4.8</mage-version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue