Add documentation to Cards and CardsImpl (#9019)

* Added minor documentation and TODO questions

* Fixed typo

* Address one set of comments

* merge fix

* remove commented code

---------

Co-authored-by: xenohedron <xenohedron@users.noreply.github.com>
This commit is contained in:
Alex Vasile 2023-07-02 18:20:28 -04:00 committed by GitHub
parent af2d336045
commit 6b5d4abb69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 124 additions and 112 deletions

View file

@ -88,7 +88,7 @@ public class ExileFromGraveCost extends CostImpl {
exiledCards.add(card);
}
Cards cardsToExile = new CardsImpl();
cardsToExile.addAll(exiledCards);
cardsToExile.addAllCards(exiledCards);
controller.moveCardsToExile(
cardsToExile.getCards(game), source, game, true,
CardUtil.getExileZoneId(game, source),

View file

@ -63,7 +63,7 @@ public class ExileFromHandCost extends CostImpl {
this.cards.add(card);
}
Cards cardsToExile = new CardsImpl();
cardsToExile.addAll(cards);
cardsToExile.addAllCards(cards);
player.moveCards(cardsToExile, Zone.EXILED, ability, game);
paid = true;
if (setXFromCMC) {

View file

@ -47,7 +47,7 @@ public class ExileCardsFromTopOfLibraryTargetEffect extends OneShotEffect {
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
if (targetPlayer != null) {
Cards cards = new CardsImpl();
cards.addAll(targetPlayer.getLibrary().getTopCards(game, amount));
cards.addAllCards(targetPlayer.getLibrary().getTopCards(game, amount));
return targetPlayer.moveCards(cards, Zone.EXILED, source, game);
}
return false;

View file

@ -63,7 +63,7 @@ public class ExileGraveyardAllPlayersEffect extends OneShotEffect {
}
Player player = game.getPlayer(playerId);
if (player != null) {
toExile.addAll(player.getGraveyard().getCards(filter, source.getControllerId(), source, game));
toExile.addAllCards(player.getGraveyard().getCards(filter, source.getControllerId(), source, game));
}
}
controller.moveCards(toExile, Zone.EXILED, source, game);

View file

@ -70,7 +70,7 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect {
MageObject sourceObject = game.getObject(source);
if (player != null && targetPlayer != null && sourceObject != null) {
Cards cards = new CardsImpl();
cards.addAll(targetPlayer.getLibrary().getTopCards(game, amount));
cards.addAllCards(targetPlayer.getLibrary().getTopCards(game, amount));
player.lookAtCards(sourceObject.getIdName(), cards, game);
if (putToGraveyard) {
for (Card card : cards.getCards(game)) {

View file

@ -128,7 +128,7 @@ public class RevealAndSeparatePilesEffect extends OneShotEffect {
game.informPlayers("Pile 1, going to " + pile1Zone + ": " + (pile1.isEmpty() ? " (none)" : pile1.stream().map(MageObject::getName).collect(Collectors.joining(", "))));
cards.clear();
cards.addAll(pile1);
cards.addAllCards(pile1);
if (pile1Zone == Zone.LIBRARY) {
controller.putCardsOnBottomOfLibrary(cards, game, source, anyOrder);
} else {
@ -137,7 +137,7 @@ public class RevealAndSeparatePilesEffect extends OneShotEffect {
game.informPlayers("Pile 2, going to " + pile2Zone + ": " + (pile2.isEmpty() ? " (none)" : pile2.stream().map(MageObject::getName).collect(Collectors.joining(", "))));
cards.clear();
cards.addAll(pile2);
cards.addAllCards(pile2);
if (pile2Zone == Zone.LIBRARY) {
controller.putCardsOnBottomOfLibrary(cards, game, source, anyOrder);
} else {

View file

@ -66,7 +66,7 @@ public class RevealLibraryPutIntoHandEffect extends OneShotEffect {
}
CardsImpl cards = new CardsImpl();
cards.addAll(controller.getLibrary().getTopCards(game, amountCards.calculate(game, source, this)));
cards.addAllCards(controller.getLibrary().getTopCards(game, amountCards.calculate(game, source, this)));
controller.revealCards(sourceObject.getIdName(), cards, game);
Set<Card> cardsList = cards.getCards(game);

View file

@ -2,7 +2,6 @@
package mage.abilities.effects.common.search;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Cards;
import mage.cards.CardsImpl;
@ -84,7 +83,7 @@ public abstract class SearchTargetGraveyardHandLibraryForCardNameAndExileEffect
// cards in Library
Cards cardsInLibrary = new CardsImpl();
cardsInLibrary.addAll(targetPlayer.getLibrary().getCards(game));
cardsInLibrary.addAllCards(targetPlayer.getLibrary().getCards(game));
cardsCount = (cardName.isEmpty() ? 0 : cardsInLibrary.count(filter, game));
filter.setMessage("card named " + cardName + " in the library of " + targetPlayer.getLogName());
TargetCardInLibrary targetLib = new TargetCardInLibrary(0, cardsCount, filter);

View file

@ -90,7 +90,7 @@ class RippleEffect extends OneShotEffect {
}
// reveal top cards from library
Cards cards = new CardsImpl();
cards.addAll(player.getLibrary().getTopCards(game, rippleNumber));
cards.addAllCards(player.getLibrary().getTopCards(game, rippleNumber));
player.revealCards(sourceObject.getIdName(), cards, game);
// determine which card should be rippled

View file

@ -13,17 +13,32 @@ import java.util.UUID;
public interface Cards extends Set<UUID>, Serializable {
/**
* Add the passed in card to the set if it's not null.
*
* @param card the card to add
*/
void add(Card card);
/**
* Get the Card corresponding to the UUID passed IF it is in the set.
* Returns null if the card is not in the set
*
* @param cardId UUID of the card to get
* @param game the current game
* @return The Card corresponding to the UUID, or null if that UUID is not in the set
*/
Card get(UUID cardId, Game game);
/**
* Remove a specific card from the set in a safe manner.
*
* @param card the card to remove from this set
* @return boolean indicating if removing the card was done successfully
*/
boolean remove(Card card);
void setOwner(UUID ownerId, Game game);
void addAll(List<? extends Card> createCards);
void addAll(Set<? extends Card> createCards);
void addAllCards(Collection<? extends Card> createCards);
Set<Card> getCards(Game game);
@ -33,6 +48,12 @@ public interface Cards extends Set<UUID>, Serializable {
String getValue(Game game);
/**
* Get a collection view of the unique non-null cards in this set.
*
* @param game The current game
* @return Collection of unique non-null cards.
*/
Collection<Card> getUniqueCards(Game game);
Card getRandom(Game game);
@ -45,7 +66,19 @@ public interface Cards extends Set<UUID>, Serializable {
Cards copy();
/**
* Remove all cards except those in the provided zone.
*
* @param zone cards from this zone will be kept.
* @param game the ongoing game.
*/
void retainZone(Zone zone, Game game);
/**
* Remove all cards which are in the provided zone.
*
* @param zone cards from this zone will be removed.
* @param game The ongoing game.
*/
void removeZone(Zone zone, Game game);
}

View file

@ -32,11 +32,11 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
}
public CardsImpl(List<? extends Card> cards) {
this.addAll(cards);
this.addAllCards(cards);
}
public CardsImpl(Set<? extends Card> cards) {
this.addAll(cards);
this.addAllCards(cards);
}
public CardsImpl(Collection<UUID> cardIds) {
@ -79,24 +79,20 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
return this.remove(card.getId());
}
@Override
public void setOwner(UUID ownerId, Game game) {
this.ownerId = ownerId;
for (UUID card : this) {
game.getCard(card).setOwnerId(ownerId);
}
}
@Override
public Card getRandom(Game game) {
if (this.isEmpty()) {
return null;
}
MageObject object = game.getObject(RandomUtil.randomFromCollection(this)); // neccessary if permanent tokens are in the collection
if (object instanceof Card) {
return (Card) object;
}
return null;
// neccessary if permanent tokens are in the collection
Set<MageObject> cardsForRandomPick = this
.stream().map(uuid -> game.getObject(uuid))
.filter(Objects::nonNull)
.filter(mageObject -> mageObject instanceof Card)
.collect(Collectors.toSet());
return (Card) RandomUtil.randomFromCollection(cardsForRandomPick);
}
@Override
@ -134,9 +130,14 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
return cards;
}
// TODO: Why is this used a completely different implementation than the version without the filter?
@Override
public Set<Card> getCards(FilterCard filter, Game game) {
return stream().map(game::getCard).filter(Objects::nonNull).filter(card -> filter.match(card, game)).collect(Collectors.toSet());
return stream()
.map(game::getCard)
.filter(Objects::nonNull)
.filter(card -> filter.match(card, game))
.collect(Collectors.toSet());
}
@Override
@ -176,17 +177,7 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
}
@Override
public void addAll(List<? extends Card> cards) {
if (cards != null) {
cards.stream()
.filter(Objects::nonNull)
.map(MageItem::getId)
.forEach(this::add);
}
}
@Override
public void addAll(Set<? extends Card> cards) {
public void addAllCards(Collection<? extends Card> cards) {
if (cards != null) {
cards.stream()
.filter(Objects::nonNull)
@ -197,13 +188,15 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
@Override
public Collection<Card> getUniqueCards(Game game) {
Map<String, Card> cards = new HashMap<>();
Map<String, Card> cards = new HashMap<>(this.size());
for (UUID cardId : this) {
Card card = game.getCard(cardId);
if (card != null) {
cards.putIfAbsent(card.getName(), card);
}
}
return cards.values();
}

View file

@ -477,8 +477,11 @@ public class Combat implements Serializable, Copyable<Combat> {
// if creature is goaded then we start with assumption that it needs to attack any player
mustAttack = true;
// Filter out the planeswalkers
defendersForcedToAttack.addAll(defenders.stream().map(game::getPlayer).filter(Objects::nonNull).map(Player::getId).collect(Collectors.toSet()));
// defendersForcedToAttack.addAll(defenders);
defendersForcedToAttack.addAll(defenders.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.map(Player::getId)
.collect(Collectors.toSet()));
}
if (!mustAttack) {
continue;

View file

@ -94,7 +94,7 @@ class KayaTheInexorableEmblemEffect extends OneShotEffect {
cards.addAll(player.getGraveyard());
break;
case "Exile":
cards.addAll(game.getExile().getCards(filter, game));
cards.addAllCards(game.getExile().getCards(filter, game));
break;
}
return CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter2);

View file

@ -5011,7 +5011,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
game.informPlayers(getLogName() + " scries " + event.getAmount() + CardUtil.getSourceLogName(game, source));
Cards cards = new CardsImpl();
cards.addAll(getLibrary().getTopCards(game, event.getAmount()));
cards.addAllCards(getLibrary().getTopCards(game, event.getAmount()));
if (!cards.isEmpty()) {
TargetCard target = new TargetCard(0, cards.size(), Zone.LIBRARY,
new FilterCard("card" + (cards.size() == 1 ? "" : "s")
@ -5039,7 +5039,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
game.informPlayers(getLogName() + " surveils " + event.getAmount() + CardUtil.getSourceLogName(game, source));
Cards cards = new CardsImpl();
cards.addAll(getLibrary().getTopCards(game, event.getAmount()));
cards.addAllCards(getLibrary().getTopCards(game, event.getAmount()));
if (!cards.isEmpty()) {
TargetCard target = new TargetCard(0, cards.size(), Zone.LIBRARY,
new FilterCard("card " + (cards.size() == 1 ? "" : "s")