Store cards by collectorNumber instead of artIndex; PaperCard flag support (#7240)

* Refactor - Unknown set code to constant

* Refactor - Support for multiple initial selections for getChoices

* Covert noSell and marked color identities into serializable flags

* Fix cards in deck not being converted to newer noSell format

* unused imports

* Fix NPE

* Cleanup card filter

* Remove 14-year-old check that shouldn't be possible anymore

* CRLF -> LF

---------

Co-authored-by: Jetz <Jetz722@gmail.com>
This commit is contained in:
Jetz72
2025-04-16 18:59:31 -04:00
committed by GitHub
parent c85214b9e3
commit 4714319204
63 changed files with 559 additions and 486 deletions

View File

@@ -182,7 +182,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display) {
/*if ((choices != null && !choices.isEmpty() && choices.iterator().next() instanceof GameObject) || selected instanceof GameObject) {
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
Thread.dumpStack();

View File

@@ -214,7 +214,7 @@ public class CardDetailPanel extends SkinnedPanel {
set = state.getSetCode();
rarity = state.getRarity();
} else {
set = CardEdition.UNKNOWN.getCode();
set = CardEdition.UNKNOWN_CODE;
rarity = CardRarity.Unknown;
}
setInfoLabel.setText(set);

View File

@@ -134,10 +134,10 @@ public class GuiChoose {
return getChoices(message, min, max, choices, null, null);
}
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display) {
return getChoices(message, min, max, choices, selected, display, null);
}
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display, final CMatchUI matchUI) {
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final Collection<T> selected, final Function<T, String> display, final CMatchUI matchUI) {
if (choices == null || choices.isEmpty()) {
if (min == 0) {
return new ArrayList<>();

View File

@@ -152,16 +152,13 @@ public class ListChooser<T> {
/** @return boolean */
public boolean show() {
return show(list.get(0));
return show(null);
}
/**
* Shows the dialog and returns after the dialog was closed.
*
* @param index0 index to select when shown
* @return a boolean.
*/
public boolean show(final T item) {
public boolean show(final Collection<T> item) {
if (this.called) {
throw new IllegalStateException("Already shown");
}
@@ -169,8 +166,12 @@ public class ListChooser<T> {
do {
//invoke later so selected item not set until dialog open
SwingUtilities.invokeLater(() -> {
if (list.contains(item)) {
lstChoices.setSelectedValue(item, true);
if (item != null) {
int[] indices = item.stream()
.mapToInt(list::indexOf)
.filter(i -> i >= 0)
.toArray();
lstChoices.setSelectedIndices(indices);
}
else {
lstChoices.setSelectedIndex(0);

View File

@@ -20,16 +20,15 @@ package forge.screens.deckeditor.controllers;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.CardPool;
import forge.deck.Deck;
@@ -582,9 +581,9 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
int val;
if ((val = existingCard.getRules().getSetColorID()) > 0) {
GuiUtils.addMenuItem(menu, label, null, () -> {
Set<String> colors = new HashSet<>(GuiChoose.getChoices(localizer.getMessage("lblChooseNColors", Lang.getNumeral(val)), val, val, MagicColor.Constant.ONLY_COLORS));
List<String> colors = GuiChoose.getChoices(localizer.getMessage("lblChooseNColors", Lang.getNumeral(val)), val, val, MagicColor.Constant.ONLY_COLORS);
// make an updated version
PaperCard updated = existingCard.getColorIDVersion(colors);
PaperCard updated = existingCard.copyWithMarkedColors(ColorSet.fromNames(colors));
// remove *quantity* instances of existing card
CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 1);
// add *quantity* into the deck and set them as selected

View File

@@ -24,7 +24,6 @@ import java.awt.image.BufferedImage;
import java.util.*;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
@@ -1072,7 +1071,7 @@ public final class CMatchUI
}
@Override
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final T selected, final Function<T, String> display) {
public <T> List<T> getChoices(final String message, final int min, final int max, final List<T> choices, final List<T> selected, final Function<T, String> display) {
/*if ((choices != null && !choices.isEmpty() && choices.iterator().next() instanceof GameObject) || selected instanceof GameObject) {
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
Thread.dumpStack();

View File

@@ -277,21 +277,6 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
}
}
@Test
public void testGetCardByNameSetArtIndexAndCollectorNumber() {
// MultiArt Card
PaperCard card;
for (int i = 0; i < 4; i++) {
int artIndex = i + 1;
card = this.cardDb.getCard(cardNameHymnToTourach, editionHymnToTourach, artIndex,
collectorNumbersHymnToTourach[i]);
assertEquals(card.getName(), cardNameHymnToTourach);
assertEquals(card.getEdition(), editionHymnToTourach);
assertEquals(card.getCollectorNumber(), collectorNumbersHymnToTourach[i]);
assertEquals(card.getArtIndex(), artIndex);
}
}
@Test
public void testNullIsReturnedWithWrongInfo() {
String wrongEditionCode = "M11";
@@ -307,11 +292,6 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
// Wrong collector number
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, "wrongCN");
assertNull(card);
// wrong artIndex or collector number in getCard Full Info
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, 3, collNrShivanDragon);
assertNull(card);
card = this.cardDb.getCard(cardNameShivanDragon, editionShivanDragon, 1, "wrongCN");
assertNull(card);
}
@Test
@@ -2105,7 +2085,7 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
public void testGetCardFromUnknownSet() {
String unknownCardName = "Unknown Card Name";
PaperCard unknownCard = new PaperCard(CardRules.getUnsupportedCardNamed(unknownCardName),
CardEdition.UNKNOWN.getCode(), CardRarity.Unknown);
CardEdition.UNKNOWN_CODE, CardRarity.Unknown);
this.cardDb.addCard(unknownCard);
assertTrue(this.cardDb.getAllCards().contains(unknownCard));
assertNotNull(this.cardDb.getAllCards(unknownCardName));
@@ -2114,7 +2094,7 @@ public class CardDbCardMockTestCase extends CardMockTestCase {
PaperCard retrievedPaperCard = this.cardDb.getCard(unknownCardName);
assertNotNull(retrievedPaperCard);
assertEquals(retrievedPaperCard.getName(), unknownCardName);
assertEquals(retrievedPaperCard.getEdition(), CardEdition.UNKNOWN.getCode());
assertEquals(retrievedPaperCard.getEdition(), CardEdition.UNKNOWN_CODE);
}
@Test