This commit is contained in:
Goudt 2017-02-05 13:27:23 +01:00
commit c89eb89c04
27 changed files with 542 additions and 53 deletions

View file

@ -26,7 +26,7 @@
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
/* /*
* ConnectDialog.java * ConnectDialog.java
* *
* Created on 20-Jan-2010, 9:37:07 PM * Created on 20-Jan-2010, 9:37:07 PM
@ -391,6 +391,7 @@ public class ConnectDialog extends MageDialog {
connection.setUsername(this.txtUserName.getText().trim()); connection.setUsername(this.txtUserName.getText().trim());
connection.setPassword(this.txtPassword.getText().trim()); connection.setPassword(this.txtPassword.getText().trim());
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected()); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected());
connection.setUserIdStr(System.getProperty("user.name"));
MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem());
PreferencesDialog.setProxyInformation(connection); PreferencesDialog.setProxyInformation(connection);

View file

@ -3520,6 +3520,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
if (selectedAvatarId == 0) { if (selectedAvatarId == 0) {
getSelectedAvatar(); getSelectedAvatar();
} }
String userStrId = System.getProperty("user.name");
return new UserData(UserGroup.PLAYER, return new UserData(UserGroup.PLAYER,
PreferencesDialog.selectedAvatarId, PreferencesDialog.selectedAvatarId,
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_ABILITY_PICKER_FORCED, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_ABILITY_PICKER_FORCED, "true").equals("true"),
@ -3533,7 +3534,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"),
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"),
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"),
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true") PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
userStrId
); );
} }

View file

@ -62,7 +62,7 @@ public interface MageServer {
boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException; boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException;
boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException; boolean connectUser(String userName, String password, String sessionId, MageVersion version, String userIdStr) throws MageException;
boolean connectAdmin(String password, String sessionId, MageVersion version) throws MageException; boolean connectAdmin(String password, String sessionId, MageVersion version) throws MageException;
@ -72,7 +72,7 @@ public interface MageServer {
List<CardInfo> getMissingCardsData(List<String> classNames); List<CardInfo> getMissingCardsData(List<String> classNames);
// user methods // user methods
boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion) throws MageException; boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException;
void sendFeedbackMessage(String sessionId, String username, String title, String type, String message, String email) throws MageException; void sendFeedbackMessage(String sessionId, String username, String title, String type, String message, String email) throws MageException;

View file

@ -55,6 +55,7 @@ public class Connection {
private String proxyPassword; private String proxyPassword;
private int clientCardDatabaseVersion; private int clientCardDatabaseVersion;
private boolean forceDBComparison; private boolean forceDBComparison;
private String userIdStr;
private UserData userData; private UserData userData;
@ -167,6 +168,14 @@ public class Connection {
this.username = username; this.username = username;
} }
public String getUserIdStr() {
return userIdStr;
}
public void setUserIdStr(String userIdStr) {
this.userIdStr = userIdStr;
}
public String getPassword() { public String getPassword() {
return password; return password;
} }

View file

@ -222,9 +222,9 @@ public class SessionImpl implements Session {
boolean registerResult; boolean registerResult;
if (connection.getAdminPassword() == null) { if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking // for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion()); registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
if (registerResult) { if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString()); server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
} }
} else { } else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion()); registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
@ -1466,7 +1466,7 @@ public class SessionImpl implements Session {
} }
return false; return false;
} }
@Override @Override
public boolean setActivation(String userName, boolean active) { public boolean setActivation(String userName, boolean active) {
try { try {
@ -1571,7 +1571,7 @@ public class SessionImpl implements Session {
public boolean updatePreferencesForServer(UserData userData) { public boolean updatePreferencesForServer(UserData userData) {
try { try {
if (isConnected()) { if (isConnected()) {
server.setUserData(connection.getUsername(), sessionId, userData, null); server.setUserData(connection.getUsername(), sessionId, userData, null, null);
} }
return true; return true;
} catch (MageException ex) { } catch (MageException ex) {

View file

@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 21; public final static int MAGE_VERSION_PATCH = 21;
public final static String MAGE_VERSION_MINOR_PATCH = "V1"; public final static String MAGE_VERSION_MINOR_PATCH = "V2";
public final static String MAGE_VERSION_INFO = ""; public final static String MAGE_VERSION_INFO = "";
private final int major; private final int major;

View file

@ -46,8 +46,9 @@ public class UserView implements Serializable {
private final Date muteChatUntil; private final Date muteChatUntil;
private final String clientVersion; private final String clientVersion;
private final String email; private final String email;
private final String userIdStr;
public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState, Date muteChatUntil, String clientVersion, String email) { public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState, Date muteChatUntil, String clientVersion, String email, String userIdStr) {
this.userName = userName; this.userName = userName;
this.host = host; this.host = host;
this.sessionId = sessionId; this.sessionId = sessionId;
@ -57,6 +58,7 @@ public class UserView implements Serializable {
this.muteChatUntil = muteChatUntil; this.muteChatUntil = muteChatUntil;
this.clientVersion = clientVersion; this.clientVersion = clientVersion;
this.email = email; this.email = email;
this.userIdStr = userIdStr;
} }
public String getUserName() { public String getUserName() {
@ -90,9 +92,12 @@ public class UserView implements Serializable {
public Date getTimeConnected() { public Date getTimeConnected() {
return timeConnected; return timeConnected;
} }
public String getEmail() { public String getEmail() {
return email; return email;
} }
public String getUserIdStr() {
return userIdStr;
}
} }

View file

@ -66,7 +66,7 @@ public class CanadianHighlander extends Constructed {
invalid.put("Deck", "Must contain 100 or more singleton cards: has " + (deck.getCards().size()) + " cards"); invalid.put("Deck", "Must contain 100 or more singleton cards: has " + (deck.getCards().size()) + " cards");
valid = false; valid = false;
} }
if (deck.getSideboard().size() > 0) { if (deck.getSideboard().size() > 0) {
invalid.put("Deck", "Sideboard can't contain any cards: has " + (deck.getSideboard().size()) + " cards"); invalid.put("Deck", "Sideboard can't contain any cards: has " + (deck.getSideboard().size()) + " cards");
valid = false; valid = false;
@ -86,11 +86,11 @@ public class CanadianHighlander extends Constructed {
} }
} }
int allowedPoints = 10 * (int) Math.floor(deck.getCards().size()/100.0); int allowedPoints = 10 * (int) Math.floor(deck.getCards().size() / 100.0);
int totalPoints = 0; int totalPoints = 0;
for (Map.Entry<String, Integer> entry : counts.entrySet()) { for (Map.Entry<String, Integer> entry : counts.entrySet()) {
String cn = entry.getKey(); String cn = entry.getKey();
if(cn.equals("Balance") if (cn.equals("Balance")
|| cn.equals("Dig Through Time") || cn.equals("Dig Through Time")
|| cn.equals("Fastbond") || cn.equals("Fastbond")
|| cn.equals("Gifts Ungiven") || cn.equals("Gifts Ungiven")
@ -108,8 +108,9 @@ public class CanadianHighlander extends Constructed {
|| cn.equals("Treasure Cruise") || cn.equals("Treasure Cruise")
|| cn.equals("True-Name Nemesis")) { || cn.equals("True-Name Nemesis")) {
totalPoints += 1; totalPoints += 1;
invalid.put(entry.getKey(), " 1 point " + cn);
} }
if(cn.equals("Doomsday") if (cn.equals("Doomsday")
|| cn.equals("Enlightened Tutor") || cn.equals("Enlightened Tutor")
|| cn.equals("Imperial Seal") || cn.equals("Imperial Seal")
|| cn.equals("Mana Crypt") || cn.equals("Mana Crypt")
@ -119,8 +120,9 @@ public class CanadianHighlander extends Constructed {
|| cn.equals("Survival of the Fittest") || cn.equals("Survival of the Fittest")
|| cn.equals("Umezawa's Jitte")) { || cn.equals("Umezawa's Jitte")) {
totalPoints += 2; totalPoints += 2;
invalid.put(entry.getKey(), " 2 points " + cn);
} }
if(cn.equals("Birthing Pod") if (cn.equals("Birthing Pod")
|| cn.equals("Mox Emerald") || cn.equals("Mox Emerald")
|| cn.equals("Mox Jet") || cn.equals("Mox Jet")
|| cn.equals("Mox Pearl") || cn.equals("Mox Pearl")
@ -129,27 +131,32 @@ public class CanadianHighlander extends Constructed {
|| cn.equals("Protean Hulk") || cn.equals("Protean Hulk")
|| cn.equals("Vampiric Tutor")) { || cn.equals("Vampiric Tutor")) {
totalPoints += 3; totalPoints += 3;
invalid.put(entry.getKey(), " 3 points " + cn);
} }
if(cn.equals("Demonic Tutor") if (cn.equals("Demonic Tutor")
|| cn.equals("Hermit Druid") || cn.equals("Hermit Druid")
|| cn.equals("Sol Ring")) { || cn.equals("Sol Ring")) {
totalPoints += 4; totalPoints += 4;
invalid.put(entry.getKey(), " 4 points " + cn);
} }
if(cn.equals("Ancestral Recall") if (cn.equals("Ancestral Recall")
|| cn.equals("Natural Order") || cn.equals("Natural Order")
|| cn.equals("Time Walk") || cn.equals("Time Walk")
|| cn.equals("Tinker")) { || cn.equals("Tinker")) {
totalPoints += 5; totalPoints += 5;
invalid.put(entry.getKey(), " 5 points " + cn);
} }
if(cn.equals("Flash")) { if (cn.equals("Flash")) {
totalPoints += 6; totalPoints += 6;
invalid.put(entry.getKey(), " 6 points " + cn);
} }
if(cn.equals("Black Lotus") if (cn.equals("Black Lotus")
|| cn.equals("Time Vault")) { || cn.equals("Time Vault")) {
totalPoints += 7; totalPoints += 7;
invalid.put(entry.getKey(), " 7 points " + cn);
} }
} }
if(totalPoints > allowedPoints) { if (totalPoints > allowedPoints) {
invalid.put("Total points too high", "Your calculated point total was " + totalPoints); invalid.put("Total points too high", "Your calculated point total was " + totalPoints);
valid = false; valid = false;
} }

View file

@ -0,0 +1,50 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.21</version>
</parent>
<artifactId>mage-game-canadianhighlanderduel</artifactId>
<packaging>jar</packaging>
<name>Mage Game Canadian Highlander Two Player</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-game-canadianhighlanderduel</finalName>
</build>
<properties/>
</project>

View file

@ -0,0 +1,60 @@
/*
* 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.game;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.match.MatchType;
public class CanadianHighlanderDuel extends GameCanadianHighlanderImpl {
public CanadianHighlanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
super(attackOption, range, freeMulligans, startLife);
}
public CanadianHighlanderDuel(final CanadianHighlanderDuel game) {
super(game);
}
@Override
public MatchType getGameType() {
return new CanadianHighlanderDuelType();
}
@Override
public int getNumPlayers() {
return 2;
}
@Override
public CanadianHighlanderDuel copy() {
return new CanadianHighlanderDuel(this);
}
}

View 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.game;
import mage.game.match.MatchImpl;
import mage.game.match.MatchOptions;
/**
*
* @author spjspj
*/
public class CanadianHighlanderDuelMatch extends MatchImpl {
public CanadianHighlanderDuelMatch(MatchOptions options) {
super(options);
}
@Override
public void startGame() throws GameException {
int startLife = 20;
CanadianHighlanderDuel game = new CanadianHighlanderDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife);
game.setStartMessage(this.createGameStartMessage());
initGame(game);
games.add(game);
}
}

View file

@ -0,0 +1,57 @@
/*
* 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.game;
import mage.game.match.MatchType;
/**
*
* @author spjspj
*/
public class CanadianHighlanderDuelType extends MatchType {
public CanadianHighlanderDuelType() {
this.name = "Canadian Highlander Two Player Duel";
this.maxPlayers = 2;
this.minPlayers = 2;
this.numTeams = 0;
this.useAttackOption = false;
this.useRange = false;
this.sideboardingAllowed = false;
}
protected CanadianHighlanderDuelType(final CanadianHighlanderDuelType matchType) {
super(matchType);
}
@Override
public CanadianHighlanderDuelType copy() {
return new CanadianHighlanderDuelType(this);
}
}

View file

@ -0,0 +1,5 @@
#Generated by Maven
#Sun Feb 05 18:32:22 AEDT 2017
version=1.4.21
groupId=org.mage
artifactId=mage-game-canadianhighlanderduel

View file

@ -22,6 +22,7 @@
<module>Mage.Game.FreeForAll</module> <module>Mage.Game.FreeForAll</module>
<module>Mage.Game.MomirDuel</module> <module>Mage.Game.MomirDuel</module>
<module>Mage.Game.TinyLeadersDuel</module> <module>Mage.Game.TinyLeadersDuel</module>
<module>Mage.Game.CanadianHighlanderDuel</module>
<module>Mage.Game.TwoPlayerDuel</module> <module>Mage.Game.TwoPlayerDuel</module>
<module>Mage.Player.AI</module> <module>Mage.Player.AI</module>
<module>Mage.Player.AIMinimax</module> <module>Mage.Player.AIMinimax</module>
@ -34,4 +35,4 @@
<module>Mage.Tournament.Sealed</module> <module>Mage.Tournament.Sealed</module>
</modules> </modules>
</project> </project>

View file

@ -72,6 +72,7 @@
<gameType name="Commander Two Player Duel" jar="mage-game-commanderduel.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/> <gameType name="Commander Two Player Duel" jar="mage-game-commanderduel.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/>
<gameType name="Commander Free For All" jar="mage-game-commanderfreeforall.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/> <gameType name="Commander Free For All" jar="mage-game-commanderfreeforall.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/>
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/> <gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
<gameType name="Canadian Highlander Two Player Duel" jar="mage-game-canadianhighlanderduel.jar" className="mage.game.CanadianHighlanderDuelMatch" typeName="mage.game.CanadianHighlanderDuelType"/>
<gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/> <gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/>
</gameTypes> </gameTypes>
<tournamentTypes> <tournamentTypes>
@ -133,10 +134,10 @@
<deckType name="Constructed - Super Type 2" jar="mage-deck-constructed.jar" className="mage.deck.SuperType2"/> <deckType name="Constructed - Super Type 2" jar="mage-deck-constructed.jar" className="mage.deck.SuperType2"/>
<deckType name="Constructed - Freeform" jar="mage-deck-constructed.jar" className="mage.deck.Freeform"/> <deckType name="Constructed - Freeform" jar="mage-deck-constructed.jar" className="mage.deck.Freeform"/>
<deckType name="Constructed - Australian Highlander" jar="mage-deck-constructed.jar" className="mage.deck.AusHighlander"/> <deckType name="Constructed - Australian Highlander" jar="mage-deck-constructed.jar" className="mage.deck.AusHighlander"/>
<deckType name="Constructed - Canadian Highlander" jar="mage-deck-constructed.jar" className="mage.deck.CanadianHighlander"/>
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/> <deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/>
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/> <deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/>
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed.jar" className="mage.deck.TinyLeaders"/> <deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed.jar" className="mage.deck.TinyLeaders"/>
<deckType name="Variant Magic - Canadian Highlander" jar="mage-deck-constructed.jar" className="mage.deck.CanadianHighlander"/>
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed.jar" className="mage.deck.Momir"/> <deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed.jar" className="mage.deck.Momir"/>
<deckType name="Block Constructed - Battle for Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.BattleForZendikarBlock"/> <deckType name="Block Constructed - Battle for Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.BattleForZendikarBlock"/>
<deckType name="Block Constructed - Innistrad" jar="mage-deck-constructed.jar" className="mage.deck.InnistradBlock"/> <deckType name="Block Constructed - Innistrad" jar="mage-deck-constructed.jar" className="mage.deck.InnistradBlock"/>

View file

@ -142,6 +142,12 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-canadianhighlanderduel</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>mage-game-momirduel</artifactId> <artifactId>mage-game-momirduel</artifactId>

View file

@ -132,7 +132,7 @@ public class MageServerImpl implements MageServer {
} }
return true; return true;
} }
@Override @Override
public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException { public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException {
if (!ConfigSettings.getInstance().isAuthenticationActivated()) { if (!ConfigSettings.getInstance().isAuthenticationActivated()) {
@ -158,13 +158,13 @@ public class MageServerImpl implements MageServer {
} }
@Override @Override
public boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException { public boolean connectUser(String userName, String password, String sessionId, MageVersion version, String userIdStr) throws MageException {
try { try {
if (version.compareTo(Main.getVersion()) != 0) { if (version.compareTo(Main.getVersion()) != 0) {
logger.info("MageVersionException: userName=" + userName + ", version=" + version); logger.info("MageVersionException: userName=" + userName + ", version=" + version);
throw new MageVersionException(version, Main.getVersion()); throw new MageVersionException(version, Main.getVersion());
} }
return SessionManager.getInstance().connectUser(sessionId, userName, password); return SessionManager.getInstance().connectUser(sessionId, userName, password, userIdStr);
} catch (MageException ex) { } catch (MageException ex) {
if (ex instanceof MageVersionException) { if (ex instanceof MageVersionException) {
throw (MageVersionException) ex; throw (MageVersionException) ex;
@ -175,11 +175,11 @@ public class MageServerImpl implements MageServer {
} }
@Override @Override
public boolean setUserData(final String userName, final String sessionId, final UserData userData, final String clientVersion) throws MageException { public boolean setUserData(final String userName, final String sessionId, final UserData userData, final String clientVersion, final String userIdStr) throws MageException {
return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() { return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() {
@Override @Override
public Boolean execute() throws MageException { public Boolean execute() throws MageException {
return SessionManager.getInstance().setUserData(userName, sessionId, userData, clientVersion); return SessionManager.getInstance().setUserData(userName, sessionId, userData, clientVersion, userIdStr);
} }
}); });
} }
@ -943,7 +943,8 @@ public class MageServerImpl implements MageServer {
user.getUserState().toString(), user.getUserState().toString(),
user.getChatLockedUntil(), user.getChatLockedUntil(),
user.getClientVersion(), user.getClientVersion(),
user.getEmail() user.getEmail(),
user.getUserIdStr()
)); ));
} }
return users; return users;

View file

@ -264,12 +264,13 @@ public class Session {
this.userId = user.getId(); this.userId = user.getId();
} }
public boolean setUserData(String userName, UserData userData, String clientVersion) { public boolean setUserData(String userName, UserData userData, String clientVersion, String userIdStr) {
User user = UserManager.getInstance().getUserByName(userName); User user = UserManager.getInstance().getUserByName(userName);
if (user != null) { if (user != null) {
if (clientVersion != null) { if (clientVersion != null) {
user.setClientVersion(clientVersion); user.setClientVersion(clientVersion);
} }
user.setUserIdStr(userIdStr);
if (user.getUserData() == null || user.getUserData().getGroupId() == UserGroup.DEFAULT.getGroupId()) { if (user.getUserData() == null || user.getUserData().getGroupId() == UserGroup.DEFAULT.getGroupId()) {
user.setUserData(userData); user.setUserData(userData);
} else { } else {

View file

@ -88,7 +88,7 @@ public class SessionManager {
return true; return true;
} }
public boolean connectUser(String sessionId, String userName, String password) throws MageException { public boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException {
Session session = sessions.get(sessionId); Session session = sessions.get(sessionId);
if (session != null) { if (session != null) {
String returnMessage = session.connectUser(userName, password); String returnMessage = session.connectUser(userName, password);
@ -117,10 +117,10 @@ public class SessionManager {
return false; return false;
} }
public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion) throws MageException { public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException {
Session session = sessions.get(sessionId); Session session = sessions.get(sessionId);
if (session != null) { if (session != null) {
session.setUserData(userName, userData, clientVersion); session.setUserData(userName, userData, clientVersion, userIdStr);
return true; return true;
} }
return false; return false;
@ -217,7 +217,7 @@ public class SessionManager {
if (session != null) { if (session != null) {
return UserManager.getInstance().getUser(sessions.get(sessionId).getUserId()); return UserManager.getInstance().getUser(sessions.get(sessionId).getUserId());
} }
logger.error(String.format("Session %s could not be found",sessionId)); logger.error(String.format("Session %s could not be found", sessionId));
return Optional.empty(); return Optional.empty();
} }

View file

@ -96,6 +96,7 @@ public class User {
private Date lockedUntil; private Date lockedUntil;
private final AuthorizedUser authorizedUser; private final AuthorizedUser authorizedUser;
private String clientVersion; private String clientVersion;
private String userIdStr;
public User(String userName, String host, AuthorizedUser authorizedUser) { public User(String userName, String host, AuthorizedUser authorizedUser) {
this.userId = UUID.randomUUID(); this.userId = UUID.randomUUID();
@ -127,6 +128,7 @@ public class User {
this.tablesToDelete = new ArrayList<>(); this.tablesToDelete = new ArrayList<>();
this.sessionId = ""; this.sessionId = "";
this.clientVersion = ""; this.clientVersion = "";
this.userIdStr = "";
} }
public String getName() { public String getName() {
@ -178,6 +180,14 @@ public class User {
this.clientVersion = clientVersion; this.clientVersion = clientVersion;
} }
public void setUserIdStr(String userIdStr) {
this.userIdStr = userIdStr;
}
public String getUserIdStr() {
return this.userIdStr;
}
public String getClientVersion() { public String getClientVersion() {
return clientVersion; return clientVersion;
} }
@ -199,7 +209,7 @@ public class User {
public void lostConnection() { public void lostConnection() {
// Because watched games don't get restored after reconnection call stop watching // Because watched games don't get restored after reconnection call stop watching
for (Iterator<UUID> iterator = watchedGames.iterator(); iterator.hasNext(); ) { for (Iterator<UUID> iterator = watchedGames.iterator(); iterator.hasNext();) {
UUID gameId = iterator.next(); UUID gameId = iterator.next();
GameManager.getInstance().stopWatching(gameId, userId); GameManager.getInstance().stopWatching(gameId, userId);
iterator.remove(); iterator.remove();
@ -781,7 +791,7 @@ public class User {
} }
return number; return number;
} }
public String getEmail() { public String getEmail() {
if (authorizedUser != null) { if (authorizedUser != null) {
return authorizedUser.email; return authorizedUser.email;

View file

@ -25,19 +25,19 @@
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.cards.t; package mage.cards.t;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.DoubleStrikeAbility;
import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
@ -47,14 +47,18 @@ import mage.filter.common.FilterCreaturePermanent;
*/ */
public class TrueConviction extends CardImpl { public class TrueConviction extends CardImpl {
public TrueConviction (UUID ownerId, CardSetInfo setInfo) { public TrueConviction(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}{W}");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); // Creatures you control have double strike and lifelink.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()));
Effect effect = new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent());
effect.setText(" and lifelink");
ability.addEffect(effect);
this.addAbility(ability);
} }
public TrueConviction (final TrueConviction card) { public TrueConviction(final TrueConviction card) {
super(card); super(card);
} }

View file

@ -7,14 +7,15 @@ package mage.sets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import mage.cards.CardGraphicInfo;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.FrameStyle;
import mage.cards.repository.CardCriteria; import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository; import mage.cards.repository.CardRepository;
import mage.cards.w.Wastes; import mage.cards.w.Wastes;
import mage.constants.SetType;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.cards.CardGraphicInfo; import mage.constants.SetType;
/** /**
* *
@ -218,8 +219,8 @@ public class OathOfTheGatewatch extends ExpansionSet {
cards.add(new SetCardInfo("Wandering Fumarole", 182, Rarity.RARE, mage.cards.w.WanderingFumarole.class)); cards.add(new SetCardInfo("Wandering Fumarole", 182, Rarity.RARE, mage.cards.w.WanderingFumarole.class));
cards.add(new SetCardInfo("Warden of Geometries", 11, Rarity.COMMON, mage.cards.w.WardenOfGeometries.class)); cards.add(new SetCardInfo("Warden of Geometries", 11, Rarity.COMMON, mage.cards.w.WardenOfGeometries.class));
cards.add(new SetCardInfo("Warping Wail", 12, Rarity.UNCOMMON, mage.cards.w.WarpingWail.class)); cards.add(new SetCardInfo("Warping Wail", 12, Rarity.UNCOMMON, mage.cards.w.WarpingWail.class));
cards.add(new SetCardInfo("Wastes", 183, Rarity.COMMON, Wastes.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Wastes", 183, Rarity.COMMON, Wastes.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true)));
cards.add(new SetCardInfo("Wastes", 184, Rarity.COMMON, Wastes.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Wastes", 184, Rarity.COMMON, Wastes.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true)));
cards.add(new SetCardInfo("Weapons Trainer", 160, Rarity.UNCOMMON, mage.cards.w.WeaponsTrainer.class)); cards.add(new SetCardInfo("Weapons Trainer", 160, Rarity.UNCOMMON, mage.cards.w.WeaponsTrainer.class));
cards.add(new SetCardInfo("Witness the End", 82, Rarity.COMMON, mage.cards.w.WitnessTheEnd.class)); cards.add(new SetCardInfo("Witness the End", 82, Rarity.COMMON, mage.cards.w.WitnessTheEnd.class));
cards.add(new SetCardInfo("World Breaker", 126, Rarity.MYTHIC, mage.cards.w.WorldBreaker.class)); cards.add(new SetCardInfo("World Breaker", 126, Rarity.MYTHIC, mage.cards.w.WorldBreaker.class));

View file

@ -47,6 +47,7 @@ public class PlayerLeftGameTest extends CardTestMultiPlayerBase {
@Override @Override
protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException {
// Start Life = 2
Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 2); Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 2);
// Player order: A -> D -> C -> B // Player order: A -> D -> C -> B
playerA = createPlayer(game, playerA, "PlayerA"); playerA = createPlayer(game, playerA, "PlayerA");
@ -197,4 +198,35 @@ public class PlayerLeftGameTest extends CardTestMultiPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1); assertGraveyardCount(playerB, "Silvercoat Lion", 1);
} }
/**
* Situation: I attacked an opponent with some creatures with True
* Conviction in play. There were multiple "deals combat damage to a
* player"-triggers (Edric, Spymaster of Trest, Daxos of Meletis et al),
* then the opponent lost the game during the first strike combat
* damage-step . In the second combat damage step the triggers went on the
* stack again, although there was no player being dealt damage (multiplayer
* game, so the game wasn't over yet). I don't think these abilities should
* trigger again here.
*/
@Test
public void TestPlayerDiesDuringFirstStrikeDamageStep() {
// Creatures you control have double strike and lifelink.
addCard(Zone.BATTLEFIELD, playerD, "True Conviction");
// Whenever a creature deals combat damage to one of your opponents, its controller may draw a card.
addCard(Zone.BATTLEFIELD, playerD, "Edric, Spymaster of Trest");
addCard(Zone.BATTLEFIELD, playerD, "Dross Crocodile", 8); // Creature 5/1
attack(2, playerD, "Dross Crocodile", playerC);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertLife(playerC, -3);
assertLife(playerD, 7);
assertHandCount(playerD, 2); // 1 (normal draw) + 1 from True Convition
assertPermanentCount(playerC, 0);
}
} }

View file

@ -60,7 +60,7 @@ public enum CardRepository {
// raise this if db structure was changed // raise this if db structure was changed
private static final long CARD_DB_VERSION = 50; private static final long CARD_DB_VERSION = 50;
// raise this if new cards were added to the server // raise this if new cards were added to the server
private static final long CARD_CONTENT_VERSION = 69; private static final long CARD_CONTENT_VERSION = 70;
private final TreeSet<String> landTypes = new TreeSet(); private final TreeSet<String> landTypes = new TreeSet();
private Dao<CardInfo, Object> cardDao; private Dao<CardInfo, Object> cardDao;
private Set<String> classNames; private Set<String> classNames;

View file

@ -0,0 +1,179 @@
/*
* 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.game;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.constants.MultiplayerAttackOption;
import mage.constants.PhaseStep;
import mage.constants.RangeOfInfluence;
import mage.game.turn.TurnMod;
import mage.players.Player;
public abstract class GameCanadianHighlanderImpl extends GameImpl {
protected boolean startingPlayerSkipsDraw = true;
protected Map<UUID, String> usedMulligans = new LinkedHashMap<>();
public GameCanadianHighlanderImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
super(attackOption, range, 0, startLife);
}
public GameCanadianHighlanderImpl(final GameCanadianHighlanderImpl game) {
super(game);
}
@Override
protected void init(UUID choosingPlayerId) {
super.init(choosingPlayerId);
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
}
private String getNextMulligan(String mulligan) {
if (mulligan.equals("7")) {
return "6a";
} else if (mulligan.equals("6a")) {
return "6b";
} else if (mulligan.equals("6b")) {
return "5a";
} else if (mulligan.equals("5a")) {
return "5b";
} else if (mulligan.equals("5b")) {
return "4a";
} else if (mulligan.equals("4a")) {
return "4b";
} else if (mulligan.equals("4b")) {
return "3a";
} else if (mulligan.equals("3a")) {
return "3b";
} else if (mulligan.equals("3b")) {
return "2a";
} else if (mulligan.equals("2a")) {
return "2b";
} else if (mulligan.equals("2b")) {
return "1a";
} else if (mulligan.equals("1a")) {
return "1b";
}
return "0";
}
private int getNextMulliganNum(String mulligan) {
if (mulligan.equals("7")) {
return 6;
} else if (mulligan.equals("6a")) {
return 6;
} else if (mulligan.equals("6b")) {
return 5;
} else if (mulligan.equals("5a")) {
return 5;
} else if (mulligan.equals("5b")) {
return 4;
} else if (mulligan.equals("4a")) {
return 4;
} else if (mulligan.equals("4b")) {
return 3;
} else if (mulligan.equals("3a")) {
return 3;
} else if (mulligan.equals("3b")) {
return 2;
} else if (mulligan.equals("2a")) {
return 2;
} else if (mulligan.equals("2b")) {
return 1;
} else if (mulligan.equals("1a")) {
return 1;
}
return 0;
}
@Override
public int mulliganDownTo(UUID playerId) {
Player player = getPlayer(playerId);
int deduction = 1;
int numToMulliganTo = -1;
if (usedMulligans != null) {
String mulliganCode = "7";
if (usedMulligans.containsKey(player.getId())) {
mulliganCode = usedMulligans.get(player.getId());
}
numToMulliganTo = getNextMulliganNum(mulliganCode);
}
if (numToMulliganTo == -1) {
return player.getHand().size() - deduction;
}
return numToMulliganTo;
}
@Override
public void mulligan(UUID playerId) {
Player player = getPlayer(playerId);
int numCards = player.getHand().size();
int numToMulliganTo = numCards;
player.getLibrary().addAll(player.getHand().getCards(this), this);
player.getHand().clear();
player.shuffleLibrary(null, this);
if (usedMulligans != null) {
String mulliganCode = "7";
if (usedMulligans.containsKey(player.getId())) {
mulliganCode = usedMulligans.get(player.getId());
}
numToMulliganTo = getNextMulliganNum(mulliganCode);
usedMulligans.put(player.getId(), getNextMulligan(mulliganCode));
}
fireInformEvent(new StringBuilder(player.getLogName())
.append(" mulligans to ")
.append(Integer.toString(numToMulliganTo))
.append(numToMulliganTo == 1 ? " card" : " cards").toString());
player.drawCards(numToMulliganTo, this);
}
@Override
public void endMulligan(UUID playerId) {
super.endMulligan(playerId);
}
@Override
public Set<UUID> getOpponents(UUID playerId) {
Set<UUID> opponents = new HashSet<>();
for (UUID opponentId : getState().getPlayersInRange(playerId, this)) {
if (!opponentId.equals(playerId)) {
opponents.add(opponentId);
}
}
return opponents;
}
@Override
public boolean isOpponent(Player player, UUID playerToCheck) {
return !player.getId().equals(playerToCheck);
}
}

View file

@ -399,7 +399,9 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
} }
} else { } else {
Player defender = game.getPlayer(defenderId); Player defender = game.getPlayer(defenderId);
defender.damage(amount, attacker.getId(), game, true, true); if (defender.isInGame()) {
defender.damage(amount, attacker.getId(), game, true, true);
}
} }
} }

View file

@ -23,6 +23,7 @@ public class UserData implements Serializable {
protected boolean passPriorityActivation; protected boolean passPriorityActivation;
protected boolean autoOrderTrigger; protected boolean autoOrderTrigger;
protected boolean useFirstManaAbility = false; protected boolean useFirstManaAbility = false;
private String userIdStr;
protected String matchHistory; protected String matchHistory;
protected int matchQuitRatio; protected int matchQuitRatio;
@ -36,7 +37,7 @@ public class UserData implements Serializable {
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted,
boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility) { boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility, String userIdStr) {
this.groupId = userGroup.getGroupId(); this.groupId = userGroup.getGroupId();
this.avatarId = avatarId; this.avatarId = avatarId;
this.showAbilityPickerForced = showAbilityPickerForced; this.showAbilityPickerForced = showAbilityPickerForced;
@ -55,6 +56,7 @@ public class UserData implements Serializable {
this.matchQuitRatio = 0; this.matchQuitRatio = 0;
this.tourneyHistory = ""; this.tourneyHistory = "";
this.tourneyQuitRatio = 0; this.tourneyQuitRatio = 0;
this.userIdStr = userIdStr;
} }
public void update(UserData userData) { public void update(UserData userData) {
@ -72,11 +74,12 @@ public class UserData implements Serializable {
this.passPriorityActivation = userData.passPriorityActivation; this.passPriorityActivation = userData.passPriorityActivation;
this.autoOrderTrigger = userData.autoOrderTrigger; this.autoOrderTrigger = userData.autoOrderTrigger;
this.useFirstManaAbility = userData.useFirstManaAbility; this.useFirstManaAbility = userData.useFirstManaAbility;
this.userIdStr = userData.userIdStr;
// todo: why we don't copy user stats here? // todo: why we don't copy user stats here?
} }
public static UserData getDefaultUserDataView() { public static UserData getDefaultUserDataView() {
return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false, false); return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false, false, "");
} }
public void setGroupId(int groupId) { public void setGroupId(int groupId) {