From 663bde22ac9efdf691d6efd63dba914c1abe44d5 Mon Sep 17 00:00:00 2001 From: kevlahnota Date: Tue, 17 Sep 2024 14:58:43 +0800 Subject: [PATCH] Add ReplacementEffectView, StaticAbility View for Netplay Dialog --- .../game/replacement/ReplacementEffect.java | 10 ++++ .../replacement/ReplacementEffectView.java | 47 +++++++++++++++++++ .../game/staticability/StaticAbility.java | 11 +++++ .../game/staticability/StaticAbilityView.java | 47 +++++++++++++++++++ .../forge/trackable/TrackableProperty.java | 8 ++++ .../forge/player/PlayerControllerHuman.java | 26 +++++----- 6 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/replacement/ReplacementEffectView.java create mode 100644 forge-game/src/main/java/forge/game/staticability/StaticAbilityView.java diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java index 1836337d45a..90747deaa5e 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java @@ -60,6 +60,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { private boolean hasRun = false; private List otherChoices = null; + private ReplacementEffectView view = null; /** * Gets the id. @@ -109,6 +110,15 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { } } + public ReplacementEffectView getView() { + if (view == null) + view = new ReplacementEffectView(this); + else { + view.updateHostCard(this); + view.updateDescription(this); + } + return view; + } /** * Sets the checks for run. * diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffectView.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffectView.java new file mode 100644 index 00000000000..156431de6d8 --- /dev/null +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffectView.java @@ -0,0 +1,47 @@ +package forge.game.replacement; + +import forge.game.card.CardView; +import forge.game.card.IHasCardView; +import forge.trackable.TrackableObject; +import forge.trackable.TrackableProperty; +import forge.trackable.Tracker; + +public class ReplacementEffectView extends TrackableObject implements IHasCardView { + private static final long serialVersionUID = 1L; + + ReplacementEffectView(ReplacementEffect re) { + this(re, re.getHostCard() == null || re.getHostCard().getGame() == null ? null : re.getHostCard().getGame().getTracker()); + } + + ReplacementEffectView(ReplacementEffect re, Tracker tracker) { + super(re.getId(), tracker); + updateHostCard(re); + updateDescription(re); + } + + @Override + public CardView getCardView() { + return this.getHostCard(); + } + + public CardView getHostCard() { + return get(TrackableProperty.RE_HostCard); + } + + void updateHostCard(ReplacementEffect re) { + set(TrackableProperty.RE_HostCard, CardView.get(re.getHostCard())); + } + + @Override + public String toString() { + return this.getDescription(); + } + + public String getDescription() { + return get(TrackableProperty.RE_Description); + } + + void updateDescription(ReplacementEffect re) { + set(TrackableProperty.RE_Description, re.getDescription()); + } +} diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index 327296f0d9c..8f292c2f328 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -62,6 +62,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone private int mayPlayTurn = 0; private SpellAbility payingTrigSA; + private StaticAbilityView view = null; @Override public final int getId() { @@ -231,6 +232,16 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone this.setCardState(state); } + public StaticAbilityView getView() { + if (view == null) + view = new StaticAbilityView(this); + else { + view.updateHostCard(this); + view.updateDescription(this); + } + return view; + } + public final CardCollectionView applyContinuousAbilityBefore(final StaticAbilityLayer layer, final CardCollectionView preList) { if (!shouldApplyContinuousAbility(layer, false)) { return null; diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityView.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityView.java new file mode 100644 index 00000000000..21fe417994e --- /dev/null +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityView.java @@ -0,0 +1,47 @@ +package forge.game.staticability; + +import forge.game.card.CardView; +import forge.game.card.IHasCardView; +import forge.trackable.TrackableObject; +import forge.trackable.TrackableProperty; +import forge.trackable.Tracker; + +public class StaticAbilityView extends TrackableObject implements IHasCardView { + private static final long serialVersionUID = 1L; + + StaticAbilityView(StaticAbility st) { + this(st, st.getHostCard() == null || st.getHostCard().getGame() == null ? null : st.getHostCard().getGame().getTracker()); + } + + StaticAbilityView(StaticAbility st, Tracker tracker) { + super(st.getId(), tracker); + updateHostCard(st); + updateDescription(st); + } + + @Override + public CardView getCardView() { + return this.getHostCard(); + } + + public CardView getHostCard() { + return get(TrackableProperty.ST_HostCard); + } + + void updateHostCard(StaticAbility st) { + set(TrackableProperty.ST_HostCard, CardView.get(st.getHostCard())); + } + + @Override + public String toString() { + return this.getDescription(); + } + + public String getDescription() { + return get(TrackableProperty.ST_Description); + } + + void updateDescription(StaticAbility st) { + set(TrackableProperty.ST_Description, st.toString()); + } +} diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index 88a10d07e93..8176cff31b5 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -241,6 +241,14 @@ public enum TrackableProperty { CanPlay(TrackableTypes.BooleanType), PromptIfOnlyPossibleAbility(TrackableTypes.BooleanType), + //ReplacementEffectView + RE_HostCard(TrackableTypes.CardViewType), + RE_Description(TrackableTypes.StringType), + + //StaticAbilityView + ST_HostCard(TrackableTypes.CardViewType), + ST_Description(TrackableTypes.StringType), + //HasBackSide BackSideName(TrackableTypes.StringType), HasBackSide(TrackableTypes.BooleanType), diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 2b8d3698a06..aa90be9c9c6 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -35,9 +35,11 @@ import forge.game.player.*; import forge.game.player.actions.SelectCardAction; import forge.game.player.actions.SelectPlayerAction; import forge.game.replacement.ReplacementEffect; +import forge.game.replacement.ReplacementEffectView; import forge.game.replacement.ReplacementLayer; import forge.game.spellability.*; import forge.game.staticability.StaticAbility; +import forge.game.staticability.StaticAbilityView; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerType; import forge.game.trigger.WrappedAbility; @@ -1857,19 +1859,16 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (possibleReplacers.size() == 1) { return first; } - final List res = Lists.newArrayListWithCapacity(possibleReplacers.size()); - for (ReplacementEffect r : possibleReplacers) - res.add(r.getDescription()); - String prompt = localizer.getMessage("lblChooseFirstApplyReplacementEffect"); + final List res = possibleReplacers.stream().map(ReplacementEffect::getDescription).collect(Collectors.toList()); final String firstStr = res.get(0); + final String prompt = localizer.getMessage("lblChooseFirstApplyReplacementEffect"); for (int i = 1; i < res.size(); i++) { // prompt user if there are multiple different options if (!res.get(i).equals(firstStr)) { - if (!GuiBase.isNetworkplay()) //non network game show more info since they don't need serialization + if (!GuiBase.isNetworkplay()) //non network game don't need serialization return getGui().one(prompt, possibleReplacers); - int index = res.indexOf(getGui().one(prompt, res)); - if (index > -1) - return possibleReplacers.get(index); + ReplacementEffectView rev = getGui().one(prompt, possibleReplacers.stream().map(ReplacementEffect::getView).collect(Collectors.toList())); + return possibleReplacers.stream().filter(re -> re.getId() == rev.getId()).findAny().orElse(first); } } // return first option without prompting if all options are the same @@ -1882,18 +1881,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (possibleStatics.size() == 1 || !fullControl) { return first; } - final List sts = Lists.newArrayListWithCapacity(possibleStatics.size()); - for (StaticAbility s : possibleStatics) - sts.add(s.toString()); + final List sts = possibleStatics.stream().map(StaticAbility::toString).collect(Collectors.toList()); final String firstStr = sts.get(0); for (int i = 1; i < sts.size(); i++) { // prompt user if there are multiple different options if (!sts.get(i).equals(firstStr)) { - if (!GuiBase.isNetworkplay()) //non network game show more info since they don't need serialization + if (!GuiBase.isNetworkplay()) //non network game don't need serialization return getGui().one(prompt, possibleStatics); - int index = sts.indexOf(getGui().one(prompt, sts)); - if (index > -1) - return possibleStatics.get(index); + StaticAbilityView stv = getGui().one(prompt, possibleStatics.stream().map(StaticAbility::getView).collect(Collectors.toList())); + return possibleStatics.stream().filter(st -> st.getId() == stv.getId()).findAny().orElse(first); } } // return first option without prompting if all options are the same