mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Fix so cards in hidden zones are properly hidden
This commit is contained in:
@@ -222,7 +222,6 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
private Player controller = null;
|
||||
private long controllerTimestamp = 0;
|
||||
private TreeMap<Long, Player> tempControllers = new TreeMap<Long, Player>();
|
||||
private final Set<Player> mayLookAt = Sets.newHashSet();
|
||||
|
||||
private String originalText = "", text = "";
|
||||
private String echoCost = "";
|
||||
@@ -2120,13 +2119,11 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
view.updateController(this);
|
||||
}
|
||||
|
||||
public final void setMayLookAt(final Player player, final boolean mayLookAt0) {
|
||||
if (mayLookAt0) {
|
||||
mayLookAt.add(player);
|
||||
}
|
||||
else {
|
||||
mayLookAt.remove(player);
|
||||
}
|
||||
public final void setMayLookAt(final Player player, final boolean mayLookAt) {
|
||||
setMayLookAt(player, mayLookAt, false);
|
||||
}
|
||||
public final void setMayLookAt(final Player player, final boolean mayLookAt, final boolean temp) {
|
||||
view.setPlayerMayLook(player, mayLookAt, temp);
|
||||
}
|
||||
|
||||
public final CardCollectionView getEquippedBy(boolean allowModify) {
|
||||
@@ -6064,81 +6061,6 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canBeShownTo(final Player viewer) {
|
||||
if (viewer == null) { return false; }
|
||||
|
||||
Zone zone = getZone();
|
||||
if (zone == null) { return true; } //cards outside any zone are visible to all
|
||||
|
||||
final Player controller = getController();
|
||||
switch (zone.getZoneType()) {
|
||||
case Ante:
|
||||
case Command:
|
||||
case Exile:
|
||||
case Battlefield:
|
||||
case Graveyard:
|
||||
case Stack:
|
||||
//cards in these zones are visible to all
|
||||
return true;
|
||||
case Hand:
|
||||
if (controller.hasKeyword("Play with your hand revealed.")) {
|
||||
return true;
|
||||
}
|
||||
//fall through
|
||||
case Sideboard:
|
||||
//face-up cards in these zones are hidden to opponents unless they specify otherwise
|
||||
if (controller.isOpponentOf(viewer) && !hasKeyword("Your opponent may look at this card.")) {
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
case Library:
|
||||
case PlanarDeck:
|
||||
//cards in these zones are hidden to all unless they specify otherwise
|
||||
if (controller == viewer && hasKeyword("You may look at this card.")) {
|
||||
return true;
|
||||
}
|
||||
if (controller.isOpponentOf(viewer) && hasKeyword("Your opponent may look at this card.")) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SchemeDeck:
|
||||
// true for now, to actually see the Scheme cards (can't see deck anyway)
|
||||
return true;
|
||||
}
|
||||
|
||||
// special viewing permissions for viewer
|
||||
if (mayLookAt.contains(viewer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//if viewer is controlled by another player, also check if card can be shown to that player
|
||||
if (controller.isMindSlaved() && viewer == controller.getMindSlaveMaster()) {
|
||||
return canBeShownTo(controller);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canCardFaceBeShownTo(final Player viewer) {
|
||||
if (!isFaceDown()) {
|
||||
return true;
|
||||
}
|
||||
if (viewer.hasKeyword("CanSeeOpponentsFaceDownCards")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// special viewing permissions for viewer
|
||||
if (mayLookAt.contains(viewer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//if viewer is controlled by another player, also check if face can be shown to that player
|
||||
if (viewer.isMindSlaved() && canCardFaceBeShownTo(viewer.getMindSlaveMaster())) {
|
||||
return true;
|
||||
}
|
||||
return !getController().isOpponentOf(viewer) || hasKeyword("Your opponent may look at this card.");
|
||||
}
|
||||
|
||||
public int getCMC() {
|
||||
return getCMC(SplitCMCMode.CurrentSideCMC);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import forge.item.IPaperCard;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.trackable.TrackableObject;
|
||||
import forge.trackable.TrackableProperty;
|
||||
import forge.util.FCollectionView;
|
||||
|
||||
|
||||
public class CardView extends GameEntityView {
|
||||
@@ -52,11 +53,11 @@ public class CardView extends GameEntityView {
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static boolean mayViewAny(Iterable<CardView> cards) {
|
||||
public static boolean mayViewAny(Iterable<CardView> cards, PlayerView viewer) {
|
||||
if (cards == null) { return false; }
|
||||
|
||||
for (CardView cv : cards) {
|
||||
if (cv.mayBeShown) {
|
||||
if (cv.canBeShownTo(viewer)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -289,11 +290,120 @@ public class CardView extends GameEntityView {
|
||||
set(TrackableProperty.NamedCard, c.getNamedCard());
|
||||
}
|
||||
|
||||
public boolean mayPlayerLook(PlayerView pv) {
|
||||
TrackableCollection<PlayerView> col = get(TrackableProperty.PlayerMayLook);
|
||||
if (col != null && col.contains(pv)) {
|
||||
return true;
|
||||
}
|
||||
col = get(TrackableProperty.PlayerMayLookTemp);
|
||||
if (col != null && col.contains(pv)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setPlayerMayLook(Player p, boolean mayLook, boolean temp) {
|
||||
TrackableProperty prop = temp ? TrackableProperty.PlayerMayLookTemp : TrackableProperty.PlayerMayLook;
|
||||
TrackableCollection<PlayerView> col = get(prop);
|
||||
if (mayLook) {
|
||||
if (col == null) {
|
||||
col = new TrackableCollection<PlayerView>(p.getView());
|
||||
set(prop, col);
|
||||
}
|
||||
else if (col.add(p.getView())) {
|
||||
flagAsChanged(prop);
|
||||
}
|
||||
}
|
||||
else if (col != null) {
|
||||
if (col.remove(p.getView())) {
|
||||
if (col.isEmpty()) {
|
||||
set(prop, null);
|
||||
}
|
||||
else {
|
||||
flagAsChanged(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean canBeShownTo(final PlayerView viewer) {
|
||||
if (viewer == null) { return false; }
|
||||
|
||||
ZoneType zone = getZone();
|
||||
if (zone == null) { return true; } //cards outside any zone are visible to all
|
||||
|
||||
final PlayerView controller = getController();
|
||||
switch (zone) {
|
||||
case Ante:
|
||||
case Command:
|
||||
case Exile:
|
||||
case Battlefield:
|
||||
case Graveyard:
|
||||
case Stack:
|
||||
//cards in these zones are visible to all
|
||||
return true;
|
||||
case Hand:
|
||||
if (controller.hasKeyword("Play with your hand revealed.")) {
|
||||
return true;
|
||||
}
|
||||
//fall through
|
||||
case Sideboard:
|
||||
//face-up cards in these zones are hidden to opponents unless they specify otherwise
|
||||
if (controller.isOpponentOf(viewer) && !getCurrentState().getOpponentMayLook()) {
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
case Library:
|
||||
case PlanarDeck:
|
||||
//cards in these zones are hidden to all unless they specify otherwise
|
||||
if (controller == viewer && getCurrentState().getYouMayLook()) {
|
||||
return true;
|
||||
}
|
||||
if (controller.isOpponentOf(viewer) && getCurrentState().getOpponentMayLook()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SchemeDeck:
|
||||
// true for now, to actually see the Scheme cards (can't see deck anyway)
|
||||
return true;
|
||||
}
|
||||
|
||||
// special viewing permissions for viewer
|
||||
if (mayPlayerLook(viewer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//if viewer is controlled by another player, also check if card can be shown to that player
|
||||
PlayerView mindSlaveMaster = controller.getMindSlaveMaster();
|
||||
if (mindSlaveMaster != null && mindSlaveMaster == viewer) {
|
||||
return canBeShownTo(controller);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean canFaceDownBeShownTo(final PlayerView viewer) {
|
||||
if (!isFaceDown()) {
|
||||
return true;
|
||||
}
|
||||
if (viewer.hasKeyword("CanSeeOpponentsFaceDownCards")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// special viewing permissions for viewer
|
||||
if (mayPlayerLook(viewer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//if viewer is controlled by another player, also check if face can be shown to that player
|
||||
PlayerView mindSlaveMaster = viewer.getMindSlaveMaster();
|
||||
if (mindSlaveMaster != null && canFaceDownBeShownTo(mindSlaveMaster)) {
|
||||
return true;
|
||||
}
|
||||
return !getController().isOpponentOf(viewer) || getCurrentState().getOpponentMayLook();
|
||||
}
|
||||
|
||||
public CardView getEquipping() {
|
||||
return get(TrackableProperty.Equipping);
|
||||
}
|
||||
|
||||
public Iterable<CardView> getEquippedBy() {
|
||||
public FCollectionView<CardView> getEquippedBy() {
|
||||
return get(TrackableProperty.EquippedBy);
|
||||
}
|
||||
|
||||
@@ -327,7 +437,7 @@ public class CardView extends GameEntityView {
|
||||
return get(TrackableProperty.Fortifying);
|
||||
}
|
||||
|
||||
public Iterable<CardView> getFortifiedBy() {
|
||||
public FCollectionView<CardView> getFortifiedBy() {
|
||||
return get(TrackableProperty.FortifiedBy);
|
||||
}
|
||||
|
||||
@@ -335,7 +445,7 @@ public class CardView extends GameEntityView {
|
||||
return getFortifiedBy() != null;
|
||||
}
|
||||
|
||||
public Iterable<CardView> getGainControlTargets() {
|
||||
public FCollectionView<CardView> getGainControlTargets() {
|
||||
return get(TrackableProperty.GainControlTargets);
|
||||
}
|
||||
|
||||
@@ -343,11 +453,11 @@ public class CardView extends GameEntityView {
|
||||
return get(TrackableProperty.CloneOrigin);
|
||||
}
|
||||
|
||||
public Iterable<CardView> getImprintedCards() {
|
||||
public FCollectionView<CardView> getImprintedCards() {
|
||||
return get(TrackableProperty.ImprintedCards);
|
||||
}
|
||||
|
||||
public Iterable<CardView> getHauntedBy() {
|
||||
public FCollectionView<CardView> getHauntedBy() {
|
||||
return get(TrackableProperty.HauntedBy);
|
||||
}
|
||||
|
||||
@@ -355,7 +465,7 @@ public class CardView extends GameEntityView {
|
||||
return get(TrackableProperty.Haunting);
|
||||
}
|
||||
|
||||
public Iterable<CardView> getMustBlockCards() {
|
||||
public FCollectionView<CardView> getMustBlockCards() {
|
||||
return get(TrackableProperty.MustBlockCards);
|
||||
}
|
||||
|
||||
@@ -534,9 +644,9 @@ public class CardView extends GameEntityView {
|
||||
return getCurrentState().getName();
|
||||
}
|
||||
|
||||
if (!mayBeShown) {
|
||||
return "(Unknown card)";
|
||||
}
|
||||
/*if (!mayBeShown) {
|
||||
return "???";
|
||||
}*/
|
||||
|
||||
if (StringUtils.isEmpty(getCurrentState().getName())) {
|
||||
CardStateView alternate = getAlternateState();
|
||||
@@ -599,8 +709,8 @@ public class CardView extends GameEntityView {
|
||||
set(TrackableProperty.Colors, c.determineColor());
|
||||
}
|
||||
|
||||
public String getImageKey(boolean ignoreMayBeShown) {
|
||||
if (mayBeShown || ignoreMayBeShown) {
|
||||
public String getImageKey(PlayerView viewer) {
|
||||
if (viewer == null || canBeShownTo(viewer)) {
|
||||
return get(TrackableProperty.ImageKey);
|
||||
}
|
||||
return ImageKeys.HIDDEN_CARD;
|
||||
@@ -741,6 +851,12 @@ public class CardView extends GameEntityView {
|
||||
public boolean hasTrample() {
|
||||
return get(TrackableProperty.HasTrample);
|
||||
}
|
||||
public boolean getYouMayLook() {
|
||||
return get(TrackableProperty.YouMayLook);
|
||||
}
|
||||
public boolean getOpponentMayLook() {
|
||||
return get(TrackableProperty.OpponentMayLook);
|
||||
}
|
||||
public int getBlockAdditional() {
|
||||
return get(TrackableProperty.BlockAdditional);
|
||||
}
|
||||
@@ -756,6 +872,7 @@ public class CardView extends GameEntityView {
|
||||
set(TrackableProperty.HasInfect, c.hasKeyword("Infect", state));
|
||||
set(TrackableProperty.HasStorm, c.hasKeyword("Storm", state));
|
||||
set(TrackableProperty.HasTrample, c.hasKeyword("Trample", state));
|
||||
set(TrackableProperty.OpponentMayLook, c.hasKeyword("Your opponent may look at this card."));
|
||||
set(TrackableProperty.BlockAdditional, c.getAmountOfKeyword("CARDNAME can block an additional creature.", state));
|
||||
updateAbilityText(c, state);
|
||||
}
|
||||
@@ -895,13 +1012,4 @@ public class CardView extends GameEntityView {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//below are properties not shared across game instances
|
||||
private boolean mayBeShown = true; //TODO: Make may be shown get updated
|
||||
public boolean mayBeShown() {
|
||||
return mayBeShown;
|
||||
}
|
||||
public void setMayBeShown(boolean mayBeShown0) {
|
||||
//mayBeShown = mayBeShown0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2080,6 +2080,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
return;
|
||||
}
|
||||
mindSlaveMaster = mindSlaveMaster0;
|
||||
view.updateMindSlaveMaster(this);
|
||||
|
||||
if (mindSlaveMaster != null) {
|
||||
LobbyPlayer oldLobbyPlayer = getLobbyPlayer();
|
||||
|
||||
@@ -104,6 +104,9 @@ public class PlayerView extends GameEntityView {
|
||||
public KeywordCollectionView getKeywords() {
|
||||
return get(TrackableProperty.Keywords);
|
||||
}
|
||||
public boolean hasKeyword(String keyword) {
|
||||
return getKeywords().contains(keyword);
|
||||
}
|
||||
void updateKeywords(Player p) {
|
||||
set(TrackableProperty.Keywords, p.getKeywords());
|
||||
}
|
||||
@@ -130,6 +133,13 @@ public class PlayerView extends GameEntityView {
|
||||
throw new NotImplementedException("Not implemented");
|
||||
}
|
||||
|
||||
public PlayerView getMindSlaveMaster() {
|
||||
return get(TrackableProperty.Commander);
|
||||
}
|
||||
void updateMindSlaveMaster(Player p) {
|
||||
set(TrackableProperty.Commander, PlayerView.get(p.getMindSlaveMaster()));
|
||||
}
|
||||
|
||||
public Iterable<CardView> getAnte() {
|
||||
return get(TrackableProperty.Ante);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
package forge.trackable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import forge.util.FCollection;
|
||||
|
||||
public class TrackableCollection<T extends TrackableObject> extends FCollection<T> {
|
||||
public TrackableCollection() {
|
||||
}
|
||||
public TrackableCollection(T e) {
|
||||
super(e);
|
||||
}
|
||||
public TrackableCollection(Collection<T> c) {
|
||||
super(c);
|
||||
}
|
||||
public TrackableCollection(Iterable<T> i) {
|
||||
super(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T item) {
|
||||
|
||||
@@ -39,6 +39,8 @@ public enum TrackableProperty {
|
||||
ChosenDirection(TrackableTypes.EnumType(Direction.class)),
|
||||
Remembered(TrackableTypes.StringType),
|
||||
NamedCard(TrackableTypes.StringType),
|
||||
PlayerMayLook(TrackableTypes.PlayerViewCollectionType),
|
||||
PlayerMayLookTemp(TrackableTypes.PlayerViewCollectionType),
|
||||
Equipping(TrackableTypes.CardViewType),
|
||||
EquippedBy(TrackableTypes.CardViewCollectionType),
|
||||
Enchanting(TrackableTypes.GameEntityViewType),
|
||||
@@ -74,6 +76,8 @@ public enum TrackableProperty {
|
||||
HasInfect(TrackableTypes.BooleanType),
|
||||
HasStorm(TrackableTypes.BooleanType),
|
||||
HasTrample(TrackableTypes.BooleanType),
|
||||
YouMayLook(TrackableTypes.BooleanType),
|
||||
OpponentMayLook(TrackableTypes.BooleanType),
|
||||
BlockAdditional(TrackableTypes.IntegerType),
|
||||
AbilityText(TrackableTypes.StringType),
|
||||
NonAbilityText(TrackableTypes.StringType),
|
||||
@@ -90,6 +94,7 @@ public enum TrackableProperty {
|
||||
Keywords(TrackableTypes.KeywordCollectionViewType),
|
||||
Commander(TrackableTypes.CardViewType),
|
||||
CommanderDamage(TrackableTypes.IntegerMapType),
|
||||
MindSlaveMaster(TrackableTypes.PlayerViewType),
|
||||
Ante(TrackableTypes.CardViewCollectionType),
|
||||
Battlefield(TrackableTypes.CardViewCollectionType),
|
||||
Command(TrackableTypes.CardViewCollectionType),
|
||||
|
||||
Reference in New Issue
Block a user