diff --git a/Mage/src/mage/Mana.java b/Mage/src/mage/Mana.java index cfce6a295f0..5708e081e5b 100644 --- a/Mage/src/mage/Mana.java +++ b/Mage/src/mage/Mana.java @@ -33,6 +33,7 @@ import mage.constants.ColoredManaSymbol; import mage.constants.ManaType; import mage.filter.FilterMana; import mage.util.Copyable; +import mage.util.ThreadLocalStringBuilder; /** * @@ -258,7 +259,7 @@ public class Mana implements Comparable, Serializable, Copyable { @Override public String toString() { - StringBuilder sbMana = new StringBuilder(); + StringBuilder sbMana = threadLocalBuilder.get(); if (colorless > 0) { sbMana.append("{").append(Integer.toString(colorless)).append("}"); } @@ -282,7 +283,9 @@ public class Mana implements Comparable, Serializable, Copyable { } return sbMana.toString(); } - + + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(10); + @Override public Mana copy() { return new Mana(this); diff --git a/Mage/src/mage/ObjectColor.java b/Mage/src/mage/ObjectColor.java index ed7903f7b4d..a1851065ccc 100644 --- a/Mage/src/mage/ObjectColor.java +++ b/Mage/src/mage/ObjectColor.java @@ -32,9 +32,12 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; import mage.util.Copyable; +import mage.util.ThreadLocalStringBuilder; public class ObjectColor implements Serializable, Copyable, Comparable { + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(10); + public static final ObjectColor WHITE = new ObjectColor("W"); public static final ObjectColor BLUE = new ObjectColor("U"); public static final ObjectColor BLACK = new ObjectColor("B"); @@ -184,7 +187,7 @@ public class ObjectColor implements Serializable, Copyable, Compara @Override public String toString() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = threadLocalBuilder.get(); if (white) { sb.append("W"); } diff --git a/Mage/src/mage/abilities/AbilitiesImpl.java b/Mage/src/mage/abilities/AbilitiesImpl.java index fb34ffa59ee..3e3b4d7ebd1 100644 --- a/Mage/src/mage/abilities/AbilitiesImpl.java +++ b/Mage/src/mage/abilities/AbilitiesImpl.java @@ -41,6 +41,7 @@ import mage.abilities.keyword.ProtectionAbility; import mage.abilities.mana.ManaAbility; import mage.constants.Zone; import mage.game.Game; +import mage.util.ThreadLocalStringBuilder; /** * @@ -49,6 +50,8 @@ import mage.game.Game; */ public class AbilitiesImpl extends ArrayList implements Abilities { + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(200); + public AbilitiesImpl() {} public AbilitiesImpl(T... abilities) { @@ -88,7 +91,7 @@ public class AbilitiesImpl extends ArrayList implements Ab } if (ability instanceof SpellAbility) { if (ability.getAlternativeCosts().size() > 0) { - StringBuilder sbRule = new StringBuilder(); + StringBuilder sbRule = threadLocalBuilder.get(); for (AlternativeCost cost: ability.getAlternativeCosts()) { if (cost.getClass().getName().equals("mage.abilities.costs.AlternativeCostImpl")) { // if the template class is used, the rule is in the getName() instead in the getText() @@ -102,7 +105,7 @@ public class AbilitiesImpl extends ArrayList implements Ab rules.add(sbRule.toString()); } if (ability.getAdditionalCostsRuleVisible() && ability.getCosts().size() > 0) { - StringBuilder sbRule = new StringBuilder(); + StringBuilder sbRule = threadLocalBuilder.get(); for (Cost cost: ability.getCosts()) { if (cost.getText() != null && !cost.getText().isEmpty()) { if (!cost.getText().startsWith("As an additional cost")) { @@ -339,7 +342,7 @@ public class AbilitiesImpl extends ArrayList implements Ab } } Collections.sort(abilities); - StringBuilder sb = new StringBuilder(); + StringBuilder sb = threadLocalBuilder.get(); for (String s: abilities) { sb.append(s); } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index deb14f6475c..1cad9c0a08d 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -74,6 +74,7 @@ import mage.game.stack.StackAbility; import mage.players.Player; import mage.target.Target; import mage.target.Targets; +import mage.util.ThreadLocalStringBuilder; import mage.watchers.Watcher; import org.apache.log4j.Logger; @@ -84,6 +85,7 @@ import org.apache.log4j.Logger; public abstract class AbilityImpl implements Ability { private static final transient Logger logger = Logger.getLogger(AbilityImpl.class); + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(100); private static final List emptyWatchers = new ArrayList<>(); private static final List emptyAbilities = new ArrayList<>(); @@ -519,7 +521,7 @@ public abstract class AbilityImpl implements Ability { if (!noMana) { xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), "Announce the value for " + variableManaCost.getText(), game, this); int amountMana = xValue * variableManaCost.getMultiplier(); - StringBuilder manaString = new StringBuilder(); + StringBuilder manaString = threadLocalBuilder.get(); if (variableManaCost.getFilter() == null || variableManaCost.getFilter().isColorless()) { manaString.append("{").append(amountMana).append("}"); } else { @@ -727,7 +729,7 @@ public abstract class AbilityImpl implements Ability { @Override public String getRule(boolean all) { - StringBuilder sbRule = new StringBuilder(); + StringBuilder sbRule = threadLocalBuilder.get(); if (all || this.abilityType != AbilityType.SPELL) { if (manaCosts.size() > 0) { sbRule.append(manaCosts.getText()); @@ -989,7 +991,7 @@ public abstract class AbilityImpl implements Ability { } protected String getMessageText(Game game) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = threadLocalBuilder.get(); MageObject object = game.getObject(this.sourceId); if (object != null) { if (object instanceof StackAbility) { @@ -1072,7 +1074,7 @@ public abstract class AbilityImpl implements Ability { } protected String getTargetDescriptionForLog(Targets targets, Game game) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = threadLocalBuilder.get(); if (targets.size() > 0) { String usedVerb = null; for (Target target : targets) { @@ -1097,7 +1099,7 @@ public abstract class AbilityImpl implements Ability { } private String getOptionalTextSuffix(Game game, Spell spell) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = threadLocalBuilder.get(); for (Ability ability : spell.getAbilities()) { if (ability instanceof OptionalAdditionalSourceCosts) { sb.append(((OptionalAdditionalSourceCosts) ability).getCastMessageSuffix()); diff --git a/Mage/src/mage/cards/Cards.java b/Mage/src/mage/cards/Cards.java index 5950de99994..fffc342824a 100644 --- a/Mage/src/mage/cards/Cards.java +++ b/Mage/src/mage/cards/Cards.java @@ -46,6 +46,7 @@ public interface Cards extends Set, Serializable { Set getCards(Game game); Set getCards(FilterCard filter, Game game); Set getCards(FilterCard filter, UUID sourceId, UUID playerId, Game game); + String getValue(Game game); Collection getUniqueCards(Game game); Card getRandom(Game game); int count(FilterCard filter, Game game); diff --git a/Mage/src/mage/cards/CardsImpl.java b/Mage/src/mage/cards/CardsImpl.java index 2bb5c2f0e61..da4c1deebbc 100644 --- a/Mage/src/mage/cards/CardsImpl.java +++ b/Mage/src/mage/cards/CardsImpl.java @@ -36,11 +36,14 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.UUID; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; +import mage.util.ThreadLocalStringBuilder; import org.apache.log4j.Logger; @@ -51,6 +54,7 @@ import org.apache.log4j.Logger; public class CardsImpl extends LinkedHashSet implements Cards, Serializable { private static final Logger logger = Logger.getLogger(CardsImpl.class); + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(200); private static Random rnd = new Random(); private UUID ownerId; @@ -207,6 +211,20 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl return cards; } + @Override + public String getValue(Game game) { + StringBuilder sb = threadLocalBuilder.get(); + SortedSet cards = new TreeSet<>(); + for (UUID cardId: this) { + Card card = game.getCard(cardId); + cards.add(card.getName()); + } + for (String name: cards) { + sb.append(name).append(":"); + } + return sb.toString(); + } + @Override public void addAll(List cards) { for (Card card: cards) { diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 3d6b41513b1..c7684a38f23 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -58,6 +58,7 @@ import mage.watchers.Watchers; import java.io.Serializable; import java.util.*; +import mage.util.ThreadLocalStringBuilder; /** * @@ -71,6 +72,9 @@ import java.util.*; */ public class GameState implements Serializable, Copyable { + + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(1024); + private final Players players; private final PlayerList playerList; private final Turn turn; @@ -222,17 +226,15 @@ public class GameState implements Serializable, Copyable { for (Player player: players.values()) { sb.append("player").append(player.isPassed()).append(player.getLife()).append("hand"); - if (useHidden) { - sb.append(player.getHand()); + if (useHidden && priorityPlayerId == player.getId()) { + sb.append(player.getHand().getValue(game)); } else { sb.append(player.getHand().size()); } sb.append("library").append(player.getLibrary().size()); sb.append("graveyard"); - for (Card card: player.getGraveyard().getCards(game)) { - sb.append(card.getName()); - } + sb.append(player.getGraveyard().getValue(game)); } sb.append("permanents"); @@ -264,7 +266,7 @@ public class GameState implements Serializable, Copyable { } for (ExileZone zone: exile.getExileZones()) { - sb.append("exile").append(zone.getName()).append(zone); + sb.append("exile").append(zone.getName()).append(zone.getValue(game)); } sb.append("combat"); @@ -275,22 +277,6 @@ public class GameState implements Serializable, Copyable { return sb.toString(); } - // create a ThreadLocal StringBuilder - private transient ThreadLocal threadLocalBuilder = new ThreadLocal() { - @Override - protected StringBuilder initialValue() { - return new StringBuilder(1024); - } - - @Override - public StringBuilder get() { - StringBuilder b = super.get(); - b.setLength(0); // clear/reset the buffer - return b; - } - - }; - public Players getPlayers() { return players; } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index 95f63a57ffc..8cd2141f522 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -76,12 +76,15 @@ import mage.game.events.GameEvent.EventType; import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; +import mage.util.ThreadLocalStringBuilder; /** * @author BetaSteward_at_googlemail.com */ public abstract class PermanentImpl extends CardImpl implements Permanent { + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(300); + protected boolean tapped; protected boolean flipped; protected boolean transformed; @@ -179,8 +182,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public String toString() { - StringBuilder sb = new StringBuilder(this.name); - sb.append("-").append(this.expansionSetCode); + StringBuilder sb = threadLocalBuilder.get(); + sb.append(this.name).append("-").append(this.expansionSetCode); if (copy) { sb.append(" [Copy]"); } @@ -209,7 +212,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public String getValue() { - StringBuilder sb = new StringBuilder(1024); + StringBuilder sb = threadLocalBuilder.get(); sb.append(controllerId).append(name).append(tapped).append(damage); sb.append(subtype).append(supertype).append(power.getValue()).append(toughness.getValue()); sb.append(abilities.getValue()); diff --git a/Mage/src/mage/game/turn/Turn.java b/Mage/src/mage/game/turn/Turn.java index 02fe4ea672e..b622a6de47a 100644 --- a/Mage/src/mage/game/turn/Turn.java +++ b/Mage/src/mage/game/turn/Turn.java @@ -41,6 +41,7 @@ import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; +import mage.util.ThreadLocalStringBuilder; /** * @@ -48,6 +49,8 @@ import mage.players.Player; */ public class Turn implements Serializable { + private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(50); + private Phase currentPhase; private UUID activePlayerId; private final List phases = new ArrayList<>(); @@ -322,20 +325,4 @@ public class Turn implements Serializable { return sb.toString(); } - // create a ThreadLocal StringBuilder - private transient ThreadLocal threadLocalBuilder = new ThreadLocal() { - @Override - protected StringBuilder initialValue() { - return new StringBuilder(50); - } - - @Override - public StringBuilder get() { - StringBuilder b = super.get(); - b.setLength(0); // clear/reset the buffer - return b; - } - - }; - } diff --git a/Mage/src/mage/util/ThreadLocalStringBuilder.java b/Mage/src/mage/util/ThreadLocalStringBuilder.java new file mode 100644 index 00000000000..bfa102d83f7 --- /dev/null +++ b/Mage/src/mage/util/ThreadLocalStringBuilder.java @@ -0,0 +1,27 @@ +package mage.util; + +/** + * + * @author BetaSteward + */ +public class ThreadLocalStringBuilder extends ThreadLocal { + + private int size; + + public ThreadLocalStringBuilder(int size) { + this.size = size; + } + + @Override + protected StringBuilder initialValue() { + return new StringBuilder(size); + } + + @Override + public StringBuilder get() { + StringBuilder b = super.get(); + b.setLength(0); // clear/reset the buffer + return b; + } + +}