diff --git a/.gitattributes b/.gitattributes index 5daf0d063f4..14b2212c771 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14499,31 +14499,32 @@ src/main/java/forge/game/combat/AttackingBand.java -text src/main/java/forge/game/combat/Combat.java svneol=native#text/plain src/main/java/forge/game/combat/CombatLki.java -text src/main/java/forge/game/combat/CombatUtil.java svneol=native#text/plain +src/main/java/forge/game/event/EventValueChangeType.java -text src/main/java/forge/game/event/GameEvent.java -text src/main/java/forge/game/event/GameEventAnteCardsSelected.java -text src/main/java/forge/game/event/GameEventAttackersDeclared.java -text -src/main/java/forge/game/event/GameEventBlockerAssigned.java -text src/main/java/forge/game/event/GameEventBlockersDeclared.java -text +src/main/java/forge/game/event/GameEventCardAttachment.java -text src/main/java/forge/game/event/GameEventCardChangeZone.java -text +src/main/java/forge/game/event/GameEventCardCounters.java -text src/main/java/forge/game/event/GameEventCardDamaged.java -text src/main/java/forge/game/event/GameEventCardDestroyed.java -text -src/main/java/forge/game/event/GameEventCardEquipped.java -text src/main/java/forge/game/event/GameEventCardRegenerated.java -text src/main/java/forge/game/event/GameEventCardSacrificed.java -text +src/main/java/forge/game/event/GameEventCardStatsChanged.java -text src/main/java/forge/game/event/GameEventCardTapped.java -text -src/main/java/forge/game/event/GameEventCounterAdded.java -text -src/main/java/forge/game/event/GameEventCounterRemoved.java -text src/main/java/forge/game/event/GameEventFlipCoin.java -text src/main/java/forge/game/event/GameEventGameFinished.java -text src/main/java/forge/game/event/GameEventGameOutcome.java -text src/main/java/forge/game/event/GameEventGameRestarted.java -text src/main/java/forge/game/event/GameEventGameStarted.java -text src/main/java/forge/game/event/GameEventLandPlayed.java -text -src/main/java/forge/game/event/GameEventLifeLoss.java -text src/main/java/forge/game/event/GameEventManaBurn.java -text +src/main/java/forge/game/event/GameEventManaPool.java -text src/main/java/forge/game/event/GameEventMulligan.java -text src/main/java/forge/game/event/GameEventPlayerControl.java -text src/main/java/forge/game/event/GameEventPlayerDamaged.java -text +src/main/java/forge/game/event/GameEventPlayerLivesChanged.java -text src/main/java/forge/game/event/GameEventPlayerPoisoned.java -text src/main/java/forge/game/event/GameEventPlayerPriority.java -text src/main/java/forge/game/event/GameEventShuffle.java -text @@ -14648,6 +14649,9 @@ src/main/java/forge/gui/download/GuiDownloadQuestImages.java -text src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java svneol=native#text/plain src/main/java/forge/gui/download/GuiDownloader.java -text src/main/java/forge/gui/download/package-info.java -text +src/main/java/forge/gui/events/IUiEventVisitor.java -text +src/main/java/forge/gui/events/UiEvent.java -text +src/main/java/forge/gui/events/UiEventBlockerAssigned.java -text src/main/java/forge/gui/framework/DragCell.java -text src/main/java/forge/gui/framework/DragTab.java -text src/main/java/forge/gui/framework/EDocID.java -text @@ -14810,6 +14814,7 @@ src/main/java/forge/gui/toolbox/special/DeckLister.java -text src/main/java/forge/gui/toolbox/special/FDeckChooser.java -text src/main/java/forge/gui/toolbox/special/PhaseIndicator.java -text src/main/java/forge/gui/toolbox/special/PhaseLabel.java -text +src/main/java/forge/gui/toolbox/special/PlayerDetailsPanel.java -text src/main/java/forge/gui/toolbox/special/package-info.java -text src/main/java/forge/item/BoosterPack.java -text src/main/java/forge/item/FatPack.java -text @@ -14937,7 +14942,6 @@ src/main/java/forge/util/IgnoringXStream.java -text src/main/java/forge/util/Lang.java -text src/main/java/forge/util/LineReader.java -text src/main/java/forge/util/MultiplexOutputStream.java svneol=native#text/plain -src/main/java/forge/util/MyObservable.java svneol=native#text/plain src/main/java/forge/util/MyRandom.java svneol=native#text/plain src/main/java/forge/util/PredicateString.java -text src/main/java/forge/util/ReflectionUtil.java -text diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 36f6ed01f05..6f8cca23801 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -73,10 +73,10 @@ import forge.game.GlobalRuleChange; import forge.game.combat.AttackingBand; import forge.game.combat.Combat; import forge.game.event.GameEventCardDamaged; +import forge.game.event.GameEventCardAttachment.AttachMethod; import forge.game.event.GameEventCardDamaged.DamageType; -import forge.game.event.GameEventCardEquipped; -import forge.game.event.GameEventCounterAdded; -import forge.game.event.GameEventCounterRemoved; +import forge.game.event.GameEventCardAttachment; +import forge.game.event.GameEventCardCounters; import forge.game.event.GameEventCardTapped; import forge.game.player.Player; import forge.game.zone.Zone; @@ -1134,6 +1134,9 @@ public class Card extends GameEntity implements Comparable { int newValue = addAmount + (oldValue == null ? 0 : oldValue.intValue()); this.counters.put(counterType, Integer.valueOf(newValue)); + // play the Add Counter sound + getGame().fireEvent(new GameEventCardCounters(this, counterType, oldValue == null ? 0 : oldValue.intValue(), newValue)); + // Run triggers final Map runParams = new TreeMap(); runParams.put("Card", this); @@ -1141,11 +1144,6 @@ public class Card extends GameEntity implements Comparable { for (int i = 0; i < addAmount; i++) { getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, runParams, false); } - - // play the Add Counter sound - getGame().fireEvent(new GameEventCounterAdded(addAmount)); - - this.updateObservers(); } /** @@ -1205,6 +1203,9 @@ public class Card extends GameEntity implements Comparable { this.counters.remove(counterName); } + // Play the Subtract Counter sound + getGame().fireEvent(new GameEventCardCounters(this, counterName, oldValue == null ? 0 : oldValue.intValue(), newValue)); + // Run triggers final Map runParams = new TreeMap(); runParams.put("Card", this); @@ -1223,10 +1224,6 @@ public class Card extends GameEntity implements Comparable { } - // Play the Subtract Counter sound - getGame().fireEvent(new GameEventCounterRemoved(delta)); - - this.updateObservers(); } /** @@ -3296,112 +3293,6 @@ public class Card extends GameEntity implements Comparable { return !this.fortifying.isEmpty(); } - /** - *

- * addEquippedBy. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void addEquippedBy(final Card c) { - this.equippedBy.add(c); - this.updateObservers(); - } - - /** - *

- * addFortifiedBy. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void addFortifiedBy(final Card c) { - this.fortifiedBy.add(c); - this.updateObservers(); - } - - /** - *

- * removeEquippedBy. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void removeEquippedBy(final Card c) { - this.equippedBy.remove(c); - this.updateObservers(); - } - - /** - *

- * removeFortifiedBy. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void removeFortifiedBy(final Card c) { - this.fortifiedBy.remove(c); - this.updateObservers(); - } - - /** - *

- * addEquipping. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void addEquipping(final Card c) { - this.equipping.add(c); - this.setTimestamp(getGame().getNextTimestamp()); - this.updateObservers(); - } - - /** - *

- * addFortifying. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void addFortifying(final Card c) { - this.fortifying.add(c); - this.setTimestamp(getGame().getNextTimestamp()); - this.updateObservers(); - } - - /** - *

- * removeFortifying. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void removeFortifying(final Card c) { - this.fortifying.remove(c); - this.updateObservers(); - } - - /** - *

- * removeEquipping. - *

- * - * @param c - * a {@link forge.Card} object. - */ - public final void removeEquipping(final Card c) { - this.equipping.remove(c); - this.updateObservers(); - } - /** *

* equipCard. @@ -3426,14 +3317,21 @@ public class Card extends GameEntity implements Comparable { return; } } + + Card oldTarget = null; if (this.isEquipping()) { - this.unEquipCard(this.getEquipping().get(0)); + oldTarget = this.getEquipping().get(0); + this.unEquipCard(oldTarget); } - this.addEquipping(c); - c.addEquippedBy(this); + + // They use double links... it's doubtful + this.equipping.add(c); + this.setTimestamp(this.getGame().getNextTimestamp()); + c.equippedBy.add(this); // Play the Equip sound - getGame().fireEvent(new GameEventCardEquipped()); + getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Equip)); + // run trigger final HashMap runParams = new HashMap(); runParams.put("AttachSource", this); @@ -3451,14 +3349,18 @@ public class Card extends GameEntity implements Comparable { * a {@link forge.Card} object. */ public final void fortifyCard(final Card c) { + Card oldTarget = null; if (this.isFortifying()) { - this.unFortifyCard(this.getFortifying().get(0)); + oldTarget = this.getFortifying().get(0); + this.unFortifyCard(oldTarget); } - this.addFortifying(c); - c.addFortifiedBy(this); + + this.fortifying.add(c); + this.setTimestamp(this.getGame().getNextTimestamp()); + c.fortifiedBy.add(this); // Play the Equip sound - getGame().fireEvent(new GameEventCardEquipped()); + getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Fortify)); // run trigger final HashMap runParams = new HashMap(); runParams.put("AttachSource", this); @@ -3477,8 +3379,10 @@ public class Card extends GameEntity implements Comparable { public final void unEquipCard(final Card c) // equipment.unEquipCard(equippedCard); { this.equipping.remove(c); - c.removeEquippedBy(this); + c.equippedBy.remove(this); + getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Equip)); + // Run triggers final Map runParams = new TreeMap(); runParams.put("Equipment", this); @@ -3496,7 +3400,9 @@ public class Card extends GameEntity implements Comparable { */ public final void unFortifyCard(final Card c) { // fortification.unEquipCard(fortifiedCard); this.fortifying.remove(c); - c.removeFortifiedBy(this); + c.fortifiedBy.remove(this); + + getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Fortify)); } /** @@ -3613,20 +3519,6 @@ public class Card extends GameEntity implements Comparable { return false; } - /** - *

- * addEnchanting. - *

- * - * @param e - * a {@link forge.GameEntity} object. - */ - public final void addEnchanting(final GameEntity e) { - this.enchanting = e; - this.setTimestamp(getGame().getNextTimestamp()); - this.updateObservers(); - } - /** *

* removeEnchanting. @@ -3638,7 +3530,6 @@ public class Card extends GameEntity implements Comparable { public final void removeEnchanting(final GameEntity e) { if (this.enchanting.equals(e)) { this.enchanting = null; - this.updateObservers(); } } @@ -3656,8 +3547,12 @@ public class Card extends GameEntity implements Comparable { + " but it can't be enchanted."); return; } - this.addEnchanting(entity); + this.enchanting = entity; + this.setTimestamp(this.getGame().getNextTimestamp()); entity.addEnchantedBy(this); + + getGame().fireEvent(new GameEventCardAttachment(this, null, entity, AttachMethod.Enchant)); + // run trigger final HashMap runParams = new HashMap(); runParams.put("AttachSource", this); @@ -3673,12 +3568,15 @@ public class Card extends GameEntity implements Comparable { * @param gameEntity * a {@link forge.GameEntity} object. */ - public final void unEnchantEntity(final GameEntity gameEntity) { - if ((this.enchanting != null) && this.enchanting.equals(gameEntity)) { - this.enchanting = null; - gameEntity.removeEnchantedBy(this); - } + public final void unEnchantEntity(final GameEntity entity) { + if (this.enchanting == null || !this.enchanting.equals(entity)) + return; + + this.enchanting = null; + entity.removeEnchantedBy(this); + getGame().fireEvent(new GameEventCardAttachment(this, entity, null, AttachMethod.Enchant)); } + /** *

* Setter for the field type. @@ -4313,7 +4211,6 @@ public class Card extends GameEntity implements Comparable { */ public final void setTapped(final boolean b) { this.tapped = b; - this.updateObservers(); } /** @@ -4322,15 +4219,15 @@ public class Card extends GameEntity implements Comparable { *

*/ public final void tap() { - if (this.isUntapped()) { - // Run triggers - final Map runParams = new TreeMap(); - runParams.put("Card", this); - getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams, false); - } - this.setTapped(true); + if (this.isTapped()) + return; + + // Run triggers + final Map runParams = new TreeMap(); + runParams.put("Card", this); + getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams, false); - // Play the Tap sound + this.setTapped(true); getGame().fireEvent(new GameEventCardTapped(this, true)); } @@ -4340,21 +4237,19 @@ public class Card extends GameEntity implements Comparable { *

*/ public final void untap() { - if (this.isTapped()) { - // Run triggers - final Map runParams = new TreeMap(); - runParams.put("Card", this); - getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, runParams, false); + if (this.isUntapped()) + return; - // Play the Untap sound - getGame().fireEvent(new GameEventCardTapped(this, false)); - } + // Run triggers + final Map runParams = new TreeMap(); + runParams.put("Card", this); + getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, runParams, false); for (final Command var : this.untapCommandList) { var.run(); } - this.setTapped(false); + getGame().fireEvent(new GameEventCardTapped(this, false)); } // keywords are like flying, fear, first strike, etc... diff --git a/src/main/java/forge/GameEntity.java b/src/main/java/forge/GameEntity.java index 0b67c5f5786..b634c407645 100644 --- a/src/main/java/forge/GameEntity.java +++ b/src/main/java/forge/GameEntity.java @@ -22,8 +22,9 @@ import java.util.Map; import java.util.TreeMap; import forge.game.Game; +import forge.game.event.GameEventCardAttachment; +import forge.game.event.GameEventCardAttachment.AttachMethod; import forge.game.player.Player; -import forge.util.MyObservable; /** *

@@ -33,7 +34,7 @@ import forge.util.MyObservable; * @author Forge * @version $Id: Player.java 10091 2011-08-30 16:11:21Z Sloth $ */ -public abstract class GameEntity extends MyObservable implements ITargetable { +public abstract class GameEntity implements ITargetable { private String name = ""; private int preventNextDamage = 0; private TreeMap> preventionShieldsWithEffects = new TreeMap>(); @@ -438,7 +439,7 @@ public abstract class GameEntity extends MyObservable implements ITargetable { */ public final void addEnchantedBy(final Card c) { this.enchantedBy.add(c); - this.updateObservers(); + getGame().fireEvent(new GameEventCardAttachment(c, null, this, AttachMethod.Enchant)); } /** @@ -451,7 +452,7 @@ public abstract class GameEntity extends MyObservable implements ITargetable { */ public final void removeEnchantedBy(final Card c) { this.enchantedBy.remove(c); - this.updateObservers(); + getGame().fireEvent(new GameEventCardAttachment(c, this, null, AttachMethod.Enchant)); } /** diff --git a/src/main/java/forge/card/ability/effects/AnimateEffect.java b/src/main/java/forge/card/ability/effects/AnimateEffect.java index 207b38b3290..32ab2f85c90 100644 --- a/src/main/java/forge/card/ability/effects/AnimateEffect.java +++ b/src/main/java/forge/card/ability/effects/AnimateEffect.java @@ -18,6 +18,9 @@ import forge.card.staticability.StaticAbility; import forge.card.trigger.Trigger; import forge.card.trigger.TriggerHandler; import forge.game.Game; +import forge.game.event.GameEvent; +import forge.game.event.GameEventCardStatsChanged; +import forge.game.event.IGameEventVisitor; public class AnimateEffect extends AnimateEffectBase { @@ -291,6 +294,8 @@ public class AnimateEffect extends AnimateEffectBase { game.getEndOfTurn().addUntil(unanimate); } } + + game.fireEvent(new GameEventCardStatsChanged(c)); } } // animateResolve extends SpellEffect { diff --git a/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java b/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java index 971dceecd2b..ab876516eaf 100644 --- a/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java +++ b/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java @@ -467,13 +467,15 @@ public class ChangeZoneEffect extends SpellAbilityEffect { } else if (tgtC.isEquipment()) { //Equipment if (tgtC.isEquipping()) { final Card oldEquiped = tgtC.getEquippingCard(); - tgtC.removeEquipping(oldEquiped); + if ( null != oldEquiped ) + tgtC.unEquipCard(oldEquiped); } tgtC.equipCard(attachedTo); } else { // fortification if (tgtC.isFortifying()) { final Card oldFortified = tgtC.getFortifyingCard(); - tgtC.removeFortifying(oldFortified); + if( oldFortified != null ) + tgtC.unFortifyCard(oldFortified); } tgtC.fortifyCard(attachedTo); } @@ -806,13 +808,15 @@ public class ChangeZoneEffect extends SpellAbilityEffect { } else if (c.isEquipment()) { //Equipment if (c.isEquipping()) { final Card oldEquiped = c.getEquippingCard(); - c.removeEquipping(oldEquiped); + if ( null != oldEquiped ) + c.unEquipCard(oldEquiped); } c.equipCard(attachedTo); } else { if (c.isFortifying()) { final Card oldFortified = c.getFortifyingCard(); - c.removeFortifying(oldFortified); + if ( null != oldFortified ) + c.unFortifyCard(oldFortified); } c.fortifyCard(attachedTo); } diff --git a/src/main/java/forge/card/ability/effects/ControlPlayerEffect.java b/src/main/java/forge/card/ability/effects/ControlPlayerEffect.java index c7911fa741f..afbd90dd301 100644 --- a/src/main/java/forge/card/ability/effects/ControlPlayerEffect.java +++ b/src/main/java/forge/card/ability/effects/ControlPlayerEffect.java @@ -36,7 +36,7 @@ public class ControlPlayerEffect extends SpellAbilityEffect { game.getUntap().addUntil(pTarget, new Command() { @Override public void run() { - pTarget.obeyNewMaster(activator.getLobbyPlayer().createControllerFor(pTarget)); + pTarget.setControllingPlayerController(activator.getLobbyPlayer().createControllerFor(pTarget)); // on following cleanup release control game.getEndOfTurn().addUntil(new Command() { diff --git a/src/main/java/forge/card/ability/effects/EndTurnEffect.java b/src/main/java/forge/card/ability/effects/EndTurnEffect.java index 91bc3b55c0a..93f87dc18d7 100644 --- a/src/main/java/forge/card/ability/effects/EndTurnEffect.java +++ b/src/main/java/forge/card/ability/effects/EndTurnEffect.java @@ -5,7 +5,6 @@ import forge.Card; import forge.card.ability.SpellAbilityEffect; import forge.card.spellability.SpellAbility; import forge.game.Game; -import forge.game.player.Player; public class EndTurnEffect extends SpellAbilityEffect { @@ -39,12 +38,6 @@ public class EndTurnEffect extends SpellAbilityEffect { // 4) The current phase and/or step ends. The game skips straight to the // cleanup step. The cleanup step happens in its entirety. game.getPhaseHandler().endTurnByEffect(); - - // Update observers - for (Player p : game.getPlayers()) { - p.updateObservers(); - p.updateLabelObservers(); - } } diff --git a/src/main/java/forge/card/ability/effects/RestartGameEffect.java b/src/main/java/forge/card/ability/effects/RestartGameEffect.java index edd392f7acc..c0963c6dbb1 100644 --- a/src/main/java/forge/card/ability/effects/RestartGameEffect.java +++ b/src/main/java/forge/card/ability/effects/RestartGameEffect.java @@ -74,7 +74,7 @@ public class RestartGameEffect extends SpellAbilityEffect { RegisteredPlayer psc = game.getMatch().getPlayers().get(i); player.setStartingLife(psc.getStartingLife()); - player.setPoisonCounters(0); + player.setPoisonCounters(0, sa.getSourceCard()); player.setNumLandsPlayed(0); player.setNumBasicForestsPlayed(0); GameNew.putCardsOnBattlefield(player, psc.getCardsOnBattlefield(player)); @@ -86,9 +86,6 @@ public class RestartGameEffect extends SpellAbilityEffect { } player.shuffle(); - player.getZone(ZoneType.Battlefield).updateObservers(); - player.updateObservers(); - player.getZone(ZoneType.Hand).updateObservers(); } trigHandler.clearSuppression(TriggerType.ChangesZone); diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java index 043168ebb3b..5633b00b9a9 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java @@ -324,8 +324,6 @@ public class CardFactoryCreatures { intermSumToughness += c.getBaseDefense(); game.getAction().exile(c); } - // is this needed? - card.getController().getZone(ZoneType.Battlefield).updateObservers(); } } card.setBaseAttack(intermSumPower); diff --git a/src/main/java/forge/card/mana/ManaPool.java b/src/main/java/forge/card/mana/ManaPool.java index 06b92ac8a40..4e015ba29de 100644 --- a/src/main/java/forge/card/mana/ManaPool.java +++ b/src/main/java/forge/card/mana/ManaPool.java @@ -30,6 +30,8 @@ import forge.card.MagicColor; import forge.card.spellability.AbilityManaPart; import forge.card.spellability.SpellAbility; import forge.game.GlobalRuleChange; +import forge.game.event.EventValueChangeType; +import forge.game.event.GameEventManaPool; import forge.game.player.Player; import forge.util.maps.MapOfLists; import forge.util.maps.TreeMapOfLists; @@ -72,7 +74,7 @@ public class ManaPool { private void addMana(final Mana mana) { floatingMana.add(mana.getColorCode(), mana); - owner.updateObservers(); + owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.Added, mana)); } /** @@ -87,8 +89,9 @@ public class ManaPool { for (final Mana m : manaList) { this.addMana(m); } - owner.getGame().getAction().checkStateEffects(); - owner.updateObservers(); + + // check state effects replaced by checkStaticAbilities + owner.getGame().getAction().checkStaticAbilities(); } /** @@ -117,6 +120,7 @@ public class ManaPool { numRemoved += floatingMana.get(b).size(); floatingMana.get(b).clear(); } + owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.Cleared, null)); return numRemoved; } @@ -228,7 +232,7 @@ public class ManaPool { private void removeMana(final Mana mana) { Collection cm = floatingMana.get(mana.getColorCode()); if (cm.remove(mana)) { - owner.updateObservers(); + owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.Removed, mana)); } } @@ -319,9 +323,9 @@ public class ManaPool { this.addMana(m); } } - manaPaid.clear(); - this.owner.updateObservers(); + + owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.ComplexUpdate, null)); } diff --git a/src/main/java/forge/control/FControl.java b/src/main/java/forge/control/FControl.java index dfe45459541..c35c1969eda 100644 --- a/src/main/java/forge/control/FControl.java +++ b/src/main/java/forge/control/FControl.java @@ -32,8 +32,6 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.WindowConstants; - - import forge.Card; import forge.Constant.Preferences; import forge.Singletons; @@ -433,12 +431,10 @@ public enum FControl { game.subscribeToEvents(playbackControl); } - - VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers()); for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) { - field.getLblLibrary().setHoverable(Preferences.DEV_MODE); + field.getDetailsPanel().getLblLibrary().setHoverable(Preferences.DEV_MODE); } // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch @@ -446,7 +442,5 @@ public enum FControl { VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(game.getPlayers().get(0)); SDisplayUtil.showTab(nextField); } - - } diff --git a/src/main/java/forge/control/FControlGameEventHandler.java b/src/main/java/forge/control/FControlGameEventHandler.java index 32144dcc9cd..32c9582fd9f 100644 --- a/src/main/java/forge/control/FControlGameEventHandler.java +++ b/src/main/java/forge/control/FControlGameEventHandler.java @@ -1,5 +1,7 @@ package forge.control; +import java.util.List; +import java.util.Vector; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang3.tuple.Pair; @@ -11,9 +13,17 @@ import forge.FThreads; import forge.game.Game; import forge.game.event.GameEvent; import forge.game.event.GameEventAnteCardsSelected; +import forge.game.event.GameEventCardChangeZone; +import forge.game.event.GameEventCardCounters; +import forge.game.event.GameEventCardDamaged; +import forge.game.event.GameEventCardStatsChanged; +import forge.game.event.GameEventCardTapped; import forge.game.event.GameEventGameFinished; import forge.game.event.GameEventGameOutcome; +import forge.game.event.GameEventManaPool; import forge.game.event.GameEventPlayerControl; +import forge.game.event.GameEventPlayerLivesChanged; +import forge.game.event.GameEventPlayerPoisoned; import forge.game.event.GameEventPlayerPriority; import forge.game.event.GameEventSpellAbilityCast; import forge.game.event.GameEventSpellRemovedFromStack; @@ -24,6 +34,7 @@ import forge.game.event.IGameEventVisitor; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; +import forge.game.zone.PlayerZone; import forge.gui.GuiDialog; import forge.gui.SOverlayUtils; import forge.gui.match.CMatchUI; @@ -40,8 +51,14 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { this.fc = fc; } + private final boolean LOG_EVENTS = false; + @Subscribe - public void receiveGameEvent(final GameEvent ev) { ev.visit(this); } + public void receiveGameEvent(final GameEvent ev) { + if ( LOG_EVENTS ) + System.out.println("GE: " + ev.toString()); + ev.visit(this); + } private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false); @Override @@ -111,6 +128,9 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(GameEventPlayerControl ev) { + if ( fc.getObservedGame().isGameOver() ) + return null; + FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { CMatchUI.SINGLETON_INSTANCE.initHandViews(fc.getLobby().getGuiPlayer()); VMatchUI.SINGLETON_INSTANCE.populate(); @@ -121,11 +141,13 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { return null; } + private final Runnable unlockGameThreadOnGameOver = new Runnable() { @Override public void run() { + fc.getInputQueue().onGameOver(); // this will unlock any game threads waiting for inputs to complete + } }; + @Override public Void visit(GameEventGameOutcome ev) { - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { - fc.getInputQueue().onGameOver(); // this will unlock any game threads waiting for inputs to complete - } }); + FThreads.invokeInEdtNowOrLater(unlockGameThreadOnGameOver); return null; } @@ -162,5 +184,141 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { if ( !stackUpdPlanned.getAndSet(true) ) FThreads.invokeInEdtNowOrLater(updStack); return null; - } + } + + + + private final List zonesToUpdate = new Vector(); + private final Runnable updZones = new Runnable() { + @Override public void run() { + synchronized (zonesToUpdate) { + CMatchUI.SINGLETON_INSTANCE.updateZones(zonesToUpdate); + zonesToUpdate.clear(); + } + } + }; + + @Override + public Void visit(GameEventCardChangeZone event) { + boolean needUpdate = false; + synchronized (zonesToUpdate) { + needUpdate = zonesToUpdate.isEmpty(); + if ( event.from instanceof PlayerZone && !zonesToUpdate.contains(event.from) ) { + zonesToUpdate.add((PlayerZone)event.from); + } + if ( event.to instanceof PlayerZone && !zonesToUpdate.contains(event.to) ) { + zonesToUpdate.add((PlayerZone)event.to); + } + } + if( needUpdate ) + FThreads.invokeInEdtNowOrLater(updZones); + return null; + } + + @Override + public Void visit(GameEventCardTapped event) { + // TODO Smart partial updates + PlayerZone z = (PlayerZone) event.card.getGame().getZoneOf(event.card); + return updateZone(z); + } + + @Override + public Void visit(GameEventCardDamaged event) { + PlayerZone z = (PlayerZone) event.damaged.getGame().getZoneOf(event.damaged); + return updateZone(z); + } + + + @Override + public Void visit(GameEventCardCounters event) { + PlayerZone z = (PlayerZone) event.target.getGame().getZoneOf(event.target); + return updateZone(z); + } + + private Void updateZone(PlayerZone z) { + boolean needUpdate = false; + synchronized (zonesToUpdate) { + needUpdate = zonesToUpdate.isEmpty(); + if ( !zonesToUpdate.contains(z) ) { + zonesToUpdate.add(z); + } + } + if( needUpdate ) + FThreads.invokeInEdtNowOrLater(updZones); + return null; + } + + + /* (non-Javadoc) + * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventCardStatsChanged) + */ + @Override + public Void visit(GameEventCardStatsChanged event) { + // TODO Smart partial updates + PlayerZone z = (PlayerZone) event.card.getGame().getZoneOf(event.card); + return updateZone(z); + } + + // Update manapool + private final List manaPoolUpdate = new Vector(); + private final Runnable updManaPool = new Runnable() { + @Override public void run() { + synchronized (manaPoolUpdate) { + CMatchUI.SINGLETON_INSTANCE.updateManaPool(manaPoolUpdate); + manaPoolUpdate.clear(); + } + } + }; + + @Override + public Void visit(GameEventManaPool event) { + boolean invokeUpdate = false; + synchronized (manaPoolUpdate) { + if( !manaPoolUpdate.contains(event.player) ) { + invokeUpdate = manaPoolUpdate.isEmpty(); + manaPoolUpdate.add(event.player); + } + } + if (invokeUpdate) + FThreads.invokeInEdtNowOrLater(updManaPool); + return null; + } + + // Update lives counters + private final List livesUpdate = new Vector(); + private final Runnable updLives = new Runnable() { + @Override public void run() { + synchronized (livesUpdate) { + CMatchUI.SINGLETON_INSTANCE.updateLives(livesUpdate); + livesUpdate.clear(); + } + } + }; + @Override + public Void visit(GameEventPlayerLivesChanged event) { + boolean invokeUpdate = false; + synchronized (livesUpdate) { + if( !livesUpdate.contains(event.player) ) { + invokeUpdate = livesUpdate.isEmpty(); + livesUpdate.add(event.player); + } + } + if (invokeUpdate) + FThreads.invokeInEdtNowOrLater(updLives); + return null; + } + + @Override + public Void visit(GameEventPlayerPoisoned event) { + boolean invokeUpdate = false; + synchronized (livesUpdate) { + if( !livesUpdate.contains(event.receiver) ) { + invokeUpdate = livesUpdate.isEmpty(); + livesUpdate.add(event.receiver); + } + } + if (invokeUpdate) + FThreads.invokeInEdtNowOrLater(updLives); + return null; + } } \ No newline at end of file diff --git a/src/main/java/forge/control/FControlGamePlayback.java b/src/main/java/forge/control/FControlGamePlayback.java index 38bf9aaa252..b6f714d6109 100644 --- a/src/main/java/forge/control/FControlGamePlayback.java +++ b/src/main/java/forge/control/FControlGamePlayback.java @@ -8,7 +8,7 @@ import com.google.common.eventbus.Subscribe; import forge.FThreads; import forge.game.event.GameEvent; -import forge.game.event.GameEventBlockerAssigned; +import forge.game.event.GameEventBlockersDeclared; import forge.game.event.GameEventGameFinished; import forge.game.event.GameEventGameStarted; import forge.game.event.GameEventLandPlayed; @@ -53,7 +53,7 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { @Override - public Void visit(GameEventBlockerAssigned event) { + public Void visit(GameEventBlockersDeclared event) { pauseForEvent(combatDelay); return super.visit(event); } diff --git a/src/main/java/forge/control/InputQueue.java b/src/main/java/forge/control/InputQueue.java index 9a3b9a46a3e..f57aba03c0d 100644 --- a/src/main/java/forge/control/InputQueue.java +++ b/src/main/java/forge/control/InputQueue.java @@ -17,6 +17,7 @@ */ package forge.control; +import java.util.Observable; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; @@ -24,7 +25,6 @@ import forge.game.Game; import forge.gui.input.Input; import forge.gui.input.InputLockUI; import forge.gui.input.InputSynchronized; -import forge.util.MyObservable; /** *

@@ -34,7 +34,7 @@ import forge.util.MyObservable; * @author Forge * @version $Id$ */ -public class InputQueue extends MyObservable { +public class InputQueue extends Observable { private final BlockingDeque inputStack = new LinkedBlockingDeque(); private final InputLockUI inputLock; @@ -44,6 +44,12 @@ public class InputQueue extends MyObservable { inputLock = new InputLockUI(this); } + + public final void updateObservers() { + this.setChanged(); + this.notifyObservers(); + } + public final Input getInput() { return inputStack.isEmpty() ? null : this.inputStack.peek(); } diff --git a/src/main/java/forge/game/Game.java b/src/main/java/forge/game/Game.java index b46e9146226..9b9d0952e76 100644 --- a/src/main/java/forge/game/Game.java +++ b/src/main/java/forge/game/Game.java @@ -66,8 +66,8 @@ public class Game { public final Phase endOfCombat; public final Untap untap; public final Upkeep upkeep; - private final PhaseHandler phaseHandler; public final MagicStack stack; + private final PhaseHandler phaseHandler; private final StaticEffects staticEffects = new StaticEffects(); private final TriggerHandler triggerHandler = new TriggerHandler(this); private final ReplacementHandler replacementHandler = new ReplacementHandler(this); diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index 68e868e5aef..97510d4a545 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -137,7 +137,7 @@ public class GameAction { zoneTo.add(c, position); } - zoneTo.updateLabelObservers(); + game.fireEvent(new GameEventCardChangeZone(c, zoneFrom, zoneTo)); return c; } @@ -198,9 +198,6 @@ public class GameAction { return c; } } - - // play the change zone sound - game.fireEvent(new GameEventCardChangeZone(c, zoneFrom, zoneTo)); copied.getOwner().removeInboundToken(copied); @@ -235,8 +232,9 @@ public class GameAction { } zoneFrom.remove(c); } - - zoneTo.updateLabelObservers(); + + // play the change zone sound + game.fireEvent(new GameEventCardChangeZone(c, zoneFrom, zoneTo)); final HashMap runParams = new HashMap(); runParams.put("Card", lastKnownInfo); @@ -672,17 +670,11 @@ public class GameAction { final HashMap runParams = new HashMap(); runParams.put("Card", lastKnownInfo); - if (p != null) { - runParams.put("Origin", p.getZoneType().name()); - } else { - runParams.put("Origin", null); - } + runParams.put("Origin", p == null ? null : p.getZoneType().name()); runParams.put("Destination", ZoneType.Library.name()); game.getTriggerHandler().runTrigger(TriggerType.ChangesZone, runParams, false); - if (p != null) { - p.updateLabelObservers(); - } + game.fireEvent(new GameEventCardChangeZone(c, p, library)); // Soulbond unpairing if (c.isPaired()) { @@ -1445,7 +1437,7 @@ public class GameAction { // FControl should determine now if there are any human players. // Where there are none, it should bring up speed controls - game.fireEvent(new GameEventGameStarted(first, game.getPlayers())); + game.fireEvent(new GameEventGameStarted(game.getType(), first, game.getPlayers())); game.setAge(GameAge.Mulligan); for (final Player p1 : game.getPlayers()) diff --git a/src/main/java/forge/game/GameActionUtil.java b/src/main/java/forge/game/GameActionUtil.java index a67d23c43e1..38ec6131fe8 100644 --- a/src/main/java/forge/game/GameActionUtil.java +++ b/src/main/java/forge/game/GameActionUtil.java @@ -55,7 +55,6 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityRestriction; import forge.game.ai.AiController; import forge.game.player.HumanPlay; -import forge.game.event.GameEventLifeLoss; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; import forge.game.player.PlayerControllerAi; @@ -422,9 +421,6 @@ public final class GameActionUtil { } c.getDamageHistory().registerCombatDamage(player); - - // Play the Life Loss sound - player.getGame().fireEvent(new GameEventLifeLoss()); } // executeCombatDamageToPlayerEffects /** diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java index c9e5c90444d..b8d07c87bf8 100644 --- a/src/main/java/forge/game/GameNew.java +++ b/src/main/java/forge/game/GameNew.java @@ -285,12 +285,6 @@ public class GameNew { rAICards.addAll(getCardsAiCantPlayWell(myDeck)); } - player.updateObservers(); - player.getZone(ZoneType.Battlefield).updateObservers(); - player.getZone(ZoneType.Hand).updateObservers(); - player.getZone(ZoneType.Command).updateObservers(); - player.getZone(ZoneType.Battlefield).updateObservers(); - if( myRemovedAnteCards != null && !myRemovedAnteCards.isEmpty() ) removedAnteCards.addAll(player, myRemovedAnteCards); } diff --git a/src/main/java/forge/game/Match.java b/src/main/java/forge/game/Match.java index 283289c3d93..49a009fc4ab 100644 --- a/src/main/java/forge/game/Match.java +++ b/src/main/java/forge/game/Match.java @@ -6,7 +6,6 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.Lists; - import forge.Card; import forge.Singletons; import forge.game.event.GameEventAnteCardsSelected; @@ -95,13 +94,11 @@ public class Match { currentGame.getAction().invoke(new Runnable() { @Override public void run() { - if (useAnte) { // Deciding which cards go to ante List> list = GameNew.chooseCardsForAnte(currentGame); GameNew.moveCardsToAnte(list); currentGame.fireEvent(new GameEventAnteCardsSelected(list)); } - currentGame.getAction().startGame(); } }); diff --git a/src/main/java/forge/game/ai/AiController.java b/src/main/java/forge/game/ai/AiController.java index 0ac8778575c..34ec7e377b9 100644 --- a/src/main/java/forge/game/ai/AiController.java +++ b/src/main/java/forge/game/ai/AiController.java @@ -760,8 +760,6 @@ public class AiController { Log.debug(sb.toString()); } - attacker.getZone(ZoneType.Battlefield).updateObservers(); - // ai is about to attack, cancel all phase skipping for (Player p : game.getPlayers()) { p.getController().autoPassCancel(); diff --git a/src/main/java/forge/game/combat/Combat.java b/src/main/java/forge/game/combat/Combat.java index a398a849dfa..2677f76050c 100644 --- a/src/main/java/forge/game/combat/Combat.java +++ b/src/main/java/forge/game/combat/Combat.java @@ -430,7 +430,6 @@ public class Combat { Map map = assigningPlayer.getController().assignCombatDamage(blocker, attackers, damage, null, assigningPlayer != blocker.getController()); for (Entry dt : map.entrySet()) { dt.getKey().addAssignedDamage(dt.getValue(), blocker); - dt.getKey().updateObservers(); } } } @@ -488,7 +487,6 @@ public class Combat { addDefendingDamage(dt.getValue(), attacker); } else { dt.getKey().addAssignedDamage(dt.getValue(), attacker); - dt.getKey().updateObservers(); } } diff --git a/src/main/java/forge/game/event/EventValueChangeType.java b/src/main/java/forge/game/event/EventValueChangeType.java new file mode 100644 index 00000000000..792ba615b05 --- /dev/null +++ b/src/main/java/forge/game/event/EventValueChangeType.java @@ -0,0 +1,12 @@ +package forge.game.event; + +/** + * TODO: Write javadoc for this type. + * + */ +public enum EventValueChangeType { + Added, + Removed, + Cleared, + ComplexUpdate +} diff --git a/src/main/java/forge/game/event/GameEventBlockerAssigned.java b/src/main/java/forge/game/event/GameEventBlockerAssigned.java deleted file mode 100644 index b940cb94c53..00000000000 --- a/src/main/java/forge/game/event/GameEventBlockerAssigned.java +++ /dev/null @@ -1,11 +0,0 @@ -package forge.game.event; - -public class GameEventBlockerAssigned extends GameEvent { - - @Override - public T visit(IGameEventVisitor visitor) { - return visitor.visit(this); - } - - -} diff --git a/src/main/java/forge/game/event/GameEventCardAttachment.java b/src/main/java/forge/game/event/GameEventCardAttachment.java new file mode 100644 index 00000000000..4aa4a87d565 --- /dev/null +++ b/src/main/java/forge/game/event/GameEventCardAttachment.java @@ -0,0 +1,30 @@ +package forge.game.event; + +import forge.Card; +import forge.GameEntity; + +public class GameEventCardAttachment extends GameEvent { + public enum AttachMethod { + Equip, + Fortify, + Enchant; + } + + + public final Card equipment; + public final GameEntity newTarget; // can enchant player, I'm ssaving a class to enchants - it could be incorrect. + public final GameEntity oldEntiy; + public final AttachMethod method; + + public GameEventCardAttachment(Card attachment, GameEntity formerEntity, GameEntity newEntity, AttachMethod method) { + this.equipment = attachment; + this.newTarget = newEntity; + this.oldEntiy = formerEntity; + this.method = method; + } + + @Override + public T visit(IGameEventVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/forge/game/event/GameEventCardChangeZone.java b/src/main/java/forge/game/event/GameEventCardChangeZone.java index d70c275144c..8698e3c6bbe 100644 --- a/src/main/java/forge/game/event/GameEventCardChangeZone.java +++ b/src/main/java/forge/game/event/GameEventCardChangeZone.java @@ -20,5 +20,13 @@ public class GameEventCardChangeZone extends GameEvent { public T visit(IGameEventVisitor visitor) { return visitor.visit(this); } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("%s : [%s] -> [%s]", card, from, to); + } } diff --git a/src/main/java/forge/game/event/GameEventCardCounters.java b/src/main/java/forge/game/event/GameEventCardCounters.java new file mode 100644 index 00000000000..6d79f32c098 --- /dev/null +++ b/src/main/java/forge/game/event/GameEventCardCounters.java @@ -0,0 +1,23 @@ +package forge.game.event; + +import forge.Card; +import forge.CounterType; + +public class GameEventCardCounters extends GameEvent { + public final Card target; + public final CounterType type; + public final int oldValue; + public final int newValue; + + public GameEventCardCounters(Card card, CounterType counterType, int old, int newValue) { + target = card; + type = counterType; + this.oldValue = old; + this.newValue = newValue; + } + + @Override + public T visit(IGameEventVisitor visitor) { + return visitor.visit(this); + } +} \ No newline at end of file diff --git a/src/main/java/forge/game/event/GameEventCardEquipped.java b/src/main/java/forge/game/event/GameEventCardEquipped.java deleted file mode 100644 index f82123ac58c..00000000000 --- a/src/main/java/forge/game/event/GameEventCardEquipped.java +++ /dev/null @@ -1,9 +0,0 @@ -package forge.game.event; - -public class GameEventCardEquipped extends GameEvent { - - @Override - public T visit(IGameEventVisitor visitor) { - return visitor.visit(this); - } -} diff --git a/src/main/java/forge/game/event/GameEventCardStatsChanged.java b/src/main/java/forge/game/event/GameEventCardStatsChanged.java new file mode 100644 index 00000000000..e070e7286d0 --- /dev/null +++ b/src/main/java/forge/game/event/GameEventCardStatsChanged.java @@ -0,0 +1,24 @@ +package forge.game.event; + +import forge.Card; + +/** + * This means card's characteristics have changed on server, clients must re-request them + */ +public class GameEventCardStatsChanged extends GameEvent { + + public final Card card; + public GameEventCardStatsChanged(Card affected) { + card = affected; + } + + /* (non-Javadoc) + * @see forge.game.event.GameEvent#visit(forge.game.event.IGameEventVisitor) + */ + @Override + public T visit(IGameEventVisitor visitor) { + // TODO Auto-generated method stub + return visitor.visit(this); + } + +} diff --git a/src/main/java/forge/game/event/GameEventCounterAdded.java b/src/main/java/forge/game/event/GameEventCounterAdded.java deleted file mode 100644 index 8548db55c37..00000000000 --- a/src/main/java/forge/game/event/GameEventCounterAdded.java +++ /dev/null @@ -1,14 +0,0 @@ -package forge.game.event; - -public class GameEventCounterAdded extends GameEvent { - public final int Amount; - - public GameEventCounterAdded(int n) { - Amount = n; - } - - @Override - public T visit(IGameEventVisitor visitor) { - return visitor.visit(this); - } -} \ No newline at end of file diff --git a/src/main/java/forge/game/event/GameEventCounterRemoved.java b/src/main/java/forge/game/event/GameEventCounterRemoved.java deleted file mode 100644 index 6dc63aedf78..00000000000 --- a/src/main/java/forge/game/event/GameEventCounterRemoved.java +++ /dev/null @@ -1,18 +0,0 @@ -package forge.game.event; - -/** - * - * - */ -public class GameEventCounterRemoved extends GameEvent { - public final int Amount; - - public GameEventCounterRemoved(int n) { - Amount = n; - } - - @Override - public T visit(IGameEventVisitor visitor) { - return visitor.visit(this); - } -} diff --git a/src/main/java/forge/game/event/GameEventGameStarted.java b/src/main/java/forge/game/event/GameEventGameStarted.java index 34ac4697a7b..1df40bf776f 100644 --- a/src/main/java/forge/game/event/GameEventGameStarted.java +++ b/src/main/java/forge/game/event/GameEventGameStarted.java @@ -1,6 +1,8 @@ package forge.game.event; +import forge.game.GameType; import forge.game.player.Player; +import forge.util.Lang; /** * TODO: Write javadoc for this type. @@ -10,9 +12,11 @@ public class GameEventGameStarted extends GameEvent { public final Player firstTurn; public final Iterable players; + public final GameType gameType; - public GameEventGameStarted(Player firstTurn, Iterable players) { + public GameEventGameStarted(GameType type, Player firstTurn, Iterable players) { super(); + this.gameType = type; this.firstTurn = firstTurn; this.players = players; } @@ -22,5 +26,13 @@ public class GameEventGameStarted extends GameEvent { public T visit(IGameEventVisitor visitor) { return visitor.visit(this); } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("%s game between %s started. %s goes first ", gameType, Lang.joinHomogenous(players), firstTurn) ; + } } diff --git a/src/main/java/forge/game/event/GameEventLifeLoss.java b/src/main/java/forge/game/event/GameEventLifeLoss.java deleted file mode 100644 index bf791513601..00000000000 --- a/src/main/java/forge/game/event/GameEventLifeLoss.java +++ /dev/null @@ -1,9 +0,0 @@ -package forge.game.event; - -public class GameEventLifeLoss extends GameEvent { - - @Override - public T visit(IGameEventVisitor visitor) { - return visitor.visit(this); - } -} diff --git a/src/main/java/forge/game/event/GameEventManaBurn.java b/src/main/java/forge/game/event/GameEventManaBurn.java index 007c0ff5d29..204465a38f6 100644 --- a/src/main/java/forge/game/event/GameEventManaBurn.java +++ b/src/main/java/forge/game/event/GameEventManaBurn.java @@ -1,7 +1,20 @@ package forge.game.event; +// This special event denotes loss of mana due to phase end public class GameEventManaBurn extends GameEvent { + public final boolean causedLifeLoss; + public final int amount; + + /** + * TODO: Write javadoc for Constructor. + * @param dealDamage + * @param burn + */ + public GameEventManaBurn(int burn, boolean dealDamage) { + amount = burn; + causedLifeLoss = dealDamage; + } @Override public T visit(IGameEventVisitor visitor) { diff --git a/src/main/java/forge/game/event/GameEventManaPool.java b/src/main/java/forge/game/event/GameEventManaPool.java new file mode 100644 index 00000000000..9ef54610f08 --- /dev/null +++ b/src/main/java/forge/game/event/GameEventManaPool.java @@ -0,0 +1,38 @@ +package forge.game.event; + +import forge.card.mana.Mana; +import forge.game.player.Player; +import forge.util.Lang; + +/** + * TODO: Write javadoc for this type. + * + */ +public class GameEventManaPool extends GameEvent { + + + public final Player player; + public final EventValueChangeType mode; + public final Mana mana; + + public GameEventManaPool(Player owner, EventValueChangeType changeMode, Mana mana) { + this.mana = mana; + player = owner; + mode = changeMode; + } + + + @Override + public T visit(IGameEventVisitor visitor) { + return visitor.visit(this); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("%s mana pool %s - %s ", Lang.getPossesive(player.getName()), mode, mana); + } + +} diff --git a/src/main/java/forge/game/event/GameEventPlayerLivesChanged.java b/src/main/java/forge/game/event/GameEventPlayerLivesChanged.java new file mode 100644 index 00000000000..9d2d8141de3 --- /dev/null +++ b/src/main/java/forge/game/event/GameEventPlayerLivesChanged.java @@ -0,0 +1,21 @@ +package forge.game.event; + +import forge.game.player.Player; + +public class GameEventPlayerLivesChanged extends GameEvent { + + public final Player player; + public final int oldLives; + public final int newLives; + + public GameEventPlayerLivesChanged(Player who, int oldValue, int newValue) { + player = who; + oldLives = oldValue; + newLives = newValue; + } + + @Override + public T visit(IGameEventVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/forge/game/event/GameEventPlayerPoisoned.java b/src/main/java/forge/game/event/GameEventPlayerPoisoned.java index 97ec402c6d0..492cc49249e 100644 --- a/src/main/java/forge/game/event/GameEventPlayerPoisoned.java +++ b/src/main/java/forge/game/event/GameEventPlayerPoisoned.java @@ -10,16 +10,14 @@ import forge.game.player.Player; public class GameEventPlayerPoisoned extends GameEvent { public final Player receiver; public final Card source; + public final int oldValue; public final int amount; - public GameEventPlayerPoisoned(Player recv, Card src, int n) { + public GameEventPlayerPoisoned(Player recv, Card src, int old, int num) { receiver = recv; source = src; - amount = n; - } - - public GameEventPlayerPoisoned(Player recv, Card src) { - this(recv, src, 1); + oldValue = old; + amount = num; } diff --git a/src/main/java/forge/game/event/GameEventShuffle.java b/src/main/java/forge/game/event/GameEventShuffle.java index 50a637a73f0..9db5450c104 100644 --- a/src/main/java/forge/game/event/GameEventShuffle.java +++ b/src/main/java/forge/game/event/GameEventShuffle.java @@ -1,9 +1,26 @@ package forge.game.event; +import forge.game.player.Player; +import forge.util.Lang; + public class GameEventShuffle extends GameEvent { + public final Player player; + + public GameEventShuffle(Player player) { + this.player = player; + } + @Override public T visit(IGameEventVisitor visitor) { return visitor.visit(this); } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("%s %s his/her/its library", player, Lang.joinVerb(player.getName(), "shuffle")); + } } diff --git a/src/main/java/forge/game/event/GameEventTurnBegan.java b/src/main/java/forge/game/event/GameEventTurnBegan.java index 2322530a0d4..d930de90d2c 100644 --- a/src/main/java/forge/game/event/GameEventTurnBegan.java +++ b/src/main/java/forge/game/event/GameEventTurnBegan.java @@ -17,4 +17,12 @@ public class GameEventTurnBegan extends GameEvent { public T visit(IGameEventVisitor visitor) { return visitor.visit(this); } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("Turn %d (%s)", turnNumber, turnOwner); + } } \ No newline at end of file diff --git a/src/main/java/forge/game/event/GameEventTurnPhase.java b/src/main/java/forge/game/event/GameEventTurnPhase.java index 794ab885c0b..c67329a2538 100644 --- a/src/main/java/forge/game/event/GameEventTurnPhase.java +++ b/src/main/java/forge/game/event/GameEventTurnPhase.java @@ -2,6 +2,7 @@ package forge.game.event; import forge.game.phase.PhaseType; import forge.game.player.Player; +import forge.util.Lang; /** * TODO: Write javadoc for this type. @@ -24,4 +25,9 @@ public class GameEventTurnPhase extends GameEvent { public T visit(IGameEventVisitor visitor) { return visitor.visit(this); } + + @Override + public String toString() { + return String.format("%s turn, %s%s phase", Lang.getPossesive(playerTurn.getName()), phaseDesc, phase.nameForUi ); + } } diff --git a/src/main/java/forge/game/event/IGameEventVisitor.java b/src/main/java/forge/game/event/IGameEventVisitor.java index 2addcd0cee5..bea9c00b40e 100644 --- a/src/main/java/forge/game/event/IGameEventVisitor.java +++ b/src/main/java/forge/game/event/IGameEventVisitor.java @@ -5,26 +5,26 @@ package forge.game.event; * */ public interface IGameEventVisitor { + T visit(GameEventAnteCardsSelected event); T visit(GameEventAttackersDeclared event); T visit(GameEventBlockersDeclared event); - T visit(GameEventBlockerAssigned event); T visit(GameEventCardDamaged event); T visit(GameEventCardDestroyed event); - T visit(GameEventCardEquipped event); + T visit(GameEventCardAttachment event); T visit(GameEventCardChangeZone event); T visit(GameEventCardRegenerated event); T visit(GameEventCardSacrificed event); - T visit(GameEventAnteCardsSelected event); T visit(GameEventCardTapped event); - T visit(GameEventCounterAdded event); - T visit(GameEventCounterRemoved event); + T visit(GameEventCardStatsChanged event); + T visit(GameEventCardCounters event); T visit(GameEventGameFinished event); T visit(GameEventGameOutcome event); T visit(GameEventFlipCoin event); T visit(GameEventGameStarted event); T visit(GameEventGameRestarted event); T visit(GameEventLandPlayed event); - T visit(GameEventLifeLoss event); + T visit(GameEventPlayerLivesChanged event); + T visit(GameEventManaPool event); T visit(GameEventManaBurn event); T visit(GameEventMulligan event); T visit(GameEventPlayerControl event); @@ -43,26 +43,26 @@ public interface IGameEventVisitor { // This is base class for all visitors. public static class Base implements IGameEventVisitor{ + public T visit(GameEventAnteCardsSelected event) { return null; } public T visit(GameEventAttackersDeclared event) { return null; } public T visit(GameEventBlockersDeclared event) { return null; } - public T visit(GameEventBlockerAssigned event) { return null; } public T visit(GameEventCardDamaged event) { return null; } public T visit(GameEventCardDestroyed event) { return null; } - public T visit(GameEventCardEquipped event) { return null; } + public T visit(GameEventCardAttachment event) { return null; } public T visit(GameEventCardChangeZone event) { return null; } public T visit(GameEventCardRegenerated event) { return null; } public T visit(GameEventCardSacrificed event) { return null; } - public T visit(GameEventAnteCardsSelected event) { return null; } public T visit(GameEventCardTapped event) { return null; } - public T visit(GameEventCounterAdded event) { return null; } - public T visit(GameEventCounterRemoved event) { return null; } + public T visit(GameEventCardStatsChanged event) { return null; } + public T visit(GameEventCardCounters event) { return null; } public T visit(GameEventGameFinished event) { return null; } public T visit(GameEventGameOutcome event) { return null; } public T visit(GameEventFlipCoin event) { return null; } public T visit(GameEventGameStarted event) { return null; } public T visit(GameEventGameRestarted event) { return null; } public T visit(GameEventLandPlayed event) { return null; } - public T visit(GameEventLifeLoss event) { return null; } + public T visit(GameEventPlayerLivesChanged event) { return null; } + public T visit(GameEventManaPool event) { return null; } public T visit(GameEventManaBurn event) { return null; } public T visit(GameEventMulligan event) { return null; } public T visit(GameEventPlayerControl event) { return null; } @@ -79,5 +79,8 @@ public interface IGameEventVisitor { public T visit(GameEventPlayerDamaged event) { return null; } } + + + } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 14adb31d642..6945e4e202b 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -42,7 +42,6 @@ import forge.game.GameType; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.event.GameEventAttackersDeclared; -import forge.game.event.GameEventBlockerAssigned; import forge.game.event.GameEventBlockersDeclared; import forge.game.event.GameEventPlayerPriority; import forge.game.event.GameEventTurnBegan; @@ -431,13 +430,14 @@ public class PhaseHandler implements java.io.Serializable { for (Player p : game.getPlayers()) { int burn = p.getManaPool().clearPool(true); - if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_MANABURN)) { + boolean dealDamage = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_MANABURN); + + if (dealDamage) { p.loseLife(burn); - - // Play the Mana Burn sound - game.fireEvent(new GameEventManaBurn()); } - p.updateObservers(); + // Play the Mana Burn sound + if ( burn > 0 ) + game.fireEvent(new GameEventManaBurn(burn, dealDamage)); } switch (this.phase) { @@ -523,7 +523,6 @@ public class PhaseHandler implements java.io.Serializable { Player whoDeclaresBlockers = playerDeclaresBlockers == null || playerDeclaresBlockers.hasLost() ? p : playerDeclaresBlockers; if ( combat.isPlayerAttacked(p) ) { whoDeclaresBlockers.getController().declareBlockers(p, combat); - game.fireEvent(new GameEventBlockerAssigned()); // } if ( game.isGameOver() ) // they just like to close window at any moment @@ -843,6 +842,7 @@ public class PhaseHandler implements java.io.Serializable { if( DEBUG_PHASES ) sw.start(); + game.getAction().checkStateEffects(); game.fireEvent(new GameEventPlayerPriority(getPlayerTurn(), getPhase(), getPriorityPlayer())); pPlayerPriority.getController().takePriority(); diff --git a/src/main/java/forge/game/phase/Untap.java b/src/main/java/forge/game/phase/Untap.java index 0d6906b37df..6497e14fc06 100644 --- a/src/main/java/forge/game/phase/Untap.java +++ b/src/main/java/forge/game/phase/Untap.java @@ -209,16 +209,19 @@ public class Untap extends Phase { final List landList = CardLists.filter(player.getLandsInPlay(), tappedCanUntap); if (!landList.isEmpty()) { + Card toUntap = null; if (player.isComputer()) { // search for lands the computer has and only untap 1 - landList.get(0).untap(); + toUntap = landList.get(0); } else { final InputSelectCards target = new InputSelectCardsFromList(1,1, landList); target.setMessage("Select one tapped land to untap"); Singletons.getControl().getInputQueue().setInputAndWait(target); if( !target.hasCancelled() && !target.getSelected().isEmpty()) - target.getSelected().get(0).untap(); + toUntap = target.getSelected().get(0); } + if ( toUntap != null ) + toUntap.untap(); } } if (game.isCardInPlay("Damping Field") || game.isCardInPlay("Imi Statue")) { diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index b33f1ce0b35..3bdc419a480 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -57,7 +57,7 @@ import forge.game.Game; import forge.game.GameAge; import forge.game.GlobalRuleChange; import forge.game.event.GameEventLandPlayed; -import forge.game.event.GameEventLifeLoss; +import forge.game.event.GameEventPlayerLivesChanged; import forge.game.event.GameEventMulligan; import forge.game.event.GameEventPlayerControl; import forge.game.event.GameEventPlayerDamaged; @@ -379,7 +379,6 @@ public class Player extends GameEntity implements Comparable { // life == newLife change = false; } - this.updateObservers(); return change; } @@ -417,19 +416,6 @@ public class Player extends GameEntity implements Comparable { return this.startingLife; } - /** - *

- * addLife. - *

- * - * @param toAdd - * a int. - */ - private void addLife(final int toAdd) { - this.life += toAdd; - this.updateObservers(); - } - /** *

* gainLife. @@ -460,9 +446,9 @@ public class Player extends GameEntity implements Comparable { final int lifeGain = toGain; if (lifeGain > 0) { - this.addLife(lifeGain); + int oldLife = life; + this.life += lifeGain; newLifeSet = true; - this.updateObservers(); this.lifeGainedThisTurn += lifeGain; // Run triggers @@ -470,6 +456,8 @@ public class Player extends GameEntity implements Comparable { runParams.put("Player", this); runParams.put("LifeAmount", lifeGain); game.getTriggerHandler().runTrigger(TriggerType.LifeGained, runParams, false); + + game.fireEvent(new GameEventPlayerLivesChanged(this, oldLife, life)); } else { System.out.println("Player - trying to gain negative or 0 life"); } @@ -506,10 +494,10 @@ public class Player extends GameEntity implements Comparable { return 0; } if (toLose > 0) { - this.subtractLife(toLose); + int oldLife = life; + this.life -= toLose; lifeLost = toLose; - game.fireEvent(new GameEventLifeLoss()); - this.updateObservers(); + game.fireEvent(new GameEventPlayerLivesChanged(this, oldLife, life)); } else if (toLose == 0) { // Rule 118.4 // this is for players being able to pay 0 life @@ -544,19 +532,6 @@ public class Player extends GameEntity implements Comparable { return true; } - /** - *

- * subtractLife. - *

- * - * @param toSub - * a int. - */ - private void subtractLife(final int toSub) { - this.life -= toSub; - this.updateObservers(); - } - /** *

* canPayLife. @@ -651,7 +626,6 @@ public class Player extends GameEntity implements Comparable { source.getController().gainLife(amount, source); } source.getDamageHistory().registerDamage(this); - this.getGame().fireEvent(new GameEventLifeLoss()); if (isCombat) { final ArrayList types = source.getType(); @@ -1079,10 +1053,7 @@ public class Player extends GameEntity implements Comparable { */ public final void addPoisonCounters(final int num, final Card source) { if (!this.hasKeyword("You can't get poison counters")) { - this.poisonCounters += num; - - game.fireEvent(new GameEventPlayerPoisoned(this, source, num)); - this.updateObservers(); + setPoisonCounters(poisonCounters + num, source); } } @@ -1093,10 +1064,12 @@ public class Player extends GameEntity implements Comparable { * * @param num * a int. + * @param source */ - public final void setPoisonCounters(final int num) { + public final void setPoisonCounters(final int num, Card source) { + int oldPoison = poisonCounters; this.poisonCounters = num; - this.updateObservers(); + game.fireEvent(new GameEventPlayerPoisoned(this, source, oldPoison, num)); } /** @@ -1110,19 +1083,6 @@ public class Player extends GameEntity implements Comparable { return this.poisonCounters; } - /** - *

- * subtractPoisonCounters. - *

- * - * @param num - * a int. - */ - public final void subtractPoisonCounters(final int num) { - this.poisonCounters -= num; - this.updateObservers(); - } - /** * Gets the keywords. * @@ -1814,7 +1774,7 @@ public class Player extends GameEntity implements Comparable { game.getTriggerHandler().runTrigger(TriggerType.Shuffled, runParams, false); // Play the shuffle sound - game.fireEvent(new GameEventShuffle()); + game.fireEvent(new GameEventShuffle(this)); } // shuffle // ////////////////////////////// @@ -2671,13 +2631,6 @@ public class Player extends GameEntity implements Comparable { return this.mustAttackEntity; } - /** - * Update label observers. - */ - public final void updateLabelObservers() { - this.getZone(ZoneType.Hand).updateObservers(); - } - // ////////////////////////////// // // generic Object overrides @@ -2766,11 +2719,14 @@ public class Player extends GameEntity implements Comparable { } public final void releaseControl() { + if ( controller == controllerCreator ) + return; + controller = controllerCreator; game.fireEvent(new GameEventPlayerControl(this, getLobbyPlayer(), null)); } - public final void obeyNewMaster(PlayerController pc) { + public final void setControllingPlayerController(PlayerController pc) { LobbyPlayer oldController = getLobbyPlayer(); controller = pc; game.fireEvent(new GameEventPlayerControl(this, oldController, pc.getLobbyPlayer())); @@ -3166,12 +3122,6 @@ public class Player extends GameEntity implements Comparable { } } - // These are used by UI to mark the player currently being attacked or targeted - // Very bad practice! Someone blame on me. - private boolean highlited = false; - public final void setHighlited(boolean value) { highlited = value; } - public final boolean isHighlited() { return highlited; } - /** * TODO: Write javadoc for this method. */ diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index 4ecee8858b5..9459c990311 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -532,7 +532,6 @@ public class MagicStack /* extends MyObservable */ implements Iterable @@ -98,8 +99,9 @@ public class PlayerZone extends Zone { */ public PlayerZone(final ZoneType zone, final Player inPlayer) { super(zone); + if ( inPlayer == null ) + throw new IllegalArgumentException("Player zone must be initialized with correct player"); this.player = inPlayer; - } // ************ BEGIN - these methods fire updateObservers() ************* @@ -135,14 +137,11 @@ public class PlayerZone extends Zone { return; } - c.addObserver(this); c.setTurnInZone(c.getGame().getPhaseHandler().getTurn()); this.cardList.add(c); if (!this.is(ZoneType.Battlefield)) { c.setTapped(false); - } else if (update) { // setTapped has already called update once - this.update(); } } @@ -157,7 +156,7 @@ public class PlayerZone extends Zone { * @return a boolean */ public final boolean is(final ZoneType zone, final Player player) { - return (zone == this.zoneName && this.player.equals(player)); + return (zone == this.zoneType && this.player.equals(player)); } /** @@ -180,16 +179,7 @@ public class PlayerZone extends Zone { */ @Override public final String toString() { - return this.player != null ? String.format("%s %s", this.player, this.zoneName) : this.zoneName.toString(); - } - - - /** - * TODO: Write javadoc for this method. - */ - @Override - public void updateLabelObservers() { - getPlayer().updateLabelObservers(); + return String.format("%s %s", Lang.getPossesive(this.player.toString()), this.zoneType); } public List getCardsPlayerCanActivate(Player who) { diff --git a/src/main/java/forge/game/zone/Zone.java b/src/main/java/forge/game/zone/Zone.java index 4ce40e7e548..e99d8098d6d 100644 --- a/src/main/java/forge/game/zone/Zone.java +++ b/src/main/java/forge/game/zone/Zone.java @@ -21,8 +21,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Observable; -import java.util.Observer; import java.util.concurrent.CopyOnWriteArrayList; import com.google.common.base.Predicate; @@ -30,7 +28,6 @@ import com.google.common.collect.Iterables; import forge.Card; import forge.game.player.Player; -import forge.util.MyObservable; /** *

@@ -40,15 +37,14 @@ import forge.util.MyObservable; * @author Forge * @version $Id: PlayerZone.java 17582 2012-10-19 22:39:09Z Max mtg $ */ -public class Zone extends MyObservable implements IZone, Observer, java.io.Serializable, Iterable { +public class Zone implements IZone, java.io.Serializable, Iterable { /** Constant serialVersionUID=-5687652485777639176L. */ private static final long serialVersionUID = -5687652485777639176L; /** The cards. */ protected final transient List cardList = new CopyOnWriteArrayList(); protected final transient List roCardList; - protected final ZoneType zoneName; - protected boolean update = true; + protected final ZoneType zoneType; protected final transient List cardsAddedThisTurn = new ArrayList(); protected final ArrayList cardsAddedThisTurnSource = new ArrayList(); @@ -66,14 +62,12 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria * a {@link forge.game.player.Player} object. */ public Zone(final ZoneType zone) { - this.zoneName = zone; + this.zoneType = zone; this.roCardList = Collections.unmodifiableList(cardList); //System.out.println(zoneName + " (ct) " + Integer.toHexString(System.identityHashCode(roCardList))); } - // ************ BEGIN - these methods fire updateObservers() ************* - @Override public void add(final Object o, boolean update) { final Card c = (Card) o; @@ -90,15 +84,10 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria } } - c.addObserver(this); c.setTurnInZone(c.getGame().getPhaseHandler().getTurn()); c.setTapped(false); this.cardList.add(c); - - if (update) { - this.update(); - } } @@ -113,19 +102,6 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria this.add(o, true); } - /** - * Update. - * - * @param ob - * an Observable - * @param object - * an Object - */ - @Override - public final void update(final Observable ob, final Object object) { - this.update(); - } - /** * Adds the. * @@ -154,7 +130,6 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria this.cardList.add(index, c); c.setTurnInZone(c.getGame().getPhaseHandler().getTurn()); - this.update(); } /* @@ -191,7 +166,6 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria @Override public void remove(final Card c) { this.cardList.remove(c); - this.update(); } /** @@ -208,7 +182,6 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria for (Card c : cards) { cardList.add(c); } - this.update(); } // ************ END - these methods fire updateObservers() ************* @@ -222,7 +195,7 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria */ @Override public final boolean is(final ZoneType zone) { - return zone == this.zoneName; + return zone == this.zoneType; } // PlayerZone should override it with a correct implementation @@ -237,7 +210,7 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria */ @Override public final boolean is(final List zones) { - return zones.contains(this.zoneName); + return zones.contains(this.zoneType); } /** @@ -249,7 +222,7 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria */ @Override public final ZoneType getZoneType() { - return this.zoneName; + return this.zoneType; } /** @@ -310,17 +283,6 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria return this.cardList.isEmpty(); } - /** - *

- * update. - *

- */ - public final void update() { - if (this.update) { - this.updateObservers(); - } - } - /** *

* toString. @@ -330,7 +292,7 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria */ @Override public String toString() { - return this.zoneName.toString(); + return this.zoneType.toString(); } /** @@ -373,14 +335,10 @@ public class Zone extends MyObservable implements IZone, Observer, java.io.Seria return roCardList.iterator(); } - /** - * TODO: Write javadoc for this method. - */ - public void updateLabelObservers() { - } - public void shuffle() { Collections.shuffle(cardList); } + + } diff --git a/src/main/java/forge/gui/GuiDisplayUtil.java b/src/main/java/forge/gui/GuiDisplayUtil.java index e262920acd7..eb23275afec 100644 --- a/src/main/java/forge/gui/GuiDisplayUtil.java +++ b/src/main/java/forge/gui/GuiDisplayUtil.java @@ -160,10 +160,6 @@ public final class GuiDisplayUtil { game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); game.getAction().checkStateEffects(); - - for (Player p : game.getRegisteredPlayers()) { - p.getZone(ZoneType.Battlefield).updateObservers(); - } } }); } diff --git a/src/main/java/forge/gui/events/IUiEventVisitor.java b/src/main/java/forge/gui/events/IUiEventVisitor.java new file mode 100644 index 00000000000..85b8ef02a59 --- /dev/null +++ b/src/main/java/forge/gui/events/IUiEventVisitor.java @@ -0,0 +1,6 @@ +package forge.gui.events; + +public interface IUiEventVisitor { + T visit(UiEventBlockerAssigned event); + +} \ No newline at end of file diff --git a/src/main/java/forge/gui/events/UiEvent.java b/src/main/java/forge/gui/events/UiEvent.java new file mode 100644 index 00000000000..d25853b89f7 --- /dev/null +++ b/src/main/java/forge/gui/events/UiEvent.java @@ -0,0 +1,7 @@ +package forge.gui.events; + + +public abstract class UiEvent { + + public abstract T visit(IUiEventVisitor visitor); +} \ No newline at end of file diff --git a/src/main/java/forge/gui/events/UiEventBlockerAssigned.java b/src/main/java/forge/gui/events/UiEventBlockerAssigned.java new file mode 100644 index 00000000000..d7f15bc680e --- /dev/null +++ b/src/main/java/forge/gui/events/UiEventBlockerAssigned.java @@ -0,0 +1,11 @@ +package forge.gui.events; + +public class UiEventBlockerAssigned extends UiEvent { + + @Override + public T visit(IUiEventVisitor visitor) { + return visitor.visit(this); + } + + +} \ No newline at end of file diff --git a/src/main/java/forge/gui/input/InputAttack.java b/src/main/java/forge/gui/input/InputAttack.java index 08786350930..d9b3960e81c 100644 --- a/src/main/java/forge/gui/input/InputAttack.java +++ b/src/main/java/forge/gui/input/InputAttack.java @@ -17,10 +17,7 @@ */ package forge.gui.input; -import java.util.HashSet; import java.util.List; -import java.util.Set; - import com.google.common.collect.Iterables; import forge.Card; @@ -32,7 +29,6 @@ import forge.game.combat.CombatUtil; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.match.CMatchUI; -import forge.util.MyObservable; import forge.view.ButtonUtil; /** @@ -92,7 +88,7 @@ public class InputAttack extends InputSyncronizedBase { } private void showCombat() { - playerAttacks.getZone(ZoneType.Battlefield).updateObservers(); // redraw sword icons + // redraw sword icons CMatchUI.SINGLETON_INSTANCE.showCombat(combat); } @@ -121,7 +117,7 @@ public class InputAttack extends InputSyncronizedBase { if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) { // TODO Is there no way to attacks each turn cards to attack Planeswalkers? combat.removeFromCombat(card); - card.setUsedToPay(false); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay(card, false); showCombat(); // When removing an attacker clear the attacking band this.activateBand(null); @@ -180,48 +176,36 @@ public class InputAttack extends InputSyncronizedBase { } // selectCard() private final void setCurrentDefender(GameEntity def) { - Set toUpdate = new HashSet(); currentDefender = def; for( GameEntity ge: defenders ) { if ( ge instanceof Card) { - ((Card) ge).setUsedToPay(ge == def); - toUpdate.add(((Card) ge).getController().getZone(ZoneType.Battlefield)); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay((Card)ge, ge == def); } else if (ge instanceof Player) { - ((Player) ge).setHighlited(ge == def); - toUpdate.add(ge); + CMatchUI.SINGLETON_INSTANCE.setHighLited((Player) ge, ge == def); } } updateMessage(); - // This will instantly highlight targets - for(MyObservable updateable : toUpdate) { - updateable.updateObservers(); - } + // update UI } private final void activateBand(AttackingBand band) { - Set toUpdate = new HashSet(); if (this.activeBand != null) { for(Card card : this.activeBand.getAttackers()) { - card.setUsedToPay(false); - toUpdate.add(card.getController().getZone(ZoneType.Battlefield)); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay(card, false); } } this.activeBand = band; if (this.activeBand != null) { for(Card card : this.activeBand.getAttackers()) { - card.setUsedToPay(true); - toUpdate.add(card.getController().getZone(ZoneType.Battlefield)); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay(card, true); } } - // This will instantly highlight targets - for(MyObservable updateable : toUpdate) { - updateable.updateObservers(); - } + // update UI } private void updateMessage() { diff --git a/src/main/java/forge/gui/input/InputBlock.java b/src/main/java/forge/gui/input/InputBlock.java index 401b85a0592..9bfc5760e83 100644 --- a/src/main/java/forge/gui/input/InputBlock.java +++ b/src/main/java/forge/gui/input/InputBlock.java @@ -137,11 +137,10 @@ public class InputBlock extends InputSyncronizedBase { currentAttacker = card; Player attacker = null; for(Card c : combat.getAttackers()) { - c.setUsedToPay(card == c); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay(c, card == c); if ( attacker == null ) attacker = c.getController(); } // request redraw from here - attacker.getZone(ZoneType.Battlefield).updateObservers(); } } diff --git a/src/main/java/forge/gui/input/InputConfirmMulligan.java b/src/main/java/forge/gui/input/InputConfirmMulligan.java index 2996c489b05..8cbfb123d10 100644 --- a/src/main/java/forge/gui/input/InputConfirmMulligan.java +++ b/src/main/java/forge/gui/input/InputConfirmMulligan.java @@ -25,6 +25,7 @@ import forge.game.Game; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiDialog; +import forge.gui.match.CMatchUI; import forge.util.Lang; import forge.view.ButtonUtil; /** @@ -120,10 +121,10 @@ public class InputConfirmMulligan extends InputSyncronizedBase { if ( isCommander ) { // allow to choose cards for partial paris if(selected.contains(c0)) { - c0.setUsedToPay(false); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay(c0, false); selected.remove(c0); } else { - c0.setUsedToPay(true); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay(c0, true); selected.add(c0); } if( selected.isEmpty()) diff --git a/src/main/java/forge/gui/input/InputPassPriority.java b/src/main/java/forge/gui/input/InputPassPriority.java index d927b2ae193..6d7b5454243 100644 --- a/src/main/java/forge/gui/input/InputPassPriority.java +++ b/src/main/java/forge/gui/input/InputPassPriority.java @@ -20,7 +20,6 @@ package forge.gui.input; import forge.Card; import forge.card.spellability.SpellAbility; import forge.game.player.Player; -import forge.game.zone.ZoneType; import forge.view.ButtonUtil; /** @@ -45,9 +44,6 @@ public class InputPassPriority extends InputSyncronizedBase { /** {@inheritDoc} */ @Override public final void showMessage() { - for (Player p : player.getGame().getRegisteredPlayers()) { - p.getZone(ZoneType.Battlefield).updateObservers(); - } showMessage(getTurnPhasePriorityMessage(player.getGame())); chosenSa = null; ButtonUtil.enableOnlyOk(); diff --git a/src/main/java/forge/gui/input/InputPayMana.java b/src/main/java/forge/gui/input/InputPayMana.java index 3c645c94079..f2991112a0d 100644 --- a/src/main/java/forge/gui/input/InputPayMana.java +++ b/src/main/java/forge/gui/input/InputPayMana.java @@ -18,7 +18,6 @@ import forge.card.spellability.SpellAbility; import forge.game.Game; import forge.game.player.HumanPlay; import forge.game.player.Player; -import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.view.ButtonUtil; @@ -235,8 +234,6 @@ public abstract class InputPayMana extends InputSyncronizedBase { player.getManaPool().payManaFromAbility(saPaidFor, manaCost, saPaymentSrc); onManaAbilityPaid(); - if ( saPaymentSrc != null ) - player.getZone(ZoneType.Battlefield).updateObservers(); } protected boolean isAlreadyPaid() { diff --git a/src/main/java/forge/gui/input/InputPayManaSimple.java b/src/main/java/forge/gui/input/InputPayManaSimple.java index d923289d4d4..0a02e5bf4f5 100644 --- a/src/main/java/forge/gui/input/InputPayManaSimple.java +++ b/src/main/java/forge/gui/input/InputPayManaSimple.java @@ -22,7 +22,6 @@ import forge.card.mana.ManaCostBeingPaid; import forge.card.spellability.SpellAbility; import forge.game.Game; import forge.game.player.Player; -import forge.game.zone.ZoneType; import forge.view.ButtonUtil; //pays the cost of a card played from the player's hand @@ -96,7 +95,7 @@ public class InputPayManaSimple extends InputPayMana { @Override protected final void onCancel() { player.getManaPool().refundManaPaid(this.saPaidFor, true); - player.getZone(ZoneType.Battlefield).updateObservers(); // DO + // Update UI this.stop(); } diff --git a/src/main/java/forge/gui/input/InputSelectManyBase.java b/src/main/java/forge/gui/input/InputSelectManyBase.java index 534065d3dbd..ddf8778c36e 100644 --- a/src/main/java/forge/gui/input/InputSelectManyBase.java +++ b/src/main/java/forge/gui/input/InputSelectManyBase.java @@ -5,6 +5,7 @@ import java.util.List; import forge.Card; import forge.GameEntity; +import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; public abstract class InputSelectManyBase extends InputSyncronizedBase implements InputSelectMany { @@ -118,14 +119,14 @@ public abstract class InputSelectManyBase extends InputSyn protected void onSelectStateChanged(T c, boolean newState) { if( c instanceof Card ) - ((Card)c).setUsedToPay(newState); // UI supports card highlighting though this abstraction-breaking mechanism + CMatchUI.SINGLETON_INSTANCE.setUsedToPay((Card)c, newState); // UI supports card highlighting though this abstraction-breaking mechanism } protected void afterStop() { for(T c : selected) if( c instanceof Card) - ((Card)c).setUsedToPay(false); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay((Card)c, false); } diff --git a/src/main/java/forge/gui/input/InputSelectTargets.java b/src/main/java/forge/gui/input/InputSelectTargets.java index e70b33813c9..4fbf8731b8b 100644 --- a/src/main/java/forge/gui/input/InputSelectTargets.java +++ b/src/main/java/forge/gui/input/InputSelectTargets.java @@ -12,6 +12,7 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.TargetRestrictions; import forge.game.player.Player; import forge.gui.GuiChoose; +import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; /** @@ -202,7 +203,7 @@ public final class InputSelectTargets extends InputSyncronizedBase { private void addTarget(GameEntity ge) { sa.getTargets().add(ge); if(ge instanceof Card) { - ((Card) ge).setUsedToPay(true); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay((Card) ge, true); } Integer val = targetDepth.get(ge); targetDepth.put(ge, val == null ? Integer.valueOf(1) : Integer.valueOf(val.intValue() + 1) ); @@ -218,7 +219,7 @@ public final class InputSelectTargets extends InputSyncronizedBase { private void done() { for(GameEntity c : targetDepth.keySet()) if( c instanceof Card) - ((Card)c).setUsedToPay(false); + CMatchUI.SINGLETON_INSTANCE.setUsedToPay((Card)c, false); this.stop(); } diff --git a/src/main/java/forge/gui/match/CMatchUI.java b/src/main/java/forge/gui/match/CMatchUI.java index bf30baa319f..6373bf696a8 100644 --- a/src/main/java/forge/gui/match/CMatchUI.java +++ b/src/main/java/forge/gui/match/CMatchUI.java @@ -19,8 +19,10 @@ package forge.gui.match; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import javax.swing.ImageIcon; @@ -91,7 +93,6 @@ public enum CMatchUI { */ public void initMatch(final List players, LobbyPlayer localPlayer) { view = VMatchUI.SINGLETON_INSTANCE; - // TODO fix for use with multiplayer final String[] indices = Singletons.getModel().getPreferences().getPref(FPref.UI_AVATARS).split(","); @@ -130,15 +131,9 @@ public enum CMatchUI { public void initHandViews(LobbyPlayer localPlayer) { final List hands = new ArrayList(); - final Iterable oldHands = view.getHands(); - + int i = 0; for (Player p : sortedPlayers) { - - PlayerZone hand = p.getZone(ZoneType.Hand); - for(VHand vh : oldHands) - hand.deleteObserver(vh.getLayoutControl()); - if (p.getLobbyPlayer() == localPlayer) { VHand newHand = new VHand(EDocID.Hands[i], p); newHand.getLayoutControl().initialize(); @@ -193,6 +188,17 @@ public enum CMatchUI { return idx < 0 ? null :view.getFieldViews().get(idx); } + public VCommand getCommandFor(Player p) { + int idx = getPlayerIndex(p); + return idx < 0 ? null :view.getCommandViews().get(idx); + } + + public VHand getHandFor(Player p) { + int idx = getPlayerIndex(p); + List allHands = view.getHands(); + return idx < 0 || idx >= allHands.size() ? null : allHands.get(idx); + } + /** * * Fires up trample dialog. Very old code, due for refactoring with new UI. @@ -269,4 +275,70 @@ public enum CMatchUI { CCombat.SINGLETON_INSTANCE.update(); } // showBlockers() + + Set highlitedPlayers = new HashSet(); + public void setHighLited(Player ge, boolean b) { + if (b) highlitedPlayers.add(ge); + else highlitedPlayers.remove(ge); + } + + public boolean isHighlited(Player player) { + return highlitedPlayers.contains(player); + } + + + Set highlitedCards = new HashSet(); + // used to highlight cards in UI + public void setUsedToPay(Card card, boolean value) { + if (value) highlitedCards.add(card); + else highlitedCards.remove(card); + } + + public boolean isUsedToPay(Card card) { + return highlitedCards.contains(card); + } + + public void updateZones(List zonesToUpdate) { + //System.out.println("updateZones " + zonesToUpdate); + for(PlayerZone z : zonesToUpdate) { + Player owner = z.getPlayer(); + + if ( z.is(ZoneType.Command) ) + getCommandFor(owner).getTabletop().setupPlayZone(); + else if ( z.is(ZoneType.Hand) ) { + VHand vHand = getHandFor(owner); + if (null != vHand) + vHand.getLayoutControl().updateHand(); + getFieldViewFor(owner).getDetailsPanel().updateZones(); + } else if ( z.is(ZoneType.Battlefield) ) + getFieldViewFor(owner).getTabletop().setupPlayZone(); + else + getFieldViewFor(owner).getDetailsPanel().updateZones(); + } + } + + + /** + * TODO: Write javadoc for this method. + * @param manaPoolUpdate + */ + public void updateManaPool(List manaPoolUpdate) { + for(Player p : manaPoolUpdate) { + getFieldViewFor(p).getDetailsPanel().updateManaPool(); + } + + } + + + /** + * TODO: Write javadoc for this method. + * @param livesUpdate + */ + public void updateLives(List livesUpdate) { + for(Player p : livesUpdate) { + getFieldViewFor(p).updateDetails(); + } + + } + } diff --git a/src/main/java/forge/gui/match/VMatchUI.java b/src/main/java/forge/gui/match/VMatchUI.java index 7d3b25f3950..3bbaa500751 100644 --- a/src/main/java/forge/gui/match/VMatchUI.java +++ b/src/main/java/forge/gui/match/VMatchUI.java @@ -163,11 +163,7 @@ public enum VMatchUI implements IVTopLevelUI { this.lstCommands = lstCommands0; } - /** - * TODO: Write javadoc for this method. - * @return - */ - public Iterable getHands() { + public List getHands() { return lstHands; } } diff --git a/src/main/java/forge/gui/match/nonsingleton/CCommand.java b/src/main/java/forge/gui/match/nonsingleton/CCommand.java index 51c91d8578f..9cf9ad6fb56 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CCommand.java +++ b/src/main/java/forge/gui/match/nonsingleton/CCommand.java @@ -23,9 +23,6 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; -import java.util.Observable; -import java.util.Observer; - import forge.Card; import forge.Command; import forge.game.player.Player; @@ -49,14 +46,6 @@ public class CCommand implements ICDoc { public void mousePressed(final MouseEvent e) { cardclickAction(e); } }; - // Card play area, attached to battlefield zone. - private final Observer observerPlay = new Observer() { - @Override - public void update(final Observable a, final Object b) { - CCommand.this.view.getTabletop().setupPlayZone(); - } - }; - /** * Controls Swing components of a player's command instance. * @@ -73,9 +62,6 @@ public class CCommand implements ICDoc { if (initializedAlready) { return; } initializedAlready = true; - // Observers - CCommand.this.player.getZone(ZoneType.Command).addObserver(observerPlay); - // Listeners // Battlefield card clicks this.view.getTabletop().addMouseListener(madCardClick); diff --git a/src/main/java/forge/gui/match/nonsingleton/CField.java b/src/main/java/forge/gui/match/nonsingleton/CField.java index 0931150aa5b..bf95089030e 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CField.java +++ b/src/main/java/forge/gui/match/nonsingleton/CField.java @@ -17,20 +17,17 @@ */ package forge.gui.match.nonsingleton; +import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; import java.util.List; -import java.util.Observable; -import java.util.Observer; - -import org.apache.commons.lang3.tuple.Pair; +import com.google.common.base.Function; import forge.Card; import forge.Command; -import forge.FThreads; import forge.Singletons; import forge.Constant.Preferences; import forge.card.spellability.SpellAbility; @@ -45,7 +42,6 @@ import forge.gui.input.Input; import forge.gui.input.InputPayMana; import forge.gui.match.CMatchUI; import forge.gui.match.controllers.CMessage; -import forge.gui.toolbox.FLabel; /** * Controls Swing components of a player's field instance. @@ -62,64 +58,14 @@ public class CField implements ICDoc { public void mouseMoved(final MouseEvent e) { cardoverAction(e); } }; - private final MouseListener madHand = new MouseAdapter() { @Override - public void mousePressed(final MouseEvent e) { - handClicked(); } }; private final MouseListener madAvatar = new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { CMessage.SINGLETON_INSTANCE.getInputControl().selectPlayer(player); } }; - private final MouseListener madExiled = new MouseAdapter() { @Override - public void mousePressed(final MouseEvent e) { exileAction.actionPerformed(null); } }; - - private final MouseListener madLibrary = new MouseAdapter() { @Override - public void mousePressed(final MouseEvent e) { if (Preferences.DEV_MODE) libraryAction.actionPerformed(null); } }; - - private final MouseListener madGraveyard = new MouseAdapter() { @Override - public void mousePressed(final MouseEvent e) { graveAction.actionPerformed(null); } }; - - private final MouseListener madFlashback = new MouseAdapter() { @Override - public void mousePressed(final MouseEvent e) { flashBackAction.actionPerformed(null); } }; - private final MouseListener madCardClick = new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { cardclickAction(e); } }; - - - private final Runnable updateZonesRunnable = new Runnable() { @Override public void run() { CField.this.view.updateZones(CField.this.player); } }; - private final Runnable updateDetailsRunnable = new Runnable() { @Override public void run() { CField.this.view.updateDetails(CField.this.player); } }; - - // Life total, poison total, and keywords, attached directly to Player. - private final Observer observerDetails = new Observer() { - @Override - public void update(final Observable a, final Object b) { - FThreads.invokeInEdtNowOrLater(updateDetailsRunnable); - } - }; - // Hand, Graveyard, Library, Flashback, Exile zones, attached to hand. - private final Observer observerZones = new Observer() { - @Override - public void update(final Observable a, final Object b) { - FThreads.invokeInEdtNowOrLater(updateZonesRunnable); - } - }; - - // Card play area, attached to battlefield zone. - private final Observer observerPlay = new Observer() { - @Override - public void update(final Observable a, final Object b) { - //FThreads.checkEDT("observerPlay.update", true); - CField.this.view.getTabletop().setupPlayZone(); - } - }; - - private final ZoneAction handAction; - private final ZoneAction libraryAction; - private final ZoneAction exileAction; - private final ZoneAction graveAction; - private final ZoneAction flashBackAction; - /** * Controls Swing components of a player's field instance. * @@ -133,11 +79,25 @@ public class CField implements ICDoc { this.viewer = playerViewer; this.view = v0; - handAction = new ZoneAction(player.getZone(ZoneType.Hand), MatchConstants.HUMANHAND); - libraryAction = new ZoneAction(player.getZone(ZoneType.Library), MatchConstants.HUMANLIBRARY); - exileAction = new ZoneAction(player.getZone(ZoneType.Exile), MatchConstants.HUMANEXILED); - graveAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANGRAVEYARD); - flashBackAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANFLASHBACK) { + ZoneAction handAction = new ZoneAction(player.getZone(ZoneType.Hand), MatchConstants.HUMANHAND) { + @Override + public void actionPerformed(ActionEvent e) { + if ( player.getLobbyPlayer() == viewer || Preferences.DEV_MODE || player.hasKeyword("Play with your hand revealed.")) + super.actionPerformed(e); + } + }; + + ZoneAction libraryAction = new ZoneAction(player.getZone(ZoneType.Library), MatchConstants.HUMANLIBRARY) { + @Override + public void actionPerformed(ActionEvent e) { + if (Preferences.DEV_MODE) + super.actionPerformed(e); + } + }; + + ZoneAction exileAction = new ZoneAction(player.getZone(ZoneType.Exile), MatchConstants.HUMANEXILED); + ZoneAction graveAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANGRAVEYARD); + ZoneAction flashBackAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANFLASHBACK) { @Override protected List getCardsAsIterable() { return player.getCardsActivableInExternalZones(); @@ -161,12 +121,24 @@ public class CField implements ICDoc { } } }; - } - private void handClicked() { - if ( player.getLobbyPlayer() == viewer || Preferences.DEV_MODE || player.hasKeyword("Play with your hand revealed.")) { - handAction.actionPerformed(null); - } + + Function manaAction = new Function() { + public Void apply(Byte colorCode) { + if (CField.this.player.getLobbyPlayer() == CField.this.viewer) { + final Input in = Singletons.getControl().getInputQueue().getInput(); + if (in instanceof InputPayMana) { + // Do something + ((InputPayMana) in).selectManaPool(colorCode); + } + } + return null; + } + }; + + + view.getDetailsPanel().setupMouseActions(handAction, libraryAction, exileAction, graveAction, flashBackAction, manaAction); + } /** */ @@ -192,26 +164,15 @@ public class CField implements ICDoc { CMessage.SINGLETON_INSTANCE.getInputControl().selectCard(c, e.isMetaDown()); } - /** */ - private void manaAction(byte colorCode) { - if (CField.this.player.getLobbyPlayer() == CField.this.viewer) { - final Input in = Singletons.getControl().getInputQueue().getInput(); - if (in instanceof InputPayMana) { - // Do something - ((InputPayMana) in).selectManaPool(colorCode); - } - } - } - @Override public void initialize() { if (initializedAlready) { return; } initializedAlready = true; // Observers - CField.this.player.getZone(ZoneType.Hand).addObserver(observerZones); - CField.this.player.getZone(ZoneType.Battlefield).addObserver(observerPlay); - CField.this.player.addObserver(observerDetails); +// CField.this.player.getZone(ZoneType.Hand).addObserver(observerZones); +// CField.this.player.getZone(ZoneType.Battlefield).addObserver(observerPlay); +// CField.this.player.addObserver(observerDetails); // Listeners // Battlefield card clicks @@ -223,31 +184,6 @@ public class CField implements ICDoc { // Player select this.view.getAvatarArea().addMouseListener(madAvatar); - // Detail label listeners - ((FLabel) this.view.getLblGraveyard()).setHoverable(true); - this.view.getLblGraveyard().addMouseListener(madGraveyard); - - ((FLabel) this.view.getLblExile()).setHoverable(true); - this.view.getLblExile().addMouseListener(madExiled); - - if (Preferences.DEV_MODE) { - ((FLabel) this.view.getLblLibrary()).setHoverable(true); - } - this.view.getLblLibrary().addMouseListener(madLibrary); - - ((FLabel) this.view.getLblHand()).setHoverable(true); - this.view.getLblHand().addMouseListener(madHand); - - ((FLabel) this.view.getLblFlashback()).setHoverable(true); - this.view.getLblFlashback().addMouseListener(madFlashback); - - for(final Pair labelPair : this.view.getManaLabels()) { - labelPair.getLeft().setHoverable(true); - labelPair.getLeft().addMouseListener(new MouseAdapter() { @Override - public void mousePressed(final MouseEvent e) { - manaAction(labelPair.getRight()); } } - ); - } } @Override diff --git a/src/main/java/forge/gui/match/nonsingleton/CHand.java b/src/main/java/forge/gui/match/nonsingleton/CHand.java index a9ea1305eda..7387f719b8a 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CHand.java +++ b/src/main/java/forge/gui/match/nonsingleton/CHand.java @@ -25,8 +25,6 @@ import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import java.util.Observable; -import java.util.Observer; - import javax.swing.JLayeredPane; import javax.swing.SwingUtilities; @@ -47,7 +45,7 @@ import forge.view.arcane.util.Animation; * Controls Swing components of a player's hand instance. * */ -public class CHand implements ICDoc, Observer { +public class CHand implements ICDoc { private final Player player; private final VHand view; private boolean initializedAlready = false; @@ -73,8 +71,8 @@ public class CHand implements ICDoc, Observer { if (initializedAlready) { return; } initializedAlready = true; - if (player != null) - player.getZone(ZoneType.Hand).addObserver(this); +// if (player != null) +// player.getZone(ZoneType.Hand).addObserver(this); HandArea area = view.getHandArea(); area.addMouseListener(madCardClick); @@ -134,7 +132,7 @@ public class CHand implements ICDoc, Observer { final HandArea p = view.getHandArea(); VField vf = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(player); - final Rectangle rctLibraryLabel = vf.getLblLibrary().getBounds(); + final Rectangle rctLibraryLabel = vf.getDetailsPanel().getLblLibrary().getBounds(); final List cc = player.getZone(ZoneType.Hand).getCards(); // Animation starts from the library label and runs to the hand panel. @@ -164,7 +162,7 @@ public class CHand implements ICDoc, Observer { JLayeredPane layeredPane = Singletons.getView().getFrame().getLayeredPane(); int fromZoneX = 0, fromZoneY = 0; - final Point zoneLocation = SwingUtilities.convertPoint(vf.getLblLibrary(), + final Point zoneLocation = SwingUtilities.convertPoint(vf.getDetailsPanel().getLblLibrary(), Math.round(rctLibraryLabel.width / 2.0f), Math.round(rctLibraryLabel.height / 2.0f), layeredPane); fromZoneX = zoneLocation.x; fromZoneY = zoneLocation.y; @@ -200,10 +198,8 @@ public class CHand implements ICDoc, Observer { return null; } - /* (non-Javadoc) - * @see forge.gui.framework.ICDoc#update() - */ @Override public void update() { + updateHand(); } } diff --git a/src/main/java/forge/gui/match/nonsingleton/VField.java b/src/main/java/forge/gui/match/nonsingleton/VField.java index c98b5695f1f..03d0815a42f 100644 --- a/src/main/java/forge/gui/match/nonsingleton/VField.java +++ b/src/main/java/forge/gui/match/nonsingleton/VField.java @@ -21,10 +21,6 @@ import java.awt.Color; import java.awt.Font; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.List; -import javax.swing.ImageIcon; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingConstants; @@ -32,11 +28,7 @@ import javax.swing.border.Border; import javax.swing.border.LineBorder; import javax.swing.border.MatteBorder; -import org.apache.commons.lang3.tuple.Pair; - import net.miginfocom.swing.MigLayout; -import forge.card.MagicColor; -import forge.card.mana.ManaPool; import forge.game.player.LobbyPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -44,11 +36,11 @@ import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; import forge.gui.framework.IVDoc; -import forge.gui.match.controllers.CPlayers; +import forge.gui.match.CMatchUI; import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FSkin; -import forge.gui.toolbox.FSkin.SkinProp; import forge.gui.toolbox.special.PhaseIndicator; +import forge.gui.toolbox.special.PlayerDetailsPanel; import forge.view.arcane.PlayArea; /** @@ -71,20 +63,12 @@ public class VField implements IVDoc { private final PlayArea tabletop; private final JPanel avatarArea = new JPanel(); - private final JPanel pnlDetails = new JPanel(); + private final PlayerDetailsPanel detailsPanel; // Avatar area private final FLabel lblAvatar = new FLabel.Builder().fontAlign(SwingConstants.CENTER).iconScaleFactor(1.0f).build(); private final FLabel lblLife = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).build(); - // Info labels - private FLabel lblHand = getBuiltFLabel(FSkin.ZoneImages.ICO_HAND, "99", "Cards in hand"); - private FLabel lblGraveyard = getBuiltFLabel(FSkin.ZoneImages.ICO_GRAVEYARD, "99", "Cards in graveyard"); - private FLabel lblLibrary = getBuiltFLabel(FSkin.ZoneImages.ICO_LIBRARY, "99", "Cards in library"); - private FLabel lblExile = getBuiltFLabel(FSkin.ZoneImages.ICO_EXILE, "99", "Exiled cards"); - private FLabel lblFlashback = getBuiltFLabel(FSkin.ZoneImages.ICO_FLASHBACK, "99", "Flashback cards"); - private FLabel lblPoison = getBuiltFLabel(FSkin.ZoneImages.ICO_POISON, "99", "Poison counters"); - private final List> manaLabels = new ArrayList>(); private final PhaseIndicator phaseInidicator = new PhaseIndicator(); @@ -108,12 +92,8 @@ public class VField implements IVDoc { if (playerOnwer != null) { tab.setText(playerOnwer.getName() + " Field"); } else { tab.setText("NO PLAYER FOR " + docID.toString()); } - manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_BLACK, "99", "Black mana"), MagicColor.BLACK)); - manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_BLUE, "99", "Blue mana"), MagicColor.BLUE)); - manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_GREEN, "99", "Green mana"), MagicColor.GREEN)); - manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_RED, "99", "Red mana"), MagicColor.RED)); - manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_WHITE, "99", "White mana"), MagicColor.WHITE)); - manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_COLORLESS, "99", "Colorless mana"), (byte)0)); + + detailsPanel = new PlayerDetailsPanel(player); // TODO player is hard-coded into tabletop...should be dynamic // (haven't looked into it too deeply). Doublestrike 12-04-12 @@ -132,14 +112,14 @@ public class VField implements IVDoc { @Override public void mouseEntered(final MouseEvent e) { avatarArea.setOpaque(true); - if (!player.isHighlited()) + if (!isHighlited()) avatarArea.setBorder(borderAvatarHover); } @Override public void mouseExited(final MouseEvent e) { avatarArea.setOpaque(false); - if (!player.isHighlited()) + if (!isHighlited()) avatarArea.setBorder(borderAvatarSimple); } }); @@ -152,10 +132,8 @@ public class VField implements IVDoc { scroller.setOpaque(false); scroller.getViewport().setOpaque(false); scroller.setBorder(null); - - pnlDetails.setOpaque(false); - pnlDetails.setLayout(new MigLayout("insets 0, gap 0, wrap")); - populateDetails(); + + updateDetails(); } //========= Overridden methods @@ -171,7 +149,7 @@ public class VField implements IVDoc { pnl.add(avatarArea, "w 10%!, h 30%!"); pnl.add(phaseInidicator, "w 5%!, h 100%!, span 1 2"); pnl.add(scroller, "w 85%!, h 100%!, span 1 2, wrap"); - pnl.add(pnlDetails, "w 10%!, h 69%!, gapleft 1px"); + pnl.add(detailsPanel, "w 10%!, h 69%!, gapleft 1px"); } /* (non-Javadoc) @@ -217,114 +195,7 @@ public class VField implements IVDoc { //========= Populate helper methods - - /** Adds various labels to pool area JPanel container. */ - private void populateDetails() { - final JPanel row1 = new JPanel(new MigLayout("insets 0, gap 0")); - final JPanel row2 = new JPanel(new MigLayout("insets 0, gap 0")); - final JPanel row3 = new JPanel(new MigLayout("insets 0, gap 0")); - final JPanel row4 = new JPanel(new MigLayout("insets 0, gap 0")); - final JPanel row5 = new JPanel(new MigLayout("insets 0, gap 0")); - final JPanel row6 = new JPanel(new MigLayout("insets 0, gap 0")); - - row1.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); - row2.setOpaque(false); - row3.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); - row4.setOpaque(false); - row5.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); - row6.setOpaque(false); - - // Hand, library, graveyard, exile, flashback, poison labels - final String constraintsCell = "w 45%!, h 100%!, gap 0 5% 2px 2px"; - - row1.add(lblHand, constraintsCell); - row1.add(lblLibrary, constraintsCell); - - row2.add(lblGraveyard, constraintsCell); - row2.add(lblExile, constraintsCell); - - row3.add(lblFlashback, constraintsCell); - row3.add(lblPoison, constraintsCell); - - row4.add(manaLabels.get(0).getLeft(), constraintsCell); - row4.add(manaLabels.get(1).getLeft(), constraintsCell); - - row5.add(manaLabels.get(2).getLeft(), constraintsCell); - row5.add(manaLabels.get(3).getLeft(), constraintsCell); - - row6.add(manaLabels.get(4).getLeft(), constraintsCell); - row6.add(manaLabels.get(5).getLeft(), constraintsCell); - - final String constraintsRow = "w 100%!, h 16%!"; - pnlDetails.add(row1, constraintsRow + ", gap 0 0 4% 0"); - pnlDetails.add(row2, constraintsRow); - pnlDetails.add(row3, constraintsRow); - pnlDetails.add(row4, constraintsRow); - pnlDetails.add(row5, constraintsRow); - pnlDetails.add(row6, constraintsRow); - } - - private FLabel getBuiltFLabel(SkinProp p0, String s0, String s1) { - return new FLabel.Builder().icon(new ImageIcon(FSkin.getImage(p0))) - .opaque(false).fontSize(14) - .fontStyle(Font.BOLD).iconInBackground() - .text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT).build(); - } - // ========== Observer update methods - /** - * Handles observer update of player Zones - hand, graveyard, etc. - * - * @param p0   {@link forge.game.player.Player} - */ - public void updateZones(final Player p0) { - this.getLblHand().setText("" + p0.getZone(ZoneType.Hand).size()); - final String handMaxToolTip = p0.isUnlimitedHandSize() - ? "no maximum hand size" : String.valueOf(p0.getMaxHandSize()); - this.getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")"); - this.getLblGraveyard().setText("" + p0.getZone(ZoneType.Graveyard).size()); - this.getLblLibrary().setText("" + p0.getZone(ZoneType.Library).size()); - this.getLblFlashback().setText("" + p0.getCardsActivableInExternalZones().size()); - this.getLblExile().setText("" + p0.getZone(ZoneType.Exile).size()); - } - - /** - * Handles observer update of non-Zone details - life, poison, etc. Also - * updates "players" panel in tabber for this player. - * - * @param p0   {@link forge.game.player.Player} - */ - public void updateDetails(final Player p0) { - // "Players" panel update - CPlayers.SINGLETON_INSTANCE.update(); - - // Mana pool update - updateManaPool(p0); - - // Poison/life - this.getLblLife().setText("" + p0.getLife()); - this.getLblPoison().setText("" + p0.getPoisonCounters()); - - Color lifeFg = p0.getLife() <= 5 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT); - this.getLblLife().setForeground(lifeFg); - - Color poisonFg = p0.getPoisonCounters() >= 8 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT); - this.getLblPoison().setForeground(poisonFg); - - this.avatarArea.setBorder(p0.isHighlited() ? borderAvatarHighlited : borderAvatarSimple ); - this.avatarArea.setOpaque(p0.isHighlited()); - } - - /** - * Handles observer update of the mana pool. - * - * @param p0   {@link forge.game.player.Player} - */ - public void updateManaPool(final Player p0) { - ManaPool m = p0.getManaPool(); - for(Pair label : manaLabels) - label.getKey().setText(Integer.toString(m.getAmountOfColor(label.getRight()))); - } //========= Retrieval methods /** @@ -363,40 +234,6 @@ public class VField implements IVDoc { return this.lblLife; } - /** @return {@link javax.swing.JLabel} */ - public FLabel getLblHand() { - return this.lblHand; - } - - /** @return {@link javax.swing.JLabel} */ - public FLabel getLblLibrary() { - return this.lblLibrary; - } - - public final Iterable> getManaLabels() { - return manaLabels; - } - - /** @return {@link javax.swing.JLabel} */ - public JLabel getLblGraveyard() { - return this.lblGraveyard; - } - - /** @return {@link javax.swing.JLabel} */ - public JLabel getLblExile() { - return this.lblExile; - } - - /** @return {@link javax.swing.JLabel} */ - public JLabel getLblFlashback() { - return this.lblFlashback; - } - - /** @return {@link javax.swing.JLabel} */ - public JLabel getLblPoison() { - return this.lblPoison; - } - /** * TODO: Write javadoc for this method. * @return @@ -405,5 +242,32 @@ public class VField implements IVDoc { return phaseInidicator; } + /** + * @return the detailsPanel + */ + public PlayerDetailsPanel getDetailsPanel() { + return detailsPanel; + } + public boolean isHighlited() { + return CMatchUI.SINGLETON_INSTANCE.isHighlited(player); + } + + /** + * TODO: Write javadoc for this method. + * @param player2 + */ + public void updateDetails() { + detailsPanel.updateDetails(); + + this.getLblLife().setText("" + player.getLife()); + Color lifeFg = player.getLife() <= 5 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT); + this.getLblLife().setForeground(lifeFg); + + + boolean highlited = isHighlited(); + this.avatarArea.setBorder(highlited ? borderAvatarHighlited : borderAvatarSimple ); + this.avatarArea.setOpaque(highlited); + + } } diff --git a/src/main/java/forge/gui/match/views/VAntes.java b/src/main/java/forge/gui/match/views/VAntes.java index cfe4026350f..4a8476d6b32 100644 --- a/src/main/java/forge/gui/match/views/VAntes.java +++ b/src/main/java/forge/gui/match/views/VAntes.java @@ -18,8 +18,6 @@ package forge.gui.match.views; import java.awt.Dimension; -import java.util.Observable; -import java.util.Observer; import java.util.SortedSet; import java.util.TreeSet; @@ -45,7 +43,7 @@ import forge.gui.toolbox.FLabel; * *

(V at beginning of class name denotes a view class.) */ -public enum VAntes implements IVDoc, Observer { +public enum VAntes implements IVDoc { /** */ SINGLETON_INSTANCE; @@ -80,10 +78,7 @@ public enum VAntes implements IVDoc, Observer { public final void setModel(Iterable playerz) { players = playerz; - for(Player p: players) { - p.getZone(ZoneType.Ante).addObserver(this); - } - update(null, null); + update(); } /* (non-Javadoc) @@ -126,9 +121,7 @@ public enum VAntes implements IVDoc, Observer { return CAntes.SINGLETON_INSTANCE; } - //========== Setters / getters - @Override - public void update(Observable o, Object arg) { + public void update() { allAntes.clear(); pnl.removeAll(); diff --git a/src/main/java/forge/gui/match/views/VPlayers.java b/src/main/java/forge/gui/match/views/VPlayers.java index 000ebf7f7ac..5de66c195b8 100644 --- a/src/main/java/forge/gui/match/views/VPlayers.java +++ b/src/main/java/forge/gui/match/views/VPlayers.java @@ -143,7 +143,7 @@ public enum VPlayers implements IVDoc { /** @param p0 {@link forge.game.player.Player} */ public void update() { // No need to update if this panel isn't showing - if (!this.equals(parentCell.getSelected())) { return; } + if (parentCell == null || !this.equals(parentCell.getSelected())) { return; } for(Entry rr : infoLBLs.entrySet()) { Player p0 = rr.getKey(); diff --git a/src/main/java/forge/gui/toolbox/special/PlayerDetailsPanel.java b/src/main/java/forge/gui/toolbox/special/PlayerDetailsPanel.java new file mode 100644 index 00000000000..725ff41a9a3 --- /dev/null +++ b/src/main/java/forge/gui/toolbox/special/PlayerDetailsPanel.java @@ -0,0 +1,246 @@ +package forge.gui.toolbox.special; + +import java.awt.Color; +import java.awt.Font; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import net.miginfocom.swing.MigLayout; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.base.Function; + +import forge.Constant.Preferences; +import forge.card.MagicColor; +import forge.card.mana.ManaPool; +import forge.game.player.Player; +import forge.game.zone.ZoneType; +import forge.gui.ForgeAction; +import forge.gui.match.controllers.CPlayers; +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FSkin; +import forge.gui.toolbox.FSkin.SkinProp; + +/** + * TODO: Write javadoc for this type. + * + */ +public class PlayerDetailsPanel extends JPanel { + private static final long serialVersionUID = 8444559244193214459L; + + private Player player; + + // Info labels + private FLabel lblHand = getBuiltFLabel(FSkin.ZoneImages.ICO_HAND, "99", "Cards in hand"); + private FLabel lblGraveyard = getBuiltFLabel(FSkin.ZoneImages.ICO_GRAVEYARD, "99", "Cards in graveyard"); + private FLabel lblLibrary = getBuiltFLabel(FSkin.ZoneImages.ICO_LIBRARY, "99", "Cards in library"); + private FLabel lblExile = getBuiltFLabel(FSkin.ZoneImages.ICO_EXILE, "99", "Exiled cards"); + private FLabel lblFlashback = getBuiltFLabel(FSkin.ZoneImages.ICO_FLASHBACK, "99", "Flashback cards"); + private FLabel lblPoison = getBuiltFLabel(FSkin.ZoneImages.ICO_POISON, "99", "Poison counters"); + private final List> manaLabels = new ArrayList>(); + + private FLabel getBuiltFLabel(SkinProp p0, String s0, String s1) { + return new FLabel.Builder().icon(new ImageIcon(FSkin.getImage(p0))) + .opaque(false).fontSize(14) + .fontStyle(Font.BOLD).iconInBackground() + .text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT).build(); + } + + public PlayerDetailsPanel(Player player) { + + this.player = player; + + manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_BLACK, "99", "Black mana"), MagicColor.BLACK)); + manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_BLUE, "99", "Blue mana"), MagicColor.BLUE)); + manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_GREEN, "99", "Green mana"), MagicColor.GREEN)); + manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_RED, "99", "Red mana"), MagicColor.RED)); + manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_WHITE, "99", "White mana"), MagicColor.WHITE)); + manaLabels.add(Pair.of(getBuiltFLabel(FSkin.ManaImages.IMG_COLORLESS, "99", "Colorless mana"), (byte)0)); + + setOpaque(false); + setLayout(new MigLayout("insets 0, gap 0, wrap")); + populateDetails(); + + updateZones(); + updateManaPool(); + //updateDetails(); + } + + + + /** Adds various labels to pool area JPanel container. */ + private void populateDetails() { + final JPanel row1 = new JPanel(new MigLayout("insets 0, gap 0")); + final JPanel row2 = new JPanel(new MigLayout("insets 0, gap 0")); + final JPanel row3 = new JPanel(new MigLayout("insets 0, gap 0")); + final JPanel row4 = new JPanel(new MigLayout("insets 0, gap 0")); + final JPanel row5 = new JPanel(new MigLayout("insets 0, gap 0")); + final JPanel row6 = new JPanel(new MigLayout("insets 0, gap 0")); + + row1.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); + row2.setOpaque(false); + row3.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); + row4.setOpaque(false); + row5.setBackground(FSkin.getColor(FSkin.Colors.CLR_ZEBRA)); + row6.setOpaque(false); + + // Hand, library, graveyard, exile, flashback, poison labels + final String constraintsCell = "w 45%!, h 100%!, gap 0 5% 2px 2px"; + + row1.add(lblHand, constraintsCell); + row1.add(lblLibrary, constraintsCell); + + row2.add(lblGraveyard, constraintsCell); + row2.add(lblExile, constraintsCell); + + row3.add(lblFlashback, constraintsCell); + row3.add(lblPoison, constraintsCell); + + row4.add(manaLabels.get(0).getLeft(), constraintsCell); + row4.add(manaLabels.get(1).getLeft(), constraintsCell); + + row5.add(manaLabels.get(2).getLeft(), constraintsCell); + row5.add(manaLabels.get(3).getLeft(), constraintsCell); + + row6.add(manaLabels.get(4).getLeft(), constraintsCell); + row6.add(manaLabels.get(5).getLeft(), constraintsCell); + + final String constraintsRow = "w 100%!, h 16%!"; + this.add(row1, constraintsRow + ", gap 0 0 4% 0"); + this.add(row2, constraintsRow); + this.add(row3, constraintsRow); + this.add(row4, constraintsRow); + this.add(row5, constraintsRow); + this.add(row6, constraintsRow); + } + + /** + * Handles observer update of player Zones - hand, graveyard, etc. + * + * @param p0   {@link forge.game.player.Player} + */ + public void updateZones() { + this.getLblHand().setText("" + player.getZone(ZoneType.Hand).size()); + final String handMaxToolTip = player.isUnlimitedHandSize() + ? "no maximum hand size" : String.valueOf(player.getMaxHandSize()); + this.getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")"); + this.getLblGraveyard().setText("" + player.getZone(ZoneType.Graveyard).size()); + this.getLblLibrary().setText("" + player.getZone(ZoneType.Library).size()); + this.getLblFlashback().setText("" + player.getCardsActivableInExternalZones().size()); + this.getLblExile().setText("" + player.getZone(ZoneType.Exile).size()); + } + + + /** + * Handles observer update of non-Zone details - life, poison, etc. Also + * updates "players" panel in tabber for this player. + * + * @param p0   {@link forge.game.player.Player} + */ + public void updateDetails() { + // "Players" panel update + CPlayers.SINGLETON_INSTANCE.update(); + + // Poison/life + this.getLblPoison().setText("" + player.getPoisonCounters()); + Color poisonFg = player.getPoisonCounters() >= 8 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT); + this.getLblPoison().setForeground(poisonFg); + } + + /** + * Handles observer update of the mana pool. + * + * @param p0   {@link forge.game.player.Player} + */ + public void updateManaPool() { + ManaPool m = player.getManaPool(); + for(Pair label : manaLabels) + label.getKey().setText(Integer.toString(m.getAmountOfColor(label.getRight()))); + } + + + + /** @return {@link javax.swing.JLabel} */ + public FLabel getLblHand() { + return this.lblHand; + } + + /** @return {@link javax.swing.JLabel} */ + public FLabel getLblLibrary() { + return this.lblLibrary; + } + + public final Iterable> getManaLabels() { + return manaLabels; + } + + /** @return {@link javax.swing.JLabel} */ + public JLabel getLblGraveyard() { + return this.lblGraveyard; + } + + /** @return {@link javax.swing.JLabel} */ + public JLabel getLblExile() { + return this.lblExile; + } + + /** @return {@link javax.swing.JLabel} */ + public JLabel getLblFlashback() { + return this.lblFlashback; + } + + /** @return {@link javax.swing.JLabel} */ + public JLabel getLblPoison() { + return this.lblPoison; + } + + + + /** + * TODO: Write javadoc for this method. + * @param handAction + * @param libraryAction + * @param exileAction + * @param graveAction + * @param flashBackAction + * @param manaAction + */ + public void setupMouseActions(final ForgeAction handAction, final ForgeAction libraryAction, final ForgeAction exileAction, + final ForgeAction graveAction, final ForgeAction flashBackAction, final Function manaAction) { + + // Detail label listeners + lblGraveyard.setHoverable(true); + lblGraveyard.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { graveAction.actionPerformed(null); } } ); + + lblExile.setHoverable(true); + lblExile.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { exileAction.actionPerformed(null); } } ); + + if (Preferences.DEV_MODE) { + lblLibrary.setHoverable(true); + lblLibrary.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { libraryAction.actionPerformed(null); } } ); + } + + lblHand.setHoverable(true); + lblHand.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { handAction.actionPerformed(null); } } ); + + lblFlashback.setHoverable(true); + lblFlashback.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) {flashBackAction.actionPerformed(null); } } ); + + for(final Pair labelPair : getManaLabels()) { + labelPair.getLeft().setHoverable(true); + labelPair.getLeft().addMouseListener(new MouseAdapter() { @Override + public void mousePressed(final MouseEvent e) { + manaAction.apply(labelPair.getRight()); } } + ); + } + + } +} diff --git a/src/main/java/forge/sound/EventVisualizer.java b/src/main/java/forge/sound/EventVisualizer.java index 2f42a783bb7..ce42fe7365a 100644 --- a/src/main/java/forge/sound/EventVisualizer.java +++ b/src/main/java/forge/sound/EventVisualizer.java @@ -6,17 +6,16 @@ import forge.card.spellability.SpellAbility; import forge.game.event.GameEventCardChangeZone; import forge.game.event.GameEventCardDamaged; import forge.game.event.GameEventCardDestroyed; -import forge.game.event.GameEventCardEquipped; +import forge.game.event.GameEventCardAttachment; import forge.game.event.GameEventCardRegenerated; import forge.game.event.GameEventCardSacrificed; -import forge.game.event.GameEventCounterAdded; -import forge.game.event.GameEventCounterRemoved; +import forge.game.event.GameEventCardCounters; import forge.game.event.GameEventGameOutcome; import forge.game.event.GameEventTurnEnded; import forge.game.event.GameEvent; import forge.game.event.GameEventFlipCoin; import forge.game.event.GameEventLandPlayed; -import forge.game.event.GameEventLifeLoss; +import forge.game.event.GameEventPlayerLivesChanged; import forge.game.event.GameEventPlayerPoisoned; import forge.game.event.GameEventCardTapped; import forge.game.event.GameEventShuffle; @@ -33,7 +32,7 @@ public class EventVisualizer extends IGameEventVisitor.Base { public SoundEffectType visit(GameEventCardDamaged event) { return SoundEffectType.Damage; } public SoundEffectType visit(GameEventCardDestroyed event) { return SoundEffectType.Destroy; } - public SoundEffectType visit(GameEventCardEquipped event) { return SoundEffectType.Equip; } + public SoundEffectType visit(GameEventCardAttachment event) { return SoundEffectType.Equip; } public SoundEffectType visit(GameEventCardChangeZone event) { ZoneType from = event.from == null ? null : event.from.getZoneType(); ZoneType to = event.to.getZoneType(); @@ -46,11 +45,10 @@ public class EventVisualizer extends IGameEventVisitor.Base { } public SoundEffectType visit(GameEventCardRegenerated event) { return SoundEffectType.Regen; } public SoundEffectType visit(GameEventCardSacrificed event) { return SoundEffectType.Sacrifice; } - public SoundEffectType visit(GameEventCounterAdded event) { return event.Amount > 0 ? SoundEffectType.AddCounter : null; } - public SoundEffectType visit(GameEventCounterRemoved event) { return event.Amount > 0 ? SoundEffectType.RemoveCounter : null; } + public SoundEffectType visit(GameEventCardCounters event) { return event.newValue > event.oldValue ? SoundEffectType.AddCounter : event.newValue < event.oldValue ? SoundEffectType.RemoveCounter : null; } public SoundEffectType visit(GameEventTurnEnded event) { return SoundEffectType.EndOfTurn; } public SoundEffectType visit(GameEventFlipCoin event) { return SoundEffectType.FlipCoin; } - public SoundEffectType visit(GameEventLifeLoss event) { return SoundEffectType.LifeLoss; } + public SoundEffectType visit(GameEventPlayerLivesChanged event) { return SoundEffectType.LifeLoss; } public SoundEffectType visit(GameEventPlayerPoisoned event) { return SoundEffectType.Poison; } public SoundEffectType visit(GameEventShuffle event) { return SoundEffectType.Shuffle; } public SoundEffectType visit(GameEventTokenCreated event) { return SoundEffectType.Token; } diff --git a/src/main/java/forge/util/Lang.java b/src/main/java/forge/util/Lang.java index 2a8c4fd2a2f..1aba93bfd15 100644 --- a/src/main/java/forge/util/Lang.java +++ b/src/main/java/forge/util/Lang.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils; import com.google.common.base.Function; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; /** * TODO: Write javadoc for this type. @@ -37,6 +38,7 @@ public class Lang { return has1 ? (has2 ? s1 + " and " + s2 : s1) : (has2 ? s2 : ""); } + public static String joinHomogenous(Iterable objects) { return joinHomogenous(Lists.newArrayList(objects)); } public static String joinHomogenous(Collection objects) { return joinHomogenous(objects, null, "and"); } public static String joinHomogenous(Collection objects, Function accessor) { return joinHomogenous(objects, accessor, "and"); diff --git a/src/main/java/forge/util/MyObservable.java b/src/main/java/forge/util/MyObservable.java deleted file mode 100644 index 50fc96f4db4..00000000000 --- a/src/main/java/forge/util/MyObservable.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Forge: Play Magic: the Gathering. - * Copyright (C) 2011 Forge Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package forge.util; - -import java.util.Observable; - -/** - *

- * MyObservable class. - *

- * - * @author Forge - * @version $Id$ - */ -public class MyObservable extends Observable { - /** - *

- * updateObservers. - *

- */ - public final void updateObservers() { - this.setChanged(); - this.notifyObservers(); - } -} diff --git a/src/main/java/forge/view/arcane/CardPanel.java b/src/main/java/forge/view/arcane/CardPanel.java index 7bba322ba90..4ab36a9f3d0 100644 --- a/src/main/java/forge/view/arcane/CardPanel.java +++ b/src/main/java/forge/view/arcane/CardPanel.java @@ -44,6 +44,7 @@ import forge.card.CardEdition; import forge.card.mana.ManaCost; import forge.game.combat.Combat; import forge.gui.CardContainer; +import forge.gui.match.CMatchUI; import forge.gui.toolbox.CardFaceSymbols; import forge.properties.ForgePreferences.FPref; import forge.view.arcane.util.OutlinedLabel; @@ -321,7 +322,7 @@ public class CardPanel extends JPanel implements CardContainer { final int offset = this.isTapped() ? 1 : 0; // Magenta outline for when card was chosen to pay - if (this.getCard().isUsedToPay()) { + if (CMatchUI.SINGLETON_INSTANCE.isUsedToPay(this.getCard())) { g2d.setColor(Color.magenta); final int n2 = Math.max(1, Math.round(2 * this.cardWidth * CardPanel.SELECTED_BORDER_SIZE)); g2d.fillRoundRect(this.cardXOffset - n2, (this.cardYOffset - n2) + offset, this.cardWidth + (n2 * 2), this.cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2); @@ -424,7 +425,7 @@ public class CardPanel extends JPanel implements CardContainer { CardFaceSymbols.drawSymbol("phasing", g, stateXSymbols, ySymbols); } - if (card.isUsedToPay()) { + if (CMatchUI.SINGLETON_INSTANCE.isUsedToPay(card)) { CardFaceSymbols.drawSymbol("sacrifice", g, (this.cardXOffset + (this.cardWidth / 2)) - 20, (this.cardYOffset + (this.cardHeight / 2)) - 20); } diff --git a/src/main/java/forge/view/arcane/PlayArea.java b/src/main/java/forge/view/arcane/PlayArea.java index 1f33ead84be..33ad4c60a50 100644 --- a/src/main/java/forge/view/arcane/PlayArea.java +++ b/src/main/java/forge/view/arcane/PlayArea.java @@ -24,8 +24,6 @@ import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - import javax.swing.JScrollPane; import forge.Card; @@ -499,17 +497,9 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen * @param newList * an array of {@link forge.Card} objects. */ - private final AtomicBoolean wantRedraw = new AtomicBoolean(false); public void setupPlayZone() { - boolean wasSet = wantRedraw.getAndSet(true); - if(wasSet) return; - FThreads.delayInEDT(50, new Runnable() { // postpone play area update per 50ms - @Override - public void run() { - wantRedraw.set(false); - setupPlayZone(model); - } - }); + FThreads.assertExecutedByEdt(true); + setupPlayZone(model); }