diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
index 1eced8ee837..7f454e5269c 100644
--- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
+++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java
@@ -77,13 +77,14 @@ import static mage.constants.Constants.DEFAULT_AVATAR_ID;
import static mage.constants.Constants.MAX_AVATAR_ID;
import static mage.constants.Constants.MIN_AVATAR_ID;
import mage.constants.ManaType;
+import mage.counters.Counter;
+import mage.counters.CounterType;
import mage.remote.Session;
import mage.utils.timer.PriorityTimer;
+import mage.view.CardView;
import mage.view.ManaPoolView;
import mage.view.PlayerView;
import org.mage.card.arcane.ManaSymbols;
-import mage.players.Player;
-import mage.view.CardView;
/**
* Enhanced player pane.
@@ -191,7 +192,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
changedFontLife = false;
}
lifeLabel.setText(Integer.toString(playerLife));
- poisonLabel.setText(Integer.toString(player.getPoison()));
+ poisonLabel.setText(Integer.toString(player.getCounters().getCount(CounterType.POISON)));
handLabel.setText(Integer.toString(player.getHandCount()));
int libraryCards = player.getLibraryCount();
if (libraryCards > 99) {
@@ -330,9 +331,10 @@ public class PlayerPanelExt extends javax.swing.JPanel {
}
// Extend tooltip
StringBuilder tooltipText = new StringBuilder(basicTooltipText);
- if (player.getExperience() > 0) {
- tooltipText.append("
Experience counters: ").append(player.getExperience());
+ for (Counter counter : player.getCounters().values()) {
+ tooltipText.append("
").append(counter.getName()).append(" counters: ").append(counter.getCount());
}
+
avatar.setToolTipText(tooltipText.toString());
avatar.repaint();
diff --git a/Mage.Common/src/mage/view/PlayerView.java b/Mage.Common/src/mage/view/PlayerView.java
index 76b72d8fc18..d64d2cb41e5 100644
--- a/Mage.Common/src/mage/view/PlayerView.java
+++ b/Mage.Common/src/mage/view/PlayerView.java
@@ -36,7 +36,7 @@ import java.util.Map;
import java.util.UUID;
import mage.cards.Card;
import mage.constants.CardType;
-import mage.counters.CounterType;
+import mage.counters.Counters;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.GameState;
@@ -58,8 +58,7 @@ public class PlayerView implements Serializable {
private final UUID playerId;
private final String name;
private final int life;
- private final int poison;
- private final int experience;
+ private final Counters counters;
private final int wins;
private final int winsNeeded;
private final long deckHashCode;
@@ -90,8 +89,7 @@ public class PlayerView implements Serializable {
this.playerId = player.getId();
this.name = player.getName();
this.life = player.getLife();
- this.poison = player.getCounters().getCount(CounterType.POISON);
- this.experience = player.getCounters().getCount(CounterType.EXPERIENCE);
+ this.counters = player.getCounters();
this.wins = player.getMatchPlayer().getWins();
this.winsNeeded = player.getMatchPlayer().getWinsNeeded();
// If match ended immediately before, deck can be set to null so check is necessarry here
@@ -195,12 +193,8 @@ public class PlayerView implements Serializable {
return this.life;
}
- public int getPoison() {
- return this.poison;
- }
-
- public int getExperience() {
- return this.experience;
+ public Counters getCounters() {
+ return this.counters;
}
public int getLibraryCount() {
diff --git a/Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java b/Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java
new file mode 100644
index 00000000000..5428d34b7b3
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/kaladesh/WoodweaversPuzzleknot.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.sets.kaladesh;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.SacrificeSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect;
+import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
+import mage.constants.Zone;
+
+/**
+ *
+ * @author emerald000
+ */
+public class WoodweaversPuzzleknot extends CardImpl {
+
+ public WoodweaversPuzzleknot(UUID ownerId) {
+ super(ownerId, 240, "Woodweaver's Puzzleknot", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}");
+ this.expansionSetCode = "KLD";
+
+ // When Woodweaver's Puzzleknot enters the battlefield, you gain 3 life and get {E}{E}{E}.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3));
+ Effect effect = new GetEnergyCountersControllerEffect(3);
+ effect.setText("and get {E}{E}{E}");
+ ability.addEffect(effect);
+ this.addAbility(ability);
+
+ // {2}{G}, Sacrifice Woodweaver's Puzzleknot: You gain 3 life and get {E}{E}{E}.
+ ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(3), new ManaCostsImpl<>("{2}{G}"));
+ ability.addCost(new SacrificeSourceCost());
+ ability.addEffect(effect);
+ this.addAbility(ability);
+ }
+
+ public WoodweaversPuzzleknot(final WoodweaversPuzzleknot card) {
+ super(card);
+ }
+
+ @Override
+ public WoodweaversPuzzleknot copy() {
+ return new WoodweaversPuzzleknot(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java
new file mode 100644
index 00000000000..faa2598939b
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.abilities.effects.common.counter;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.constants.Outcome;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.players.Player;
+import mage.util.CardUtil;
+
+/**
+ * @author emerald000
+ */
+public class GetEnergyCountersControllerEffect extends OneShotEffect {
+
+ private final int value;
+
+ public GetEnergyCountersControllerEffect(int value) {
+ super(Outcome.Benefit);
+ this.value = value;
+ setText();
+ }
+
+ public GetEnergyCountersControllerEffect(final GetEnergyCountersControllerEffect effect) {
+ super(effect);
+ this.value = effect.value;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player != null) {
+ return player.addCounters(CounterType.ENERGY.createInstance(value), game);
+ }
+ return false;
+ }
+
+ private void setText() {
+ this.staticText = "you get ";
+ for (int i = 0; i < value; i++) {
+ this.staticText += "{E}";
+ }
+ this.staticText += " (" + CardUtil.numberToText(value, "an") + " energy counter" + (value > 1 ? "s" : "") + ")";
+ }
+
+ @Override
+ public GetEnergyCountersControllerEffect copy() {
+ return new GetEnergyCountersControllerEffect(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java
index 4d41db4ee0c..6e1817559e4 100644
--- a/Mage/src/main/java/mage/counters/CounterType.java
+++ b/Mage/src/main/java/mage/counters/CounterType.java
@@ -54,6 +54,7 @@ public enum CounterType {
DIVINITY("divinity"),
DOOM("doom"),
ELIXIR("elixir"),
+ ENERGY("energy"),
EON("eon"),
EXPERIENCE("experience"),
EYEBALL("eyeball"),