forked from External/mage
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
|
||||
*.iml
|
||||
hs_err*.log
|
||||
/submitted
|
||||
|
||||
/Mage.Server/config/ai.please.cast.this.txt
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
XMage.de 1 (Europe/Germany) fast :xmage.de: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
|
||||
Seedds Server (Asia) :115.29.203.80:17171
|
||||
localhost -> connect to your local server (must be started):localhost:17171
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* TableWaitingDialog.java
|
||||
*
|
||||
* Created on Dec 16, 2009, 10:27:44 AM
|
||||
|
|
@ -68,7 +68,7 @@ public class TableWaitingDialog extends MageDialog {
|
|||
private Session session;
|
||||
private final TableWaitModel tableWaitModel;
|
||||
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
|
||||
|
|
@ -268,10 +268,8 @@ public class TableWaitingDialog extends MageDialog {
|
|||
if (session.startMatch(roomId, tableId)) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
if (session.startTournament(roomId, tableId)) {
|
||||
closeDialog();
|
||||
}
|
||||
} else if (session.startTournament(roomId, tableId)) {
|
||||
closeDialog();
|
||||
}
|
||||
}//GEN-LAST:event_btnStartActionPerformed
|
||||
|
||||
|
|
@ -319,7 +317,7 @@ public class TableWaitingDialog extends MageDialog {
|
|||
|
||||
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];
|
||||
|
||||
public void loadData(TableView table) {
|
||||
|
|
@ -353,6 +351,8 @@ class TableWaitModel extends AbstractTableModel {
|
|||
return seats[arg0].getPlayerName();
|
||||
case 3:
|
||||
return seats[arg0].getPlayerType();
|
||||
case 4:
|
||||
return seats[arg0].getHistory();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* PlayerPanel.java
|
||||
*
|
||||
* 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()
|
||||
+ "<br/>Country: " + countryname
|
||||
+ "<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
|
||||
StringBuilder tooltipText = new StringBuilder(basicTooltipText);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* ChatPanel.java
|
||||
*
|
||||
* 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 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.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());
|
||||
|
||||
jScrollPaneTalk.setSystemMessagesPane(colorPaneSystem);
|
||||
|
|
@ -118,7 +118,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
|
||||
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];
|
||||
|
||||
public void loadData(Collection<RoomUsersView> roomUserInfoList) throws MageRemoteException {
|
||||
|
|
@ -128,7 +128,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
TableColumnModel tcm = th.getColumnModel();
|
||||
|
||||
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()
|
||||
+ (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (")
|
||||
+ " limit: " + roomUserInfo.getNumberMaxGames() + ")");
|
||||
|
|
@ -156,10 +156,8 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
case 2:
|
||||
return players[arg0].getHistory();
|
||||
case 3:
|
||||
return players[arg0].getInfoState();
|
||||
case 4:
|
||||
return players[arg0].getInfoGames();
|
||||
case 5:
|
||||
case 4:
|
||||
return players[arg0].getInfoPing();
|
||||
}
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
/**
|
||||
* DownloadJob.java
|
||||
*
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
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.utils.CardImageUtils;
|
||||
|
||||
|
||||
/**
|
||||
* The class DownloadJob.
|
||||
*
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class DownloadJob extends AbstractLaternaBean {
|
||||
|
||||
public static enum State {
|
||||
|
||||
NEW, WORKING, FINISHED, ABORTED;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final Source source;
|
||||
private final Destination destination;
|
||||
private final Property<State> state = properties.property("state", State.NEW);
|
||||
private final Property<String> message = properties.property("message");
|
||||
private final Property<Exception> error = properties.property("error");
|
||||
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
||||
private final String name;
|
||||
private final Source source;
|
||||
private final Destination destination;
|
||||
private final Property<State> state = properties.property("state", State.NEW);
|
||||
private final Property<String> message = properties.property("message");
|
||||
private final Property<Exception> error = properties.property("error");
|
||||
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
||||
|
||||
public DownloadJob(String name, Source source, Destination destination) {
|
||||
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
|
||||
*/
|
||||
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
|
||||
* with the given message.
|
||||
* Sets the job's state to {@link State#ABORTED} and the error message to
|
||||
* the given message. Logs a warning with the given message.
|
||||
*
|
||||
* @param 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
|
||||
* given exception.
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given
|
||||
* exception. Logs a warning with the given exception.
|
||||
*
|
||||
* @param 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
|
||||
* given message and exception.
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given
|
||||
* exception. Logs a warning with the given message and exception.
|
||||
*
|
||||
* @param message
|
||||
* @param error
|
||||
*/
|
||||
public void setError(String message, Exception error) {
|
||||
if (message == null) {
|
||||
|
||||
|
||||
message = "Download of " + this.getName() + "from " + this.getSource().toString() + " caused error: " + error.toString();
|
||||
}
|
||||
// log.warn(message, error);
|
||||
|
|
@ -97,6 +101,7 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
|
||||
/**
|
||||
* Sets the job's message.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
|
|
@ -119,7 +124,6 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
return message.getValue();
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
@ -163,9 +167,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
|
||||
@Override
|
||||
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 {
|
||||
return getConnection().getContentLength();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() throws IOException {
|
||||
if (file.isFile()) {
|
||||
return file.length() > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return file.isFile();
|
||||
|
|
@ -228,16 +240,20 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
}
|
||||
|
||||
public interface Source {
|
||||
|
||||
InputStream open() throws IOException;
|
||||
|
||||
int length() throws IOException;
|
||||
}
|
||||
|
||||
public interface Destination {
|
||||
|
||||
OutputStream open() throws IOException;
|
||||
|
||||
boolean exists() throws IOException;
|
||||
|
||||
boolean isValid() throws IOException;
|
||||
|
||||
void delete() throws IOException;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
/**
|
||||
* Downloader.java
|
||||
*
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
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.lm.AbstractLaternaBean;
|
||||
|
||||
|
||||
/**
|
||||
* The class Downloader.
|
||||
*
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
|
|
@ -40,16 +38,16 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
|
||||
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 ExecutorService pool = Executors.newCachedThreadPool();
|
||||
private final List<Fiber> fibers = new ArrayList<>();
|
||||
private final ExecutorService pool = Executors.newCachedThreadPool();
|
||||
private final List<Fiber> fibers = new ArrayList<>();
|
||||
|
||||
public Downloader() {
|
||||
PoolFiberFactory f = new PoolFiberFactory(pool);
|
||||
//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.start();
|
||||
fibers.add(fiber);
|
||||
|
|
@ -59,15 +57,15 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
|
||||
@Override
|
||||
public void dispose() {
|
||||
for(DownloadJob j:getJobs()) {
|
||||
switch(j.getState()) {
|
||||
for (DownloadJob j : getJobs()) {
|
||||
switch (j.getState()) {
|
||||
case NEW:
|
||||
case WORKING:
|
||||
j.setState(State.ABORTED);
|
||||
}
|
||||
}
|
||||
|
||||
for(Fiber f:fibers) {
|
||||
for (Fiber f : fibers) {
|
||||
f.dispose();
|
||||
}
|
||||
pool.shutdown();
|
||||
|
|
@ -84,10 +82,10 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
}
|
||||
|
||||
public void add(DownloadJob job) {
|
||||
if(job.getState() == State.WORKING) {
|
||||
if (job.getState() == State.WORKING) {
|
||||
throw new IllegalArgumentException("Job already running");
|
||||
}
|
||||
if(job.getState() == State.FINISHED) {
|
||||
if (job.getState() == State.FINISHED) {
|
||||
throw new IllegalArgumentException("Job already finished");
|
||||
}
|
||||
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
|
||||
* download job's state to reflect the progress.
|
||||
* Performs the download job: Transfers data from {@link Source} to
|
||||
* {@link Destination} and updates the download job's state to reflect the
|
||||
* progress.
|
||||
*/
|
||||
private class DownloadCallback implements Callback<DownloadJob> {
|
||||
|
||||
@Override
|
||||
public void onMessage(DownloadJob job) {
|
||||
//the job won't be processed by multiple threads
|
||||
synchronized(job) {
|
||||
if(job.getState() != State.NEW) {
|
||||
synchronized (job) {
|
||||
if (job.getState() != State.NEW) {
|
||||
return;
|
||||
}
|
||||
job.setState(State.WORKING);
|
||||
|
|
@ -118,10 +118,17 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
Destination dst = job.getDestination();
|
||||
BoundedRangeModel progress = job.getProgress();
|
||||
|
||||
if(dst.exists()) {
|
||||
if (dst.isValid()) {
|
||||
progress.setMaximum(1);
|
||||
progress.setValue(1);
|
||||
} else {
|
||||
if (dst.exists()) {
|
||||
try {
|
||||
dst.delete();
|
||||
} catch (IOException ex1) {
|
||||
logger.warn("While deleting not valid file", ex1);
|
||||
}
|
||||
}
|
||||
progress.setMaximum(src.length());
|
||||
InputStream is = new BufferedInputStream(src.open());
|
||||
try {
|
||||
|
|
@ -129,45 +136,45 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
try {
|
||||
byte[] buf = new byte[8 * 1024];
|
||||
int total = 0;
|
||||
for(int len; (len = is.read(buf)) != -1;) {
|
||||
if(job.getState() == State.ABORTED) {
|
||||
for (int len; (len = is.read(buf)) != -1;) {
|
||||
if (job.getState() == State.ABORTED) {
|
||||
throw new IOException("Job was aborted");
|
||||
}
|
||||
progress.setValue(total += len);
|
||||
os.write(buf, 0, len);
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
dst.delete();
|
||||
} catch(IOException ex1) {
|
||||
} catch (IOException ex1) {
|
||||
logger.warn("While deleting", ex1);
|
||||
}
|
||||
throw ex;
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
} catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
logger.warn("While closing", ex);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
logger.warn("While closing", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
job.setState(State.FINISHED);
|
||||
} catch(ConnectException ex) {
|
||||
} catch (ConnectException ex) {
|
||||
String message;
|
||||
if (ex.getMessage() != null) {
|
||||
message = ex.getMessage();
|
||||
} else {
|
||||
message = "Unknown error";
|
||||
}
|
||||
logger.warn("Error resource download " + job.getName() +" from "+ job.getSource().toString() + ": " + message);
|
||||
} catch(IOException ex) {
|
||||
logger.warn("Error resource download " + job.getName() + " from " + job.getSource().toString() + ": " + message);
|
||||
} catch (IOException ex) {
|
||||
job.setError(ex);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<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_MINOR = 4;
|
||||
public final static int MAGE_VERSION_PATCH = 7;
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v1";
|
||||
public final static int MAGE_VERSION_PATCH = 8;
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v0";
|
||||
public final static String MAGE_VERSION_INFO = "";
|
||||
|
||||
private final int major;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public class SeatView implements Serializable {
|
|||
private UUID playerId;
|
||||
private final String playerName;
|
||||
private final String playerType;
|
||||
private final String history;
|
||||
|
||||
public SeatView(Seat seat) {
|
||||
if (seat.getPlayer() != null) {
|
||||
|
|
@ -51,13 +52,16 @@ public class SeatView implements Serializable {
|
|||
this.playerName = seat.getPlayer().getName();
|
||||
if (seat.getPlayer().getUserData() == null) {
|
||||
this.flagName = UserData.getDefaultFlagName();
|
||||
this.history = "";
|
||||
} else {
|
||||
this.flagName = seat.getPlayer().getUserData().getFlagName();
|
||||
this.history = seat.getPlayer().getUserData().getHistory();
|
||||
}
|
||||
} else {
|
||||
// Empty seat
|
||||
this.playerName = "";
|
||||
this.flagName = "";
|
||||
this.history = "";
|
||||
}
|
||||
this.playerType = seat.getPlayerType();
|
||||
}
|
||||
|
|
@ -78,4 +82,8 @@ public class SeatView implements Serializable {
|
|||
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
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
*/
|
||||
package mage.view;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -40,15 +40,13 @@ public class UsersView implements Serializable {
|
|||
private final String flagName;
|
||||
private final String userName;
|
||||
private final String history;
|
||||
private final String infoState;
|
||||
private final String infoGames;
|
||||
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.history = history;
|
||||
this.userName = userName;
|
||||
this.infoState = infoState;
|
||||
this.infoGames = infoGames;
|
||||
this.infoPing = infoPing;
|
||||
}
|
||||
|
|
@ -65,10 +63,6 @@ public class UsersView implements Serializable {
|
|||
return history;
|
||||
}
|
||||
|
||||
public String getInfoState() {
|
||||
return infoState;
|
||||
}
|
||||
|
||||
public String getInfoGames() {
|
||||
return infoGames;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-counter-plugin</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-plugins</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-deck-constructed</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-deck-limited</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-commanderduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-commanderfreeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeforall</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-momirduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-tinyleadersduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-twoplayerduel</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-draftbot</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-ma</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-mcts</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-aiminimax</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-human</artifactId>
|
||||
|
|
|
|||
|
|
@ -358,15 +358,13 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (target.canTarget(response.getUUID(), game)) {
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
target.addTarget(response.getUUID(), null, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
} else if (target.canTarget(response.getUUID(), game)) {
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
target.addTarget(response.getUUID(), null, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -530,12 +528,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (response.getUUID() != null) {
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
target.addTarget(response.getUUID(), source, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
} else if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
target.addTarget(response.getUUID(), source, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1065,10 +1061,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
// does not block yet and can block or can block more attackers
|
||||
if (filter.match(blocker, null, playerId, game)) {
|
||||
selectCombatGroup(defendingPlayerId, blocker.getId(), game);
|
||||
} else {
|
||||
if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) {
|
||||
removeBlocker = true;
|
||||
}
|
||||
} else if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) {
|
||||
removeBlocker = true;
|
||||
}
|
||||
|
||||
if (removeBlocker) {
|
||||
|
|
@ -1546,4 +1540,9 @@ public class HumanPlayer extends PlayerImpl {
|
|||
pass(game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHistory() {
|
||||
return "no available";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-boosterdraft</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-constructed</artifactId>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-sealed</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,17 @@
|
|||
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"
|
||||
serverName="mage-server"
|
||||
|
|
@ -37,10 +48,15 @@
|
|||
maxPasswordLength="100"
|
||||
maxAiOpponents="15"
|
||||
saveGameActivated="false"
|
||||
authenticationActivated="false"
|
||||
authenticationActivated="true"
|
||||
googleAccount=""
|
||||
mailgunApiKey=""
|
||||
mailgunDomain=""
|
||||
mailgunApiKey="key-d93e81f19a9c9ed243ebb7cc9381385c"
|
||||
mailgunDomain="sandbox401a433f30d445309a5e86b6c53f7812.mailgun.org"
|
||||
mailSmtpHost="smtp.1und1.de"
|
||||
mailSmtpPort="465"
|
||||
mailUser="xmageserver@online.de"
|
||||
mailPassword="24wrsfxv"
|
||||
mailFromAddress="xmageserver@online.de"
|
||||
/>
|
||||
<playerTypes>
|
||||
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<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"
|
||||
serverName="mage-server"
|
||||
port="17171"
|
||||
|
|
@ -18,6 +48,13 @@
|
|||
saveGameActivated="false"
|
||||
authenticationActivated="false"
|
||||
googleAccount=""
|
||||
mailgunApiKey=""
|
||||
mailgunDomain=""
|
||||
mailSmtpHost=""
|
||||
mailSmtpPort=""
|
||||
mailUser=""
|
||||
mailPassword=""
|
||||
mailFromAddress=""
|
||||
/>
|
||||
<playerTypes>
|
||||
<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
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -44,14 +43,15 @@ import org.apache.log4j.Logger;
|
|||
public class ChatManager {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ChatManager.class);
|
||||
|
||||
|
||||
private static final ChatManager INSTANCE = new ChatManager();
|
||||
|
||||
public static ChatManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private ChatManager() {}
|
||||
private ChatManager() {
|
||||
}
|
||||
|
||||
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
|
||||
|
||||
|
|
@ -66,16 +66,16 @@ public class ChatManager {
|
|||
if (chatSession != null) {
|
||||
chatSession.join(userId);
|
||||
} 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) {
|
||||
ChatSession chatSession = chatSessions.get(chatId);
|
||||
if (chatSession != null && chatSession.hasUser(userId)) {
|
||||
chatSession.kill(userId, DisconnectReason.CleaningUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyChatSession(UUID chatId) {
|
||||
|
|
@ -88,7 +88,7 @@ public class ChatManager {
|
|||
logger.trace("Chat removed - chatId: " + chatId);
|
||||
} else {
|
||||
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) {
|
||||
String command = message.substring(1).trim().toUpperCase(Locale.ENGLISH);
|
||||
if (command.equals("I") || command.equals("INFO")) {
|
||||
user.setInfo("");
|
||||
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);
|
||||
if (command.startsWith("H ") || command.startsWith("HISTORY ")) {
|
||||
message = UserManager.getInstance().getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9));
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
return true;
|
||||
}
|
||||
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(" ");
|
||||
if (first > 1) {
|
||||
String userToName = rest.substring(0,first);
|
||||
String userToName = rest.substring(0, first);
|
||||
rest = rest.substring(first + 1).trim();
|
||||
User userTo = UserManager.getInstance().getUserByName(userToName);
|
||||
if (userTo != null) {
|
||||
if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo, rest)) {
|
||||
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (command.equals("L") || command.equals("LIST")) {
|
||||
message += new StringBuilder("<br/>List of commands:")
|
||||
.append("<br/>\\info [text] - set a info text to your player")
|
||||
.append("<br/>\\list - Show a list of commands")
|
||||
.append("<br/>\\whisper [player name] [text] - whisper to the player with the given name").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
.append("<br/>\\history or \\h [username] - shows the history of a player")
|
||||
.append("<br/>\\list or \\l - Show a list of commands")
|
||||
.append("<br/>\\whisper or \\w [player name] [text] - whisper to the player with the given name").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
return true;
|
||||
}
|
||||
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 message
|
||||
* @param color
|
||||
* @param color
|
||||
*/
|
||||
public void broadcast(UUID userId, String message, MessageColor color) {
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
for (ChatSession chat: chatSessions.values()) {
|
||||
for (ChatSession chat : chatSessions.values()) {
|
||||
if (chat.hasUser(userId)) {
|
||||
chat.broadcast(user.getName(), message, color);
|
||||
}
|
||||
|
|
@ -186,16 +179,16 @@ public class ChatManager {
|
|||
public void sendReconnectMessage(UUID userId) {
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
for (ChatSession chat: chatSessions.values()) {
|
||||
for (ChatSession chat : chatSessions.values()) {
|
||||
if (chat.hasUser(userId)) {
|
||||
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeUser(UUID userId, DisconnectReason reason) {
|
||||
for (ChatSession chatSession: chatSessions.values()) {
|
||||
for (ChatSession chatSession : chatSessions.values()) {
|
||||
if (chatSession.hasUser(userId)) {
|
||||
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 ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
|
||||
private final String adminPassword;
|
||||
private final boolean testMode;
|
||||
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
||||
|
|
@ -140,9 +140,16 @@ public class MageServerImpl implements MageServer {
|
|||
}
|
||||
String authToken = generateAuthToken();
|
||||
activeAuthTokens.put(email, authToken);
|
||||
if (!MailgunClient.sendMessage(email, "XMage Password Reset Auth Token",
|
||||
"Use this auth token to reset your password: " + authToken + "\n" +
|
||||
"It's valid until the next server restart.")) {
|
||||
String subject = "XMage Password Reset Auth Token";
|
||||
String text = "Use this auth token to reset your password: " + authToken + "\n"
|
||||
+ "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");
|
||||
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.MalformedURLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.management.MBeanServer;
|
||||
import mage.cards.repository.CardScanner;
|
||||
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.interfaces.MageServer;
|
||||
import mage.remote.Connection;
|
||||
|
|
@ -53,9 +43,6 @@ import mage.server.draft.CubeFactory;
|
|||
import mage.server.game.DeckValidatorFactory;
|
||||
import mage.server.game.GameFactory;
|
||||
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.tournament.TournamentFactory;
|
||||
import mage.server.util.ConfigSettings;
|
||||
|
|
@ -102,8 +89,6 @@ public class Main {
|
|||
protected static boolean testMode;
|
||||
protected static boolean fastDbMode;
|
||||
|
||||
private static final ScheduledExecutorService updateUserStatsTaskExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
|
|
@ -132,6 +117,10 @@ public class Main {
|
|||
}
|
||||
logger.info("Done.");
|
||||
|
||||
logger.info("Updating user stats DB...");
|
||||
UserStatsRepository.instance.updateUserStats();
|
||||
logger.info("Done.");
|
||||
|
||||
deleteSavedGames();
|
||||
ConfigSettings config = ConfigSettings.getInstance();
|
||||
for (GamePlugin plugin : config.getGameTypes()) {
|
||||
|
|
@ -167,7 +156,12 @@ public class Main {
|
|||
logger.info("Config - auth. activated : " + (config.isAuthenticationActivated() ? "true" : "false"));
|
||||
logger.info("Config - mailgun api key : " + config.getMailgunApiKey());
|
||||
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.setHost(config.getServerAddress());
|
||||
|
|
@ -190,13 +184,6 @@ public class Main {
|
|||
} catch (Exception 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() {
|
||||
|
|
@ -391,78 +378,4 @@ public class Main {
|
|||
public static boolean isTestMode() {
|
||||
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;
|
||||
}
|
||||
AuthorizedUserRepository.instance.add(userName, password, email);
|
||||
if (MailgunClient.sendMessage(email, "XMage Registration Completed",
|
||||
"You are successfully registered as " + userName + ".")) {
|
||||
String subject = "XMage Registration Completed";
|
||||
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);
|
||||
} else {
|
||||
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.constants.ManaType;
|
||||
import mage.game.Table;
|
||||
import mage.game.result.ResultProtos;
|
||||
import mage.game.tournament.TournamentPlayer;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
import mage.players.net.UserData;
|
||||
|
|
@ -61,7 +62,7 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
public class User {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(User.class);
|
||||
private static final Logger LOGGER = Logger.getLogger(User.class);
|
||||
|
||||
public enum UserState {
|
||||
|
||||
|
|
@ -81,7 +82,6 @@ public class User {
|
|||
private final Map<UUID, Deck> sideboarding;
|
||||
private final List<UUID> watchedGames;
|
||||
private String sessionId;
|
||||
private String info = "";
|
||||
private String pingInfo = "";
|
||||
private Date lastActivity;
|
||||
private UserState userState;
|
||||
|
|
@ -106,6 +106,7 @@ public class User {
|
|||
this.watchedGames = new ArrayList<>();
|
||||
this.tablesToDelete = new ArrayList<>();
|
||||
this.sessionId = "";
|
||||
this.userStats = null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
@ -129,15 +130,15 @@ public class User {
|
|||
if (sessionId.isEmpty()) {
|
||||
userState = UserState.Disconnected;
|
||||
lostConnection();
|
||||
logger.trace("USER - lost connection: " + userName + " id: " + userId);
|
||||
LOGGER.trace("USER - lost connection: " + userName + " id: " + userId);
|
||||
|
||||
} else if (userState == UserState.Created) {
|
||||
userState = UserState.Connected;
|
||||
logger.trace("USER - created: " + userName + " id: " + userId);
|
||||
LOGGER.trace("USER - created: " + userName + " id: " + userId);
|
||||
} else {
|
||||
userState = UserState.Reconnected;
|
||||
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) {
|
||||
if (lastActivity.before(expired)) {
|
||||
logger.trace(userName + " is expired!");
|
||||
LOGGER.trace(userName + " is expired!");
|
||||
userState = UserState.Expired;
|
||||
return true;
|
||||
}
|
||||
logger.trace(new StringBuilder("isExpired: User ").append(userName).append(" lastActivity: ").append(lastActivity).append(" expired: ").append(expired).toString());
|
||||
return false; /*userState == UserState.Disconnected && */
|
||||
LOGGER.trace(new StringBuilder("isExpired: User ").append(userName).append(" lastActivity: ").append(lastActivity).append(" expired: ").append(expired).toString());
|
||||
return false;
|
||||
/*userState == UserState.Disconnected && */
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -360,35 +362,35 @@ public class User {
|
|||
}
|
||||
|
||||
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()) {
|
||||
draftSession.setKilled();
|
||||
}
|
||||
draftSessions.clear();
|
||||
logger.trace("REMOVE " + getName() + " Tournament sessions " + userTournaments.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Tournament sessions " + userTournaments.size());
|
||||
for (UUID tournamentId : userTournaments.values()) {
|
||||
TournamentManager.getInstance().quit(tournamentId, getId());
|
||||
}
|
||||
userTournaments.clear();
|
||||
logger.trace("REMOVE " + getName() + " Tables " + tables.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Tables " + tables.size());
|
||||
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());
|
||||
}
|
||||
tables.clear();
|
||||
logger.trace("REMOVE " + getName() + " Game sessions: " + gameSessions.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Game sessions: " + gameSessions.size());
|
||||
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);
|
||||
gameSessionPlayer.quitGame();
|
||||
}
|
||||
gameSessions.clear();
|
||||
logger.trace("REMOVE " + getName() + " watched Games " + watchedGames.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " watched Games " + watchedGames.size());
|
||||
for (UUID gameId : watchedGames) {
|
||||
GameManager.getInstance().stopWatching(gameId, userId);
|
||||
}
|
||||
watchedGames.clear();
|
||||
logger.trace("REMOVE " + getName() + " Chats ");
|
||||
LOGGER.trace("REMOVE " + getName() + " Chats ");
|
||||
ChatManager.getInstance().removeUser(userId, reason);
|
||||
}
|
||||
|
||||
|
|
@ -397,6 +399,12 @@ public class User {
|
|||
this.userData.update(userData);
|
||||
} else {
|
||||
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 {
|
||||
// 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());
|
||||
}
|
||||
} else {
|
||||
logger.error(getName() + " tournament key missing - tableId: " + table.getId(), null);
|
||||
LOGGER.error(getName() + " tournament key missing - tableId: " + table.getId(), null);
|
||||
}
|
||||
} else {
|
||||
switch (table.getState()) {
|
||||
|
|
@ -500,14 +508,6 @@ public class User {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public void setInfo(String Info) {
|
||||
this.info = Info;
|
||||
}
|
||||
|
||||
public void addGameWatchInfo(UUID gameId) {
|
||||
watchedGames.add(gameId);
|
||||
}
|
||||
|
|
@ -540,5 +540,84 @@ public class User {
|
|||
// resetUserStats loads UserStats from DB.
|
||||
public void resetUserStats() {
|
||||
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.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
* 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.
|
||||
|
|
@ -38,6 +38,8 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import mage.server.User.UserState;
|
||||
import mage.server.record.UserStats;
|
||||
import mage.server.record.UserStatsRepository;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
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
|
||||
* activity the user is removed
|
||||
*
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class UserManager {
|
||||
|
|
@ -56,7 +58,7 @@ public class UserManager {
|
|||
|
||||
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, User> usersByName = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||
|
||||
private static final UserManager INSTANCE = new UserManager();
|
||||
|
|
@ -64,8 +66,8 @@ public class UserManager {
|
|||
public static UserManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private UserManager() {
|
||||
|
||||
private UserManager() {
|
||||
expireExecutor.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
@ -113,7 +115,7 @@ public class UserManager {
|
|||
public void disconnect(UUID userId, DisconnectReason reason) {
|
||||
if (userId != null) {
|
||||
User user = users.get(userId);
|
||||
if (user != null) {
|
||||
if (user != null) {
|
||||
user.setSessionId(""); // Session will be set again with new id if user reconnects
|
||||
}
|
||||
ChatManager.getInstance().removeUser(userId, reason);
|
||||
|
|
@ -123,44 +125,44 @@ public class UserManager {
|
|||
public boolean isAdmin(UUID userId) {
|
||||
if (userId != null) {
|
||||
User user = users.get(userId);
|
||||
if (user != null) {
|
||||
if (user != null) {
|
||||
return user.getName().equals("Admin");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeUser(final UUID userId, final DisconnectReason reason) {
|
||||
public void removeUser(final UUID userId, final DisconnectReason reason) {
|
||||
if (userId != null) {
|
||||
final User user = users.get(userId);
|
||||
if (user != null) {
|
||||
callExecutor.execute(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId);
|
||||
user.remove(reason);
|
||||
logger.debug("USER REMOVE END - " + user.getName());
|
||||
} catch (Exception ex) {
|
||||
handleException(ex);
|
||||
} finally {
|
||||
users.remove(userId);
|
||||
usersByName.remove(user.getName());
|
||||
}
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId);
|
||||
user.remove(reason);
|
||||
logger.debug("USER REMOVE END - " + user.getName());
|
||||
} catch (Exception ex) {
|
||||
handleException(ex);
|
||||
} finally {
|
||||
users.remove(userId);
|
||||
usersByName.remove(user.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
logger.warn("Trying to remove userId: " + userId + " - but it does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean extendUserSession(UUID userId, String pingInfo) {
|
||||
if (userId != null) {
|
||||
User user = users.get(userId);
|
||||
if (user != null) {
|
||||
if (user != null) {
|
||||
user.updateLastActivity(pingInfo);
|
||||
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() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
|
@ -185,13 +188,39 @@ public class UserManager {
|
|||
|
||||
public void handleException(Exception ex) {
|
||||
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) {
|
||||
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null":ex.getCause().getMessage()));
|
||||
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null" : ex.getCause().getMessage()));
|
||||
}
|
||||
ex.printStackTrace();
|
||||
}else {
|
||||
} else {
|
||||
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.Table;
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.game.result.ResultProtos.UserStatsProto;
|
||||
import mage.game.tournament.TournamentOptions;
|
||||
import mage.server.RoomImpl;
|
||||
import mage.server.TableManager;
|
||||
import mage.server.User;
|
||||
import mage.server.UserManager;
|
||||
import mage.server.record.UserStats;
|
||||
import mage.server.tournament.TournamentManager;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
|
|
@ -93,74 +91,6 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
|||
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() {
|
||||
ArrayList<TableView> tableList = new ArrayList<>();
|
||||
ArrayList<MatchView> matchList = new ArrayList<>();
|
||||
|
|
@ -183,20 +113,14 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
|||
matchView = matchList;
|
||||
List<UsersView> users = new ArrayList<>();
|
||||
for (User user : UserManager.getInstance().getUsers()) {
|
||||
String history = null;
|
||||
UserStats stats = user.getUserStats();
|
||||
if (stats != null) {
|
||||
history = userStatsToString(stats.getProto());
|
||||
}
|
||||
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) {
|
||||
logger.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex);
|
||||
users.add(new UsersView(
|
||||
(user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world",
|
||||
user.getName() != null ? user.getName() : "<no name>",
|
||||
history != null ? history : "<no history>",
|
||||
user.getInfo() != null ? user.getInfo() : "<no info>",
|
||||
user.getHistory() != null ? user.getHistory() : "<no history>",
|
||||
"[exception]",
|
||||
user.getPingInfo() != null ? user.getPingInfo() : "<no ping>"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mage.server.record;
|
|||
import mage.game.Table;
|
||||
import mage.game.Table.TableRecorder;
|
||||
import mage.game.result.ResultProtos.TableProto;
|
||||
import mage.server.UserManager;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class TableRecorderImpl implements TableRecorder {
|
||||
|
|
@ -17,5 +18,6 @@ public class TableRecorderImpl implements TableRecorder {
|
|||
public void record(Table table) {
|
||||
TableProto proto = table.toProto();
|
||||
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 java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import mage.cards.repository.RepositoryUtil;
|
||||
import mage.game.result.ResultProtos;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public enum UserStatsRepository {
|
||||
|
|
@ -98,6 +101,79 @@ public enum UserStatsRepository {
|
|||
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() {
|
||||
try {
|
||||
if (dao != null && dao.getConnectionSource() != null) {
|
||||
|
|
|
|||
|
|
@ -147,6 +147,26 @@ public class ConfigSettings {
|
|||
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() {
|
||||
return config.getPlayerTypes().getPlayerType();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@
|
|||
<xs:attribute name="googleAccount" 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="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:element>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ import mage.constants.Layer;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
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;
|
||||
|
|
@ -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.
|
||||
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) {
|
||||
|
|
@ -91,7 +102,7 @@ class ConsumeStrengthEffect extends ContinuousEffectImpl {
|
|||
permanent.addPower(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) {
|
||||
permanent.addPower(-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}");
|
||||
this.expansionSetCode = "EVE";
|
||||
|
||||
|
||||
// Counter target spell. Its controller draws a card.
|
||||
this.getSpellAbility().addEffect(new DreamFractureEffect());
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
|
|
@ -73,7 +72,7 @@ class DreamFractureEffect extends OneShotEffect {
|
|||
|
||||
public DreamFractureEffect() {
|
||||
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) {
|
||||
|
|
@ -102,4 +101,4 @@ class DreamFractureEffect extends OneShotEffect {
|
|||
}
|
||||
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.
|
||||
getSpellAbility().addEffect(new MoveCounterFromTargetToTargetEffect());
|
||||
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() {
|
||||
super();
|
||||
this.filter = new FilterCreaturePermanent("another target creature with the same controller (counters go to)");
|
||||
private static final FilterCreaturePermanent 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);
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +138,7 @@ class BioshiftSecondTargetPermanent extends TargetPermanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BioshiftSecondTargetPermanent copy() {
|
||||
return new BioshiftSecondTargetPermanent(this);
|
||||
public BioshiftSecondTargetCreaturePermanent copy() {
|
||||
return new BioshiftSecondTargetCreaturePermanent(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ import mage.constants.Layer;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
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;
|
||||
|
|
@ -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.
|
||||
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) {
|
||||
|
|
@ -88,7 +100,7 @@ class SchismotivateEffect extends ContinuousEffectImpl {
|
|||
if (permanent != null) {
|
||||
permanent.addPower(4);
|
||||
}
|
||||
permanent = game.getPermanent(source.getTargets().get(0).getTargets().get(1));
|
||||
permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
if (permanent != null) {
|
||||
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.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
* @author nantuko
|
||||
|
|
@ -87,8 +86,8 @@ public class AdaptiveAutomaton extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class AdaptiveAutomatonAddSubtypeEffect extends ContinuousEffectImpl {
|
||||
|
||||
public AdaptiveAutomatonAddSubtypeEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||
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.Rarity;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
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.
|
||||
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) {
|
||||
|
|
@ -86,9 +103,9 @@ class IncrementalGrowthEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int i = 0;
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
for (Target target : source.getTargets()) {
|
||||
i++;
|
||||
Permanent creature = game.getPermanent(targetId);
|
||||
Permanent creature = game.getPermanent(target.getFirstTarget());
|
||||
if (creature != null) {
|
||||
creature.addCounters(CounterType.P1P1.createInstance(i), game);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,15 +28,20 @@
|
|||
package mage.sets.newphyrexia;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
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.targetpointer.SecondTargetPointer;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -48,16 +53,20 @@ public class LeechingBite extends CardImpl {
|
|||
super(ownerId, 113, "Leeching Bite", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{G}");
|
||||
this.expansionSetCode = "NPH";
|
||||
|
||||
|
||||
// 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);
|
||||
effect.setText("Target creature gets +1/+1 until end of turn");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (getting the +1/+1 counter)")));
|
||||
effect = new BoostTargetEffect(-1, -1, Duration.EndOfTurn);
|
||||
effect.setText("Another target creature gets -1/-1 until end of turn");
|
||||
effect.setTargetPointer(new SecondTargetPointer());
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (getting the -1/-1 counter)")));
|
||||
this.getSpellAbility().addEffect(new LeechingBiteEffect());
|
||||
|
||||
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature to get +1/+1");
|
||||
TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1);
|
||||
target1.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target1);
|
||||
|
||||
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature to get -1/-1");
|
||||
filter2.add(new AnotherTargetPredicate(2));
|
||||
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2);
|
||||
target2.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target2);
|
||||
}
|
||||
|
||||
public LeechingBite(final LeechingBite card) {
|
||||
|
|
@ -69,3 +78,35 @@ public class LeechingBite extends CardImpl {
|
|||
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.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
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;
|
||||
|
|
@ -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.
|
||||
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) {
|
||||
|
|
@ -89,7 +101,7 @@ class StealStrengthEffect extends ContinuousEffectImpl {
|
|||
permanent.addPower(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) {
|
||||
permanent.addPower(-1);
|
||||
permanent.addToughness(-1);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ import mage.constants.SubLayer;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.CardImpl;
|
||||
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;
|
||||
|
|
@ -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.
|
||||
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) {
|
||||
|
|
@ -90,7 +102,7 @@ class RitesOfReapingEffect extends ContinuousEffectImpl {
|
|||
permanent.addPower(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) {
|
||||
permanent.addPower(-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.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.discard.DiscardTargetEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -42,7 +40,6 @@ import mage.constants.Rarity;
|
|||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -94,14 +91,17 @@ class CragganwickCrematorEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player you = game.getPlayer(source.getControllerId());
|
||||
Player targetedPlayer = game.getPlayer(source.getFirstTarget());
|
||||
if (you != null && targetedPlayer != null) {
|
||||
Card discardedCard = targetedPlayer.discardOne(true, source, game);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
||||
if (controller != null) {
|
||||
Card discardedCard = controller.discardOne(true, source, game);
|
||||
if (discardedCard != null
|
||||
&& discardedCard.getCardType().contains(CardType.CREATURE)) {
|
||||
int damage = discardedCard.getPower().getValue();
|
||||
targetedPlayer.damage(damage, source.getSourceId(), game, false, true);
|
||||
Player targetedPlayer = game.getPlayer(source.getFirstTarget());
|
||||
if (targetedPlayer != null) {
|
||||
int damage = discardedCard.getPower().getValue();
|
||||
targetedPlayer.damage(damage, source.getSourceId(), game, false, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Rarity;
|
||||
import mage.counters.Counter;
|
||||
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;
|
||||
|
|
@ -47,7 +48,7 @@ import mage.target.common.TargetCreaturePermanent;
|
|||
public class FateTransfer extends CardImpl {
|
||||
|
||||
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) {
|
||||
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.
|
||||
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.cards.CardImpl;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
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.
|
||||
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) {
|
||||
|
|
@ -85,9 +102,9 @@ class IncrementalBlightEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int i = 0;
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
for (Target target : source.getTargets()) {
|
||||
i++;
|
||||
Permanent creature = game.getPermanent(targetId);
|
||||
Permanent creature = game.getPermanent(target.getFirstTarget());
|
||||
if (creature != null) {
|
||||
creature.addCounters(CounterType.M1M1.createInstance(i), game);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class RealmRazerEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
ExileZone exZone = game.getExile().getExileZone(source.getSourceId());
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
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.constants.Duration;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
|
@ -54,10 +56,18 @@ public class FeralContest extends CardImpl {
|
|||
|
||||
// Put a +1/+1 counter on target creature you control.
|
||||
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.
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tests</artifactId>
|
||||
|
|
|
|||
|
|
@ -2077,4 +2077,8 @@ public class TestPlayer implements Player {
|
|||
return AIPlayer;
|
||||
}
|
||||
|
||||
public String getHistory() {
|
||||
return computerPlayer.getHistory();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
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.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
|
@ -25,19 +35,13 @@ import org.junit.BeforeClass;
|
|||
import org.mage.test.player.RandomPlayer;
|
||||
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.
|
||||
*
|
||||
* @author ayratn
|
||||
*/
|
||||
public abstract class MageTestBase {
|
||||
|
||||
protected static Logger logger = Logger.getLogger(MageTestBase.class);
|
||||
|
||||
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 List<Card> handCardsA = new ArrayList<Card>();
|
||||
protected List<Card> handCardsB = new ArrayList<Card>();
|
||||
protected List<PermanentCard> battlefieldCardsA = new ArrayList<PermanentCard>();
|
||||
protected List<PermanentCard> battlefieldCardsB = new ArrayList<PermanentCard>();
|
||||
protected List<Card> graveyardCardsA = new ArrayList<Card>();
|
||||
protected List<Card> graveyardCardsB = new ArrayList<Card>();
|
||||
protected List<Card> libraryCardsA = new ArrayList<Card>();
|
||||
protected List<Card> libraryCardsB = new ArrayList<Card>();
|
||||
protected List<Card> handCardsA = new ArrayList<>();
|
||||
protected List<Card> handCardsB = new ArrayList<>();
|
||||
protected List<PermanentCard> battlefieldCardsA = new ArrayList<>();
|
||||
protected List<PermanentCard> battlefieldCardsB = new ArrayList<>();
|
||||
protected List<Card> graveyardCardsA = new ArrayList<>();
|
||||
protected List<Card> graveyardCardsB = new ArrayList<>();
|
||||
protected List<Card> libraryCardsA = new ArrayList<>();
|
||||
protected List<Card> libraryCardsB = new ArrayList<>();
|
||||
|
||||
protected Map<Zone, String> commandsA = new HashMap<Zone, String>();
|
||||
protected Map<Zone, String> commandsB = new HashMap<Zone, String>();
|
||||
protected Map<Zone, String> commandsA = new HashMap<>();
|
||||
protected Map<Zone, String> commandsB = new HashMap<>();
|
||||
|
||||
protected TestPlayer playerA;
|
||||
protected TestPlayer playerB;
|
||||
|
|
@ -67,8 +71,7 @@ public abstract class MageTestBase {
|
|||
protected static Game currentGame = null;
|
||||
|
||||
/**
|
||||
* Player thats starts the game first.
|
||||
* By default, it is ComputerA.
|
||||
* Player thats starts the game first. By default, it is ComputerA.
|
||||
*/
|
||||
protected static Player activePlayer = null;
|
||||
|
||||
|
|
@ -77,6 +80,7 @@ public abstract class MageTestBase {
|
|||
protected PhaseStep stopAtStep = PhaseStep.UNTAP;
|
||||
|
||||
protected enum ParserState {
|
||||
|
||||
INIT,
|
||||
OPTIONS,
|
||||
EXPECTED
|
||||
|
|
@ -85,18 +89,13 @@ public abstract class MageTestBase {
|
|||
protected ParserState parserState;
|
||||
|
||||
/**
|
||||
* Expected results of the test.
|
||||
* Read from test case in {@link String} based format:
|
||||
* Expected results of the test. Read from test case in {@link String} based
|
||||
* format:
|
||||
* <p/>
|
||||
* Example:
|
||||
* turn:1
|
||||
* result:won:ComputerA
|
||||
* life:ComputerA:20
|
||||
* life:ComputerB:0
|
||||
* battlefield:ComputerB:Tine Shrike:0
|
||||
* graveyard:ComputerB:Tine Shrike:1
|
||||
* Example: turn: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;
|
||||
|
||||
|
|
@ -163,8 +162,9 @@ public abstract class MageTestBase {
|
|||
|
||||
private static void deleteSavedGames() {
|
||||
File directory = new File("saved/");
|
||||
if (!directory.exists())
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
File[] files = directory.listFiles(
|
||||
new FilenameFilter() {
|
||||
@Override
|
||||
|
|
@ -185,7 +185,9 @@ public abstract class MageTestBase {
|
|||
try {
|
||||
while (scanner.hasNextLine()) {
|
||||
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")) {
|
||||
includeFrom(line);
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -1237,4 +1237,10 @@ public class PlayerStub implements Player {
|
|||
public boolean addTargets(Ability ability, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHistory() {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<groupId>org.mage</groupId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage</artifactId>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public enum CardRepository {
|
|||
// raise this if db structure was changed
|
||||
private static final long CARD_DB_VERSION = 43;
|
||||
// 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 Dao<CardInfo, Object> cardDao;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@
|
|||
* 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.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -38,7 +37,6 @@ import mage.players.Player;
|
|||
public class Seat implements Serializable {
|
||||
|
||||
// private static final Logger logger = Logger.getLogger(Seat.class);
|
||||
|
||||
private String playerType;
|
||||
private Player player;
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ public class GameEvent implements Serializable {
|
|||
DRAW_CARD, DREW_CARD,
|
||||
MIRACLE_CARD_REVEALED,
|
||||
MADNESS_CARD_EXILED,
|
||||
DISCARD_CARD,
|
||||
DISCARDED_CARD,
|
||||
CYCLE_CARD, CYCLED_CARD,
|
||||
CLASH, CLASHED,
|
||||
|
|
|
|||
|
|
@ -824,4 +824,6 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
* @return
|
||||
*/
|
||||
boolean addTargets(Ability ability, Game game);
|
||||
|
||||
String getHistory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,14 @@ import mage.constants.ManaType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
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.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
|
|
@ -516,31 +524,29 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
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 {
|
||||
if ((range.getRange() * 2) + 1 >= game.getPlayers().size()) {
|
||||
for (Player player : game.getPlayers().values()) {
|
||||
if (!player.hasLeft()) {
|
||||
inRange.add(player.getId());
|
||||
}
|
||||
inRange.add(playerId);
|
||||
PlayerList players = game.getState().getPlayerList(playerId);
|
||||
for (int i = 0; i < range.getRange(); i++) {
|
||||
Player player = players.getNext(game);
|
||||
while (player.hasLeft()) {
|
||||
player = players.getNext(game);
|
||||
}
|
||||
} else {
|
||||
inRange.add(playerId);
|
||||
PlayerList players = game.getState().getPlayerList(playerId);
|
||||
for (int i = 0; i < range.getRange(); i++) {
|
||||
Player player = players.getNext(game);
|
||||
while (player.hasLeft()) {
|
||||
player = players.getNext(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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -760,7 +766,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
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").
|
||||
*/
|
||||
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
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(getLogName() + " discards " + card.getLogName());
|
||||
|
|
@ -2089,7 +2096,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
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))) {
|
||||
logger.debug("player won -> start: " + this.getName());
|
||||
if (!this.loses) {
|
||||
|
|
@ -2169,10 +2177,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (blocker != null && group != null && group.canBlock(blocker, game)) {
|
||||
group.addBlocker(blockerId, playerId, game);
|
||||
game.getCombat().addBlockingGroup(blockerId, attackerId, playerId, game);
|
||||
} else {
|
||||
if (this.isHuman() && !game.isSimulation()) {
|
||||
game.informPlayer(this, "You can't block this creature.");
|
||||
}
|
||||
} else if (this.isHuman() && !game.isSimulation()) {
|
||||
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) {
|
||||
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 {
|
||||
if (option.getChoices().size() > 0) {
|
||||
addChoiceOptions(options, newOption, 0, game);
|
||||
} else if (option.getCosts().getTargets().size() > 0) {
|
||||
addCostTargetOptions(options, newOption, 0, game);
|
||||
} else {
|
||||
options.add(newOption);
|
||||
}
|
||||
options.add(newOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2811,12 +2815,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
newOption.getChoices().get(choiceNum).setChoice(choice);
|
||||
if (choiceNum < option.getChoices().size() - 1) {
|
||||
addChoiceOptions(options, newOption, choiceNum + 1, game);
|
||||
} else if (option.getCosts().getTargets().size() > 0) {
|
||||
addCostTargetOptions(options, newOption, 0, game);
|
||||
} else {
|
||||
if (option.getCosts().getTargets().size() > 0) {
|
||||
addCostTargetOptions(options, newOption, 0, game);
|
||||
} else {
|
||||
options.add(newOption);
|
||||
}
|
||||
options.add(newOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3503,4 +3505,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHistory() {
|
||||
return "no available";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ public class UserData implements Serializable {
|
|||
protected boolean passPriorityActivation;
|
||||
protected boolean autoOrderTrigger;
|
||||
|
||||
protected String history;
|
||||
|
||||
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
|
||||
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
|
||||
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted,
|
||||
|
|
@ -40,6 +42,7 @@ public class UserData implements Serializable {
|
|||
this.passPriorityCast = passPriorityCast;
|
||||
this.passPriorityActivation = passPriorityActivation;
|
||||
this.autoOrderTrigger = autoOrderTrigger;
|
||||
this.history = "";
|
||||
}
|
||||
|
||||
public void update(UserData userData) {
|
||||
|
|
@ -166,7 +169,16 @@ public class UserData implements Serializable {
|
|||
this.autoOrderTrigger = autoOrderTrigger;
|
||||
}
|
||||
|
||||
public void setHistory(String history) {
|
||||
this.history = history;
|
||||
}
|
||||
|
||||
public String getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public static String getDefaultFlagName() {
|
||||
return "world.png";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ git log 2ad15bbd48d5ae34b0cb5d709895d406b977d104..head --diff-filter=A --name-st
|
|||
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
|
||||
|
||||
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
|
||||
4. Run script:
|
||||
> 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>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.7</version>
|
||||
<version>1.4.8</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Mage Root</name>
|
||||
<description>Mage Root POM</description>
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
</repositories>
|
||||
|
||||
<properties>
|
||||
<mage-version>1.4.7</mage-version>
|
||||
<mage-version>1.4.8</mage-version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue