Some changes to userData handling. Added country flag to some dialogs. Saved and restored some more table columns width and order information.

This commit is contained in:
LevelX2 2015-06-28 00:10:38 +02:00
parent cb3b5f895b
commit 87f3978589
32 changed files with 1982 additions and 1699 deletions

View file

@ -1,36 +1,33 @@
/*
* 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.
*/
* 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.cards.decks;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
@ -61,7 +58,7 @@ public class Deck implements Serializable {
Deck deck = new Deck();
deck.setName(deckCardLists.getName());
List<String> deckCardNames = new ArrayList<>();
for (DeckCardInfo deckCardInfo: deckCardLists.getCards()) {
for (DeckCardInfo deckCardInfo : deckCardLists.getCards()) {
Card card = createCard(deckCardInfo, mockCards);
if (card != null) {
deck.cards.add(card);
@ -71,7 +68,7 @@ public class Deck implements Serializable {
}
}
List<String> sbCardNames = new ArrayList<>();
for (DeckCardInfo deckCardInfo: deckCardLists.getSideboard()) {
for (DeckCardInfo deckCardInfo : deckCardLists.getSideboard()) {
Card card = createCard(deckCardInfo, mockCards);
if (card != null) {
deck.sideboard.add(card);
@ -97,9 +94,9 @@ public class Deck implements Serializable {
}
private static GameException createCardNotFoundGameException(DeckCardInfo deckCardInfo, String deckName) {
return new GameException("Card not found - " + deckCardInfo.getCardName() + " - " + deckCardInfo.getSetCode() + " for deck - " + deckName + "\n" +
"Possible reason is, that you use cards in your deck, that are only supported in newer versions of the server.\n" +
"So it can help to use the same card from another set, that's already supported from this server." );
return new GameException("Card not found - " + deckCardInfo.getCardName() + " - " + deckCardInfo.getSetCode() + " for deck - " + deckName + "\n"
+ "Possible reason is, that you use cards in your deck, that are only supported in newer versions of the server.\n"
+ "So it can help to use the same card from another set, that's already supported from this server.");
}
private static Card createCard(DeckCardInfo deckCardInfo, boolean mockCards) {
@ -119,11 +116,11 @@ public class Deck implements Serializable {
DeckCardLists deckCardLists = new DeckCardLists();
deckCardLists.setName(name);
for (Card card: cards) {
for (Card card : cards) {
deckCardLists.getCards().add(new DeckCardInfo(card.getName(), card.getCardNumber(), card.getExpansionSetCode()));
}
for (Card card: sideboard) {
for (Card card : sideboard) {
deckCardLists.getSideboard().add(new DeckCardInfo(card.getName(), card.getCardNumber(), card.getExpansionSetCode()));
}

View file

@ -1,31 +1,30 @@
/*
* 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.
*/
* 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.players;
import java.io.Serializable;
@ -35,7 +34,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageItem;
import mage.MageObject;
import mage.abilities.Abilities;
@ -84,104 +82,170 @@ import mage.util.Copyable;
public interface Player extends MageItem, Copyable<Player> {
boolean isHuman();
String getName();
String getLogName();
RangeOfInfluence getRange();
Library getLibrary();
Cards getSideboard();
Graveyard getGraveyard();
Abilities<Ability> getAbilities();
void addAbility(Ability ability);
Counters getCounters();
int getLife();
void initLife(int life);
void setLife(int life, Game game);
int loseLife(int amount, Game game);
int gainLife(int amount, Game game);
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable);
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects);
// to handle rule changing effects (613.10)
boolean isCanLoseLife();
void setCanLoseLife(boolean canLoseLife);
void setCanLoseLife(boolean canLoseLife);
void setCanGainLife(boolean canGainLife);
boolean isCanGainLife();
void setCanPayLifeCost(boolean canPayLifeCost);
boolean canPayLifeCost();
void setCanPaySacrificeCost(boolean canPaySacrificeCost);
void setCanPaySacrificeCost(boolean canPaySacrificeCost);
boolean canPaySacrificeCost();
void setLifeTotalCanChange(boolean lifeTotalCanChange);
boolean isLifeTotalCanChange();
boolean isLifeTotalCanChange();
void setLoseByZeroOrLessLife(boolean loseByZeroOrLessLife);
boolean canLoseByZeroOrLessLife();
void setPlayCardsFromGraveyard(boolean playCardsFromGraveyard);
boolean canPlayCardsFromGraveyard();
/**
* Returns alternative casting costs a player can cast spells for
*
* @return
*
* @return
*/
List<AlternativeSourceCosts> getAlternativeSourceCosts();
Cards getHand();
int getLandsPlayed();
int getLandsPerTurn();
void setLandsPerTurn(int landsPerTurn);
int getLoyaltyUsePerTurn();
void setLoyaltyUsePerTurn(int loyaltyUsePerTurn);
int getMaxHandSize();
void setMaxHandSize(int maxHandSize);
int getMaxAttackedBy();
void setMaxAttackedBy(int maxAttackedBy);
boolean isPassed();
boolean isEmptyDraw();
void pass(Game game);
void resetPassed();
boolean getPassedTurn();
boolean getPassedUntilEndOfTurn();
boolean getPassedUntilNextMain();
boolean getPassedUntilStackResolved();
boolean getPassedAllTurns();
boolean hasLost();
boolean hasWon();
boolean hasQuit();
void quit(Game game);
boolean hasTimerTimeout();
void timerTimeout(Game game);
boolean hasIdleTimeout();
void idleTimeout(Game game);
boolean hasLeft();
/**
* Player is still active in game (has not left, lost or won the game).
*
* @return
*/
boolean isInGame();
/**
* Called if other player left the game
*
* @param game
*/
void otherPlayerLeftGame(Game game);
ManaPool getManaPool();
Set<UUID> getInRange();
boolean isTopCardRevealed();
void setTopCardRevealed(boolean topCardRevealed);
/**
* Get data from the client Preferences (e.g. avatarId or showAbilityPickerForce)
* @return
* Get data from the client Preferences (e.g. avatarId or
* showAbilityPickerForce)
*
* @return
*/
UserData getUserData();
void setUserData(UserData userData);
boolean canLose(Game game);
boolean autoLoseGame();
/**
* Returns a set of players which turns under you control.
* Doesn't include yourself.
* Returns a set of players which turns under you control. Doesn't include
* yourself.
*
* @return
*/
@ -189,6 +253,7 @@ public interface Player extends MageItem, Copyable<Player> {
/**
* Defines player whose turn this player controls at the moment.
*
* @param game
* @param playerId
*/
@ -211,7 +276,8 @@ public interface Player extends MageItem, Copyable<Player> {
/**
* Returns false in case player don't control the game.
*
* Note: For effects like "You control target player during that player's next turn".
* Note: For effects like "You control target player during that player's
* next turn".
*
* @return
*/
@ -220,103 +286,165 @@ public interface Player extends MageItem, Copyable<Player> {
/**
* Returns false in case you don't control the game.
*
* Note: For effects like "You control target player during that player's next turn".
* Note: For effects like "You control target player during that player's
* next turn".
*
* @param value
*/
void setGameUnderYourControl(boolean value);
boolean isTestMode();
void setTestMode(boolean value);
void addAction(String action);
int getActionCount();
void setAllowBadMoves(boolean allowBadMoves);
void init(Game game);
void init(Game game, boolean testMode);
void useDeck(Deck deck, Game game);
/**
* Called before each applyEffects, to rest all what can be applyed by continuous effects
* Called before each applyEffects, to rest all what can be applyed by
* continuous effects
*/
void reset();
void shuffleLibrary(Game game);
int drawCards(int num, Game game);
int drawCards(int num, Game game, ArrayList<UUID> appliedEffects);
boolean cast(SpellAbility ability, Game game, boolean noMana);
SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana);
boolean putInHand(Card card, Game game);
boolean removeFromHand(Card card, Game game);
boolean removeFromBattlefield(Permanent permanent, Game game);
boolean putInGraveyard(Card card, Game game, boolean fromBattlefield);
boolean removeFromGraveyard(Card card, Game game);
boolean removeFromLibrary(Card card, Game game);
boolean searchLibrary(TargetCardInLibrary target, Game game);
/**
*
* @param target
* @param game
* @param targetPlayerId player whose library will be searched
* @return true if search was successful
*/
*
* @param target
* @param game
* @param targetPlayerId player whose library will be searched
* @return true if search was successful
*/
boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId);
boolean canPlayLand();
boolean playLand(Card card, Game game);
boolean activateAbility(ActivatedAbility ability, Game game);
boolean triggerAbility(TriggeredAbility ability, Game game);
boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game);
boolean hasProtectionFrom(MageObject source, Game game);
boolean flipCoin(Game game);
boolean flipCoin(Game game, ArrayList<UUID> appliedEffects);
@Deprecated
void discard(int amount, Ability source, Game game);
Card discardOne(boolean random, Ability source, Game game);
Cards discard(int amount, boolean random, Ability source, Game game);
void discardToMax(Game game);
boolean discard(Card card, Ability source, Game game);
void lost(Game game);
void lostForced(Game game);
void won(Game game);
void leave();
void concede(Game game);
void abort();
void abortReset();
void skip();
// priority, undo, ...
void sendPlayerAction(PlayerAction passPriorityAction, Game game);
int getStoredBookmark();
void setStoredBookmark(int bookmark);
void resetStoredBookmark(Game game);
void revealCards(String name, Cards cards, Game game);
void revealCards(String name, Cards cards, Game game, boolean postToLog);
void lookAtCards(String name, Card card, Game game);
void lookAtCards(String name, Cards cards, Game game);
@Override
Player copy();
void restore(Player player);
void setResponseString(String responseString);
void setResponseUUID(UUID responseUUID);
void setResponseBoolean(Boolean responseBoolean);
void setResponseInteger(Integer data);
void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType);
boolean priority(Game game);
boolean choose(Outcome outcome, Target target, UUID sourceId, Game game);
boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options);
boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game);
boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game);
boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game);
boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game);
boolean chooseMulligan(Game game);
boolean chooseUse(Outcome outcome, String message, Game game);
boolean choose(Outcome outcome, Choice choice, Game game);
boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game);
boolean playMana(ManaCost unpaid, String promptText, Game game);
/**
@ -348,13 +476,20 @@ public interface Player extends MageItem, Copyable<Player> {
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
int chooseReplacementEffect(Map<String, String> abilityMap, Game game);
TriggeredAbility chooseTriggeredAbility(List<TriggeredAbility> abilities, Game game);
Mode chooseMode(Modes modes, Ability source, Game game);
void selectAttackers(Game game, UUID attackingPlayerId);
void selectBlockers(Game game, UUID defendingPlayerId);
UUID chooseAttackerOrder(List<Permanent> attacker, Game game);
/**
* Choose the order in which blockers get damage assigned to
*
* @param blockers list of blockers where to choose the next one from
* @param combatGroup the concerning combat group
* @param blockerOrder the already set order of blockers
@ -362,35 +497,52 @@ public interface Player extends MageItem, Copyable<Player> {
* @return blocker next to add to the blocker order
*/
UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game);
void assignDamage(int damage, List<UUID> targets, String singleTargetName, UUID sourceId, Game game);
int getAmount(int min, int max, String message, Game game);
void sideboard(Match match, Deck deck);
void construct(Tournament tournament, Deck deck);
void pickCard(List<Card> cards, Deck deck, Draft draft);
void declareAttacker(UUID attackerId, UUID defenderId, Game game, boolean allowUndo);
void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game);
List<Permanent> getAvailableAttackers(Game game);
List<Permanent> getAvailableAttackers(UUID defenderId, Game game);
List<Permanent> getAvailableBlockers(Game game);
void beginTurn(Game game);
void endOfTurn(Game game);
void phasing(Game game);
void untap(Game game);
ManaOptions getManaAvailable(Game game);
List<Ability> getPlayable(Game game, boolean hidden);
List<Ability> getPlayableOptions(Ability ability, Game game);
Set<UUID> getPlayableInHand(Game game);
LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game);
void addCounters(Counter counter, Game game);
List<UUID> getAttachments();
boolean addAttachment(UUID permanentId, Game game);
boolean removeAttachment(Permanent permanent, Game game);
boolean removeAttachment(Permanent permanent, Game game);
/**
* Signals that the player becomes active player in this turn.
@ -422,10 +574,13 @@ public interface Player extends MageItem, Copyable<Player> {
int getPriorityTimeLeft();
void setReachedNextTurnAfterLeaving(boolean reachedNextTurnAfterLeaving);
boolean hasReachedNextTurnAfterLeaving();
/**
* Checks if a AI player is able to join a table
* i.e. Draft - bot can not enter a table with constructed format
* Checks if a AI player is able to join a table i.e. Draft - bot can not
* enter a table with constructed format
*
* @param table
* @return
*/
@ -433,34 +588,38 @@ public interface Player extends MageItem, Copyable<Player> {
/**
* Set the commanderId of the player
*
* @param commanderId
*/
void setCommanderId(UUID commanderId);
/**
* Get the commanderId of the player
* @return
*
* @return
*/
UUID getCommanderId();
/**
* Moves cards from one zone to another
*
* Moves cards from one zone to another
*
* @param cards
* @param fromZone
* @param toZone
* @param source
* @param game
* @return
* @return
*/
boolean moveCards(Cards cards, Zone fromZone, Zone toZone, Ability source, Game game);
boolean moveCards(List<Card> cards, Zone fromZone, Zone toZone, Ability source, Game game);
boolean moveCards(Card card, Zone fromZone, Zone toZone, Ability source, Game game);
/**
* Uses card.moveToZone and posts a inform message about moving the card
* into the game log
*
*
* @param card
* @param sourceId
* @param game
@ -468,7 +627,7 @@ public interface Player extends MageItem, Copyable<Player> {
* @return
*/
boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game, Zone fromZone);
/**
* @param card
* @param sourceId
@ -476,12 +635,13 @@ public interface Player extends MageItem, Copyable<Player> {
* @param withName show the card name in the log
* @param fromZone
* @return
* */
*
*/
boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean withName);
/**
* Uses card.moveToExile and posts a inform message about moving the card to exile
* into the game log
* Uses card.moveToExile and posts a inform message about moving the card to
* exile into the game log
*
* @param card
* @param exileId exile zone id (optional)
@ -495,8 +655,8 @@ public interface Player extends MageItem, Copyable<Player> {
boolean moveCardToExileWithInfo(Card card, UUID exileId, String exileName, UUID sourceId, Game game, Zone fromZone, boolean withName);
/**
* Uses card.moveToZone and posts a inform message about moving the card to graveyard
* into the game log
* Uses card.moveToZone and posts a inform message about moving the card to
* graveyard into the game log
*
* @param card
* @param sourceId
@ -506,10 +666,8 @@ public interface Player extends MageItem, Copyable<Player> {
*/
boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, Game game, Zone fromZone);
/**
* Internal used to move cards
* Use commonly player.moveCards()
* Internal used to move cards Use commonly player.moveCards()
*
* @param cards
* @param source
@ -520,8 +678,8 @@ public interface Player extends MageItem, Copyable<Player> {
boolean moveCardsToGraveyardWithInfo(List<Card> cards, Ability source, Game game, Zone fromZone);
/**
* Uses card.moveToZone and posts a inform message about moving the card to graveyard
* into the game log
* Uses card.moveToZone and posts a inform message about moving the card to
* graveyard into the game log
*
* @param card
* @param sourceId
@ -533,9 +691,9 @@ public interface Player extends MageItem, Copyable<Player> {
*/
boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop, boolean withName);
/**
* Uses putOntoBattlefield and posts also a info message about in the game log
* Uses putOntoBattlefield and posts also a info message about in the game
* log
*
* @param card
* @param game
@ -544,9 +702,10 @@ public interface Player extends MageItem, Copyable<Player> {
* @return
*/
boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId);
/**
* Uses putOntoBattlefield and posts also a info message about in the game log
* Uses putOntoBattlefield and posts also a info message about in the game
* log
*
* @param card
* @param game
@ -558,7 +717,8 @@ public interface Player extends MageItem, Copyable<Player> {
boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId, boolean tapped);
/**
* Uses putOntoBattlefield and posts also a info message about in the game log
* Uses putOntoBattlefield and posts also a info message about in the game
* log
*
* @param card
* @param game
@ -569,10 +729,10 @@ public interface Player extends MageItem, Copyable<Player> {
* @return
*/
boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId, boolean tapped, boolean facedown);
/**
* Checks if the playerToCheckId is from an opponent in range
*
*
* @param playerToCheckId
* @param game
* @return true if playerToCheckId belongs to an opponent
@ -580,30 +740,38 @@ public interface Player extends MageItem, Copyable<Player> {
boolean hasOpponent(UUID playerToCheckId, Game game);
/**
* Free resources on match end
* Free resources on match end
*/
void cleanUpOnMatchEnd();
/**
* If the next cast spell has the set sourceId, the spell will
* be cast without mana.
* If the next cast spell has the set sourceId, the spell will be cast
* without mana.
*
* @param sourceId the source that can be cast without mana
* @param manaCosts alternate ManaCost, null if it can be cast without mana cost
* @param manaCosts alternate ManaCost, null if it can be cast without mana
* cost
*/
void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts);
UUID getCastSourceIdWithAlternateMana();
ManaCosts getCastSourceIdManaCosts();
// permission handling to show hand cards
void addPermissionToShowHandCards(UUID watcherUserId);
boolean hasUserPermissionToSeeHand(UUID userId);
void revokePermissionToSeeHandCards();
boolean isRequestToShowHandCardsAllowed();
Set<UUID> getUsersAllowedToSeeHandCards();
boolean isInPayManaMode();
void setMatchPlayer(MatchPlayer matchPlayer);
MatchPlayer getMatchPlayer();
}

View file

@ -227,6 +227,8 @@ public abstract class PlayerImpl implements Player, Serializable {
protected UserData userData;
protected MatchPlayer matchPlayer;
protected String flagName;
/**
* During some steps we can't play anything
*/
@ -571,7 +573,9 @@ public abstract class PlayerImpl implements Player, Serializable {
}
/**
* returns true if the player has the control itself - false if the player is controlled by another player
* returns true if the player has the control itself - false if the player
* is controlled by another player
*
* @return
*/
@Override
@ -701,7 +705,7 @@ public abstract class PlayerImpl implements Player, Serializable {
if (random) {
for (int i = 0; i < amount; i++) {
Card card = this.getHand().getRandom(game);
if(card != null) {
if (card != null) {
discardedCards.add(card);
discard(card, source, game);
}
@ -917,7 +921,6 @@ public abstract class PlayerImpl implements Player, Serializable {
return castSourceIdManaCosts;
}
@Override
public boolean isInPayManaMode() {
return payManaMode;
@ -939,7 +942,7 @@ public abstract class PlayerImpl implements Player, Serializable {
// some effects set sourceId to cast without paying mana costs
if (ability.getSourceId().equals(getCastSourceIdWithAlternateMana())) {
ManaCosts alternateCosts = getCastSourceIdManaCosts();
Ability spellAbility = spell.getSpellAbility();
Ability spellAbility = spell.getSpellAbility();
if (alternateCosts == null) {
noMana = true;
} else {
@ -1096,7 +1099,6 @@ public abstract class PlayerImpl implements Player, Serializable {
}
if (ability instanceof PlayLandAbility) {
Card card = game.getCard(ability.getSourceId());
result = playLand(card, game);
} else {
@ -1338,7 +1340,7 @@ public abstract class PlayerImpl implements Player, Serializable {
game.getState().getLookedAt(this.playerId).add(name, card);
game.fireUpdatePlayersEvent();
}
@Override
public void lookAtCards(String name, Cards cards, Game game) {
game.getState().getLookedAt(this.playerId).add(name, cards);
@ -1679,7 +1681,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} else if (source instanceof Card) {
sourceAbilities = ((Card) source).getAbilities(game);
sourceControllerId = ((Card) source).getOwnerId();
} else if (source instanceof CommandObject){
} else if (source instanceof CommandObject) {
sourceControllerId = ((CommandObject) source).getControllerId();
sourceAbilities = ((CommandObject) source).getAbilities();
}
@ -2033,7 +2035,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
Permanent attacker = game.getPermanent(attackerId);
if (attacker != null && attacker.canAttack(defenderId, game) && attacker.getControllerId().equals(playerId)) {
if(!game.getCombat().declareAttacker(attackerId, defenderId, playerId, game)) {
if (!game.getCombat().declareAttacker(attackerId, defenderId, playerId, game)) {
game.undo(playerId);
}
}
@ -2285,64 +2287,64 @@ public abstract class PlayerImpl implements Player, Serializable {
}
protected boolean canPlayCardByAlternateCost(Card sourceObject, ManaOptions available, Ability ability, Game game) {
if (sourceObject != null && !(sourceObject instanceof Permanent)) {
for (Ability alternateSourceCostsAbility : sourceObject.getAbilities()) {
// if cast for noMana no Alternative costs are allowed
if (alternateSourceCostsAbility instanceof AlternativeSourceCosts) {
if (((AlternativeSourceCosts) alternateSourceCostsAbility).isAvailable(ability, game)) {
if (alternateSourceCostsAbility.getCosts().canPay(ability, playerId, playerId, game)) {
ManaCostsImpl manaCosts = new ManaCostsImpl();
for (Cost cost : alternateSourceCostsAbility.getCosts()) {
if (cost instanceof ManaCost) {
manaCosts.add((ManaCost) cost);
}
}
if (sourceObject != null && !(sourceObject instanceof Permanent)) {
for (Ability alternateSourceCostsAbility : sourceObject.getAbilities()) {
// if cast for noMana no Alternative costs are allowed
if (alternateSourceCostsAbility instanceof AlternativeSourceCosts) {
if (((AlternativeSourceCosts) alternateSourceCostsAbility).isAvailable(ability, game)) {
if (alternateSourceCostsAbility.getCosts().canPay(ability, playerId, playerId, game)) {
ManaCostsImpl manaCosts = new ManaCostsImpl();
for (Cost cost : alternateSourceCostsAbility.getCosts()) {
if (cost instanceof ManaCost) {
manaCosts.add((ManaCost) cost);
}
}
if (manaCosts.size() == 0) {
return true;
} else {
for (Mana mana : manaCosts.getOptions()) {
for (Mana avail : available) {
if (mana.enough(avail)) {
return true;
}
}
}
}
}
}
}
}
if (manaCosts.size() == 0) {
return true;
} else {
for (Mana mana : manaCosts.getOptions()) {
for (Mana avail : available) {
if (mana.enough(avail)) {
return true;
}
}
}
}
}
}
}
}
// controller specific alternate spell costs
for (AlternativeSourceCosts alternateSourceCosts: getAlternativeSourceCosts()) {
if (alternateSourceCosts instanceof Ability) {
if (alternateSourceCosts.isAvailable(ability, game)) {
if (((Ability) alternateSourceCosts).getCosts().canPay(ability, playerId, playerId, game)) {
ManaCostsImpl manaCosts = new ManaCostsImpl();
for (Cost cost : ((Ability) alternateSourceCosts).getCosts()) {
if (cost instanceof ManaCost) {
manaCosts.add((ManaCost) cost);
}
}
// controller specific alternate spell costs
for (AlternativeSourceCosts alternateSourceCosts : getAlternativeSourceCosts()) {
if (alternateSourceCosts instanceof Ability) {
if (alternateSourceCosts.isAvailable(ability, game)) {
if (((Ability) alternateSourceCosts).getCosts().canPay(ability, playerId, playerId, game)) {
ManaCostsImpl manaCosts = new ManaCostsImpl();
for (Cost cost : ((Ability) alternateSourceCosts).getCosts()) {
if (cost instanceof ManaCost) {
manaCosts.add((ManaCost) cost);
}
}
if (manaCosts.size() == 0) {
return true;
} else {
for (Mana mana : manaCosts.getOptions()) {
for (Mana avail : available) {
if (mana.enough(avail)) {
return true;
}
}
}
}
}
}
}
}
}
return false;
if (manaCosts.size() == 0) {
return true;
} else {
for (Mana mana : manaCosts.getOptions()) {
for (Mana avail : available) {
if (mana.enough(avail)) {
return true;
}
}
}
}
}
}
}
}
}
return false;
}
protected boolean canLandPlayAlternateSourceCostsAbility(Card sourceObject, ManaOptions available, Ability ability, Game game) {
@ -2847,7 +2849,7 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean moveCards(Cards cards, Zone fromZone, Zone toZone, Ability source, Game game) {
ArrayList<Card> cardList = new ArrayList<>();
for (UUID cardId: cards) {
for (UUID cardId : cards) {
if (fromZone.equals(Zone.BATTLEFIELD)) {
Permanent permanent = game.getPermanent(cardId);
if (permanent != null) {
@ -2857,7 +2859,7 @@ public abstract class PlayerImpl implements Player, Serializable {
Card card = game.getCard(cardId);
if (card != null) {
cardList.add(card);
}
}
}
}
return moveCards(cardList, fromZone, toZone, source, game);
@ -2878,10 +2880,10 @@ public abstract class PlayerImpl implements Player, Serializable {
return true;
}
game.fireEvent(new ZoneChangeGroupEvent(cards, source == null ? null : source.getSourceId(), this.getId(), fromZone, toZone));
switch(toZone) {
switch (toZone) {
case EXILED:
boolean result = false;
for(Card card: cards) {
for (Card card : cards) {
result |= moveCardToExileWithInfo(card, null, "", source == null ? null : source.getSourceId(), game, fromZone, true);
}
return result;
@ -2889,7 +2891,7 @@ public abstract class PlayerImpl implements Player, Serializable {
return moveCardsToGraveyardWithInfo(cards, source, game, fromZone);
case HAND:
result = false;
for(Card card: cards) {
for (Card card : cards) {
result |= moveCardToHandWithInfo(card, source == null ? null : source.getSourceId(), game, fromZone);
}
return result;
@ -2912,7 +2914,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
if (!game.isSimulation()) {
StringBuilder sb = new StringBuilder(this.getLogName()).append(" puts ").append(withName ? card.getLogName() : "a face down card");
switch(fromZone) {
switch (fromZone) {
case EXILED:
sb.append(" from exile zone ");
break;
@ -3051,8 +3053,8 @@ public abstract class PlayerImpl implements Player, Serializable {
if (card instanceof PermanentCard) {
card = game.getCard(card.getId());
}
game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName() : "a card face down") + " " +
(fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + " " : "") + "to the exile zone");
game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName() : "a card face down") + " "
+ (fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + " " : "") + "to the exile zone");
}
result = true;
}
@ -3075,7 +3077,7 @@ public abstract class PlayerImpl implements Player, Serializable {
if (card.putOntoBattlefield(game, fromZone, sourceId, this.getId(), tapped, facedown)) {
if (!game.isSimulation()) {
game.informPlayers(new StringBuilder(this.getLogName())
.append(" puts ").append(facedown ? "a card face down ":card.getLogName())
.append(" puts ").append(facedown ? "a card face down " : card.getLogName())
.append(" from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" ")
.append("onto the Battlefield").toString());
}
@ -3129,7 +3131,6 @@ public abstract class PlayerImpl implements Player, Serializable {
usersAllowedToSeeHandCards.add(watcherUserId);
}
@Override
public boolean isRequestToShowHandCardsAllowed() {
return userData.isAllowRequestShowHandCards();

View file

@ -18,7 +18,7 @@ public class UserData implements Serializable {
protected String flagName;
protected boolean askMoveToGraveOrder;
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced,
boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps,
String flagName, boolean askMoveToGraveOrder) {
this.groupId = userGroup.getGroupId();
@ -31,6 +31,21 @@ public class UserData implements Serializable {
this.askMoveToGraveOrder = askMoveToGraveOrder;
}
public void update(UserData userData) {
this.groupId = userData.groupId;
this.avatarId = userData.avatarId;
this.showAbilityPickerForced = userData.showAbilityPickerForced;
this.allowRequestShowHandCards = userData.allowRequestShowHandCards;
this.userSkipPrioritySteps = userData.userSkipPrioritySteps;
this.confirmEmptyManaPool = userData.confirmEmptyManaPool;
this.flagName = userData.flagName;
this.askMoveToGraveOrder = userData.askMoveToGraveOrder;
}
public static UserData getDefaultUserDataView() {
return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, "world.png", false);
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
@ -90,5 +105,5 @@ public class UserData implements Serializable {
public void setAskMoveToGraveOrder(boolean askMoveToGraveOrder) {
this.askMoveToGraveOrder = askMoveToGraveOrder;
}
}

View file

@ -7,6 +7,7 @@ public enum UserGroup {
COMPUTER(0),
PLAYER(1),
DEFAULT(2),
MAGE(3),
ADMIN(7),
OWNER(15);