mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 21:42:07 -08:00
* Performance: memory usage optimization for deck editor (part 2 of removed bloated usage of ManaCosts -> ManaColor objects, see #7515);
This commit is contained in:
parent
c1dea5b21e
commit
10e557b873
25 changed files with 164 additions and 113 deletions
|
|
@ -88,6 +88,14 @@ public interface MageObject extends MageItem, Serializable {
|
|||
|
||||
ManaCosts<ManaCost> getManaCost();
|
||||
|
||||
default List<String> getManaCostSymbols() {
|
||||
List<String> symbols = new ArrayList<>();
|
||||
for (ManaCost cost : getManaCost()) {
|
||||
symbols.add(cost.getText());
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
|
||||
int getConvertedManaCost();
|
||||
|
||||
MageInt getPower();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import mage.target.targetadjustment.TargetAdjuster;
|
|||
import mage.watchers.Watcher;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageIdentifier;
|
||||
|
|
@ -123,6 +124,14 @@ public interface Ability extends Controllable, Serializable {
|
|||
*/
|
||||
ManaCosts<ManaCost> getManaCosts();
|
||||
|
||||
default List<String> getManaCostSymbols() {
|
||||
List<String> symbols = new ArrayList<>();
|
||||
for (ManaCost cost : getManaCosts()) {
|
||||
symbols.add(cost.getText());
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the {@link ManaCosts} that must be paid before activating this
|
||||
* ability. These costs should be modified by any modification effects
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ public interface ManaCosts<T extends ManaCost> extends List<T>, ManaCost {
|
|||
*/
|
||||
void load(String mana, boolean extractMonoHybridGenericValue);
|
||||
|
||||
List<String> getSymbols();
|
||||
|
||||
boolean payOrRollback(Ability ability, Game game, Ability source, UUID payingPlayerId);
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -505,15 +505,6 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSymbols() {
|
||||
List<String> symbols = new ArrayList<>();
|
||||
for (ManaCost cost : this) {
|
||||
symbols.add(cost.getText());
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return this.id;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,7 @@ public class SpellCostReductionForEachSourceEffect extends CostModificationEffec
|
|||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("this spell costs ");
|
||||
for (String manaSymbol : reduceManaCosts.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(reduceManaCosts.getText());
|
||||
sb.append(" less to cast for each ").append(this.eachAmount.getMessage());
|
||||
this.staticText = sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@ public class SpellCostReductionSourceEffect extends CostModificationEffectImpl {
|
|||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("this spell costs ");
|
||||
for (String manaSymbol : manaCostsToReduce.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(manaCostsToReduce.getText());
|
||||
sb.append(" less to cast");
|
||||
if (this.condition != null) {
|
||||
sb.append(" if ").append(this.condition.toString());
|
||||
|
|
|
|||
|
|
@ -63,9 +63,7 @@ public class SpellsCostIncreasingAllEffect extends CostModificationEffectImpl {
|
|||
|
||||
sb.append(" cost ");
|
||||
if (this.increaseManaCosts != null) {
|
||||
for (String manaSymbol : this.increaseManaCosts.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(this.increaseManaCosts.getText());
|
||||
} else {
|
||||
sb.append("{").append(increaseGenericCost).append("}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ public class SpellsCostReductionControllerEffect extends CostModificationEffectI
|
|||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(filter.getMessage()).append(" you cast cost ");
|
||||
for (String manaSymbol : manaCostsToReduce.getSymbols()) {
|
||||
sb.append(manaSymbol);
|
||||
}
|
||||
sb.append(manaCostsToReduce.getText());
|
||||
sb.append(" less to cast. This effect reduces only the amount of colored mana you pay.");
|
||||
this.staticText = sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.ModalDoubleFacesCard;
|
||||
import mage.cards.repository.CardInfo;
|
||||
|
|
@ -35,6 +34,7 @@ public class MockCard extends CardImpl {
|
|||
protected List<String> manaCostStr;
|
||||
protected String adventureSpellName;
|
||||
protected boolean isModalDoubleFacesCard;
|
||||
protected int convertedManaCost;
|
||||
|
||||
public MockCard(CardInfo card) {
|
||||
super(null, card.getName());
|
||||
|
|
@ -49,10 +49,11 @@ public class MockCard extends CardImpl {
|
|||
|
||||
this.usesVariousArt = card.usesVariousArt();
|
||||
|
||||
this.manaCost = new ManaCostsImpl(join(card.getManaCosts(CardInfo.ManaCostSide.ALL)));
|
||||
//this.manaCost = new ManaCostsImpl(join(card.getManaCosts(CardInfo.ManaCostSide.ALL)));
|
||||
this.manaCostLeftStr = card.getManaCosts(CardInfo.ManaCostSide.LEFT);
|
||||
this.manaCostRightStr = card.getManaCosts(CardInfo.ManaCostSide.RIGHT);
|
||||
this.manaCostStr = card.getManaCosts(CardInfo.ManaCostSide.ALL);
|
||||
this.convertedManaCost = card.getConvertedManaCost();
|
||||
|
||||
this.color = card.getColor();
|
||||
|
||||
|
|
@ -112,21 +113,20 @@ public class MockCard extends CardImpl {
|
|||
|
||||
@Override
|
||||
public ManaCosts<ManaCost> getManaCost() {
|
||||
return manaCost;
|
||||
// only split half cards can store mana cost in objects list instead strings (memory optimization)
|
||||
// see https://github.com/magefree/mage/issues/7515
|
||||
throw new IllegalArgumentException("Unsupport method call: getManaCost in " + this.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
/*
|
||||
private ManaCosts<ManaCost> getManaCost(CardInfo.ManaCostSide manaCostSide) {
|
||||
switch (manaCostSide) {
|
||||
case LEFT:
|
||||
return manaCostLeft;
|
||||
case RIGHT:
|
||||
return manaCostRight;
|
||||
default:
|
||||
case ALL:
|
||||
return manaCost;
|
||||
}
|
||||
}*/
|
||||
@Override
|
||||
public List<String> getManaCostSymbols() {
|
||||
return getManaCostStr(CardInfo.ManaCostSide.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConvertedManaCost() {
|
||||
return this.convertedManaCost;
|
||||
}
|
||||
|
||||
public List<String> getManaCostStr(CardInfo.ManaCostSide manaCostSide) {
|
||||
switch (manaCostSide) {
|
||||
|
|
@ -164,14 +164,6 @@ public class MockCard extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
private String join(List<String> strings) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String string : strings) {
|
||||
sb.append(string);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Ability textAbilityFromString(final String text) {
|
||||
return new MockAbility(text);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
|
||||
package mage.cards.mock;
|
||||
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.SplitCardHalf;
|
||||
import mage.cards.repository.CardInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
|
@ -12,9 +18,13 @@ import mage.cards.repository.CardInfo;
|
|||
public class MockSplitCardHalf extends MockCard implements SplitCardHalf {
|
||||
|
||||
private SplitCard splitCardParent;
|
||||
private ManaCosts<ManaCost> manaCosts;
|
||||
private List<String> manaCostsSymbols;
|
||||
|
||||
public MockSplitCardHalf(CardInfo card) {
|
||||
super(card);
|
||||
this.manaCostsSymbols = card.getManaCosts(CardInfo.ManaCostSide.ALL);
|
||||
this.manaCosts = new ManaCostsImpl<>(String.join("", this.manaCostsSymbols));
|
||||
}
|
||||
|
||||
public MockSplitCardHalf(final MockSplitCardHalf card) {
|
||||
|
|
@ -36,4 +46,15 @@ public class MockSplitCardHalf extends MockCard implements SplitCardHalf {
|
|||
return splitCardParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaCosts<ManaCost> getManaCost() {
|
||||
// only split half cards can store mana cost in objects list instead strings (memory optimization)
|
||||
return manaCosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getManaCostSymbols() {
|
||||
// only split half cards can store mana cost in objects list instead strings (memory optimization)
|
||||
return manaCostsSymbols;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,19 +167,19 @@ public class CardInfo {
|
|||
|
||||
// mana cost can contains multiple cards (split left/right, modal double faces, card/adventure)
|
||||
if (card instanceof SplitCard) {
|
||||
List<String> manaCostLeft = ((SplitCard) card).getLeftHalfCard().getManaCost().getSymbols();
|
||||
List<String> manaCostRight = ((SplitCard) card).getRightHalfCard().getManaCost().getSymbols();
|
||||
List<String> manaCostLeft = ((SplitCard) card).getLeftHalfCard().getManaCostSymbols();
|
||||
List<String> manaCostRight = ((SplitCard) card).getRightHalfCard().getManaCostSymbols();
|
||||
this.setManaCosts(CardUtil.concatManaSymbols(SPLIT_MANA_SEPARATOR_FULL, manaCostLeft, manaCostRight));
|
||||
} else if (card instanceof ModalDoubleFacesCard) {
|
||||
List<String> manaCostLeft = ((ModalDoubleFacesCard) card).getLeftHalfCard().getManaCost().getSymbols();
|
||||
List<String> manaCostRight = ((ModalDoubleFacesCard) card).getRightHalfCard().getManaCost().getSymbols();
|
||||
List<String> manaCostLeft = ((ModalDoubleFacesCard) card).getLeftHalfCard().getManaCostSymbols();
|
||||
List<String> manaCostRight = ((ModalDoubleFacesCard) card).getRightHalfCard().getManaCostSymbols();
|
||||
this.setManaCosts(CardUtil.concatManaSymbols(SPLIT_MANA_SEPARATOR_FULL, manaCostLeft, manaCostRight));
|
||||
} else if (card instanceof AdventureCard) {
|
||||
List<String> manaCostLeft = ((AdventureCard) card).getSpellCard().getManaCost().getSymbols();
|
||||
List<String> manaCostRight = card.getManaCost().getSymbols();
|
||||
List<String> manaCostLeft = ((AdventureCard) card).getSpellCard().getManaCostSymbols();
|
||||
List<String> manaCostRight = card.getManaCostSymbols();
|
||||
this.setManaCosts(CardUtil.concatManaSymbols(SPLIT_MANA_SEPARATOR_FULL, manaCostLeft, manaCostRight));
|
||||
} else {
|
||||
this.setManaCosts(card.getManaCost().getSymbols());
|
||||
this.setManaCosts(card.getManaCostSymbols());
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
|
|
|
|||
|
|
@ -317,10 +317,10 @@ public final class RateCard {
|
|||
* @return
|
||||
*/
|
||||
private static int getManaCostScore(Card card, List<ColoredManaSymbol> allowedColors) {
|
||||
int converted = card.getManaCost().convertedManaCost();
|
||||
int converted = card.getConvertedManaCost();
|
||||
if (allowedColors == null) {
|
||||
int colorPenalty = 0;
|
||||
for (String symbol : card.getManaCost().getSymbols()) {
|
||||
for (String symbol : card.getManaCostSymbols()) {
|
||||
if (isColoredMana(symbol)) {
|
||||
colorPenalty++;
|
||||
}
|
||||
|
|
@ -329,7 +329,7 @@ public final class RateCard {
|
|||
}
|
||||
final Map<String, Integer> singleCount = new HashMap<>();
|
||||
int maxSingleCount = 0;
|
||||
for (String symbol : card.getManaCost().getSymbols()) {
|
||||
for (String symbol : card.getManaCostSymbols()) {
|
||||
int count = 0;
|
||||
symbol = symbol.replace("{", "").replace("}", "");
|
||||
if (isColoredMana(symbol)) {
|
||||
|
|
@ -385,7 +385,7 @@ public final class RateCard {
|
|||
*/
|
||||
public static int getColorManaCount(Card card) {
|
||||
int count = 0;
|
||||
for (String symbol : card.getManaCost().getSymbols()) {
|
||||
for (String symbol : card.getManaCostSymbols()) {
|
||||
if (isColoredMana(symbol)) {
|
||||
count++;
|
||||
}
|
||||
|
|
@ -401,7 +401,7 @@ public final class RateCard {
|
|||
*/
|
||||
public static int getDifferentColorManaCount(Card card) {
|
||||
Set<String> symbols = new HashSet<>();
|
||||
for (String symbol : card.getManaCost().getSymbols()) {
|
||||
for (String symbol : card.getManaCostSymbols()) {
|
||||
if (isColoredMana(symbol)) {
|
||||
symbols.add(symbol);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package mage.game.stack;
|
||||
|
||||
import mage.MageIdentifier;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.*;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
|
|
@ -222,6 +219,11 @@ public class StackAbility extends StackObjImpl implements Ability {
|
|||
return emptyCost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getManaCostSymbols() {
|
||||
return super.getManaCostSymbols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageInt getPower() {
|
||||
return MageInt.EmptyMageInt;
|
||||
|
|
|
|||
|
|
@ -133,29 +133,37 @@ public final class CardUtil {
|
|||
}
|
||||
|
||||
private static ManaCosts<ManaCost> adjustCost(ManaCosts<ManaCost> manaCosts, int reduceCount) {
|
||||
ManaCosts<ManaCost> adjustedCost = new ManaCostsImpl<>();
|
||||
ManaCosts<ManaCost> newCost = new ManaCostsImpl<>();
|
||||
|
||||
// nothing to change
|
||||
if (reduceCount == 0) {
|
||||
for (ManaCost manaCost : manaCosts) {
|
||||
adjustedCost.add(manaCost.copy());
|
||||
newCost.add(manaCost.copy());
|
||||
}
|
||||
return adjustedCost;
|
||||
return newCost;
|
||||
}
|
||||
|
||||
// keep same order for costs
|
||||
Map<ManaCost, ManaCost> changedCost = new LinkedHashMap<>(); // must be ordered
|
||||
List<ManaCost> addedCost = new ArrayList<>();
|
||||
manaCosts.forEach(manaCost -> {
|
||||
changedCost.put(manaCost, manaCost);
|
||||
});
|
||||
|
||||
// remove or save cost
|
||||
if (reduceCount > 0) {
|
||||
int restToReduce = reduceCount;
|
||||
|
||||
// first run - priority for single option costs (generic)
|
||||
for (ManaCost manaCost : manaCosts) {
|
||||
|
||||
// ignore snow mana
|
||||
if (manaCost instanceof SnowManaCost) {
|
||||
adjustedCost.add(manaCost);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore unknown mana
|
||||
if (manaCost.getOptions().size() == 0) {
|
||||
adjustedCost.add(manaCost);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -171,15 +179,15 @@ public final class CardUtil {
|
|||
if ((colorless - restToReduce) > 0) {
|
||||
// partly reduce
|
||||
int newColorless = colorless - restToReduce;
|
||||
adjustedCost.add(new GenericManaCost(newColorless));
|
||||
changedCost.put(manaCost, new GenericManaCost(newColorless));
|
||||
restToReduce = 0;
|
||||
} else {
|
||||
// full reduce - ignore cost
|
||||
changedCost.put(manaCost, null);
|
||||
restToReduce -= colorless;
|
||||
}
|
||||
} else {
|
||||
// nothing to reduce
|
||||
adjustedCost.add(manaCost.copy());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,22 +211,21 @@ public final class CardUtil {
|
|||
if ((colorless - restToReduce) > 0) {
|
||||
// partly reduce
|
||||
int newColorless = colorless - restToReduce;
|
||||
adjustedCost.add(new MonoHybridManaCost(mono.getManaColor(), newColorless));
|
||||
changedCost.put(manaCost, new MonoHybridManaCost(mono.getManaColor(), newColorless));
|
||||
restToReduce = 0;
|
||||
} else {
|
||||
// full reduce
|
||||
adjustedCost.add(new MonoHybridManaCost(mono.getManaColor(), 0));
|
||||
changedCost.put(manaCost, new MonoHybridManaCost(mono.getManaColor(), 0));
|
||||
restToReduce -= colorless;
|
||||
}
|
||||
} else {
|
||||
// nothing to reduce
|
||||
adjustedCost.add(mono.copy());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// unsupported multi-option mana types for reduce (like HybridManaCost)
|
||||
adjustedCost.add(manaCost.copy());
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,23 +233,39 @@ public final class CardUtil {
|
|||
if (reduceCount < 0) {
|
||||
boolean added = false;
|
||||
for (ManaCost manaCost : manaCosts) {
|
||||
// ignore already reduced cost (add new cost to the start)
|
||||
if (changedCost.get(manaCost) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add to existing cost
|
||||
if (reduceCount != 0 && manaCost instanceof GenericManaCost) {
|
||||
// add increase cost to existing generic
|
||||
GenericManaCost gen = (GenericManaCost) manaCost;
|
||||
adjustedCost.add(new GenericManaCost(gen.getOptions().get(0).getGeneric() + -reduceCount));
|
||||
changedCost.put(manaCost, new GenericManaCost(gen.getOptions().get(0).getGeneric() + -reduceCount));
|
||||
reduceCount = 0;
|
||||
added = true;
|
||||
} else {
|
||||
// non-generic mana
|
||||
adjustedCost.add(manaCost.copy());
|
||||
}
|
||||
}
|
||||
|
||||
// add as new cost
|
||||
if (!added) {
|
||||
// add increase cost as new
|
||||
adjustedCost.add(new GenericManaCost(-reduceCount));
|
||||
addedCost.add(new GenericManaCost(-reduceCount));
|
||||
}
|
||||
}
|
||||
|
||||
// collect final result
|
||||
addedCost.forEach(cost -> {
|
||||
newCost.add(cost.copy());
|
||||
});
|
||||
changedCost.forEach((key, value) -> {
|
||||
// ignore fully reduced and add changed
|
||||
if (value != null) {
|
||||
newCost.add(value.copy());
|
||||
}
|
||||
});
|
||||
|
||||
// cost modifying effects requiring snow mana unnecessarily (fixes #6000)
|
||||
Filter filter = manaCosts.stream()
|
||||
.filter(manaCost -> !(manaCost instanceof SnowManaCost))
|
||||
|
|
@ -251,9 +274,10 @@ public final class CardUtil {
|
|||
.findFirst()
|
||||
.orElse(null);
|
||||
if (filter != null) {
|
||||
adjustedCost.setSourceFilter(filter);
|
||||
newCost.setSourceFilter(filter);
|
||||
}
|
||||
return adjustedCost;
|
||||
|
||||
return newCost;
|
||||
}
|
||||
|
||||
public static void reduceCost(SpellAbility spellAbility, ManaCosts<ManaCost> manaCostsToReduce) {
|
||||
|
|
|
|||
|
|
@ -576,7 +576,7 @@ public final class ManaUtil {
|
|||
res.setWhite(res.isWhite() || secondColor.isWhite());
|
||||
|
||||
// from mana
|
||||
List<String> secondManaSymbols = secondSideCard.getManaCost().getSymbols();
|
||||
List<String> secondManaSymbols = secondSideCard.getManaCostSymbols();
|
||||
res.setWhite(res.isWhite() || containsManaSymbol(secondManaSymbols, "W"));
|
||||
res.setBlue(res.isBlue() || containsManaSymbol(secondManaSymbols, "U"));
|
||||
res.setBlack(res.isBlack() || containsManaSymbol(secondManaSymbols, "B"));
|
||||
|
|
@ -628,7 +628,7 @@ public final class ManaUtil {
|
|||
} else {
|
||||
secondSide = card.getSecondCardFace();
|
||||
}
|
||||
return getColorIdentity(card.getColor(), String.join("", card.getManaCost().getSymbols()), card.getRules(), secondSide);
|
||||
return getColorIdentity(card.getColor(), String.join("", card.getManaCostSymbols()), card.getRules(), secondSide);
|
||||
}
|
||||
|
||||
public static int getColorIdentityHash(FilterMana colorIdentity) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue