Remove unsupported cards from AdventurePlayer inventory

- closes #8545
This commit is contained in:
Anthony Calosa
2025-08-27 21:34:07 +08:00
parent 1611559909
commit 0585ece2c1
13 changed files with 137 additions and 68 deletions

View File

@@ -375,7 +375,8 @@ public class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet,
System.out.println("PaperCard: " + name + " not found with set and index " + edition + ", " + artIndex);
pc = readObjectAlternate(name, edition);
if (pc == null) {
throw new IOException(TextUtil.concatWithSpace("Card", name, "not found with set and index", edition, Integer.toString(artIndex)));
pc = StaticData.instance().getCommonCards().createUnsupportedCard(name);
//throw new IOException(TextUtil.concatWithSpace("Card", name, "not found with set and index", edition, Integer.toString(artIndex)));
}
System.out.println("Alternate object found: " + pc.getName() + ", " + pc.getEdition() + ", " + pc.getArtIndex());
}

View File

@@ -31,6 +31,7 @@ import forge.util.ItemPool;
import java.io.Serializable;
import java.util.*;
import java.util.function.Predicate;
/**
* Class that represents the player (not the player sprite)
@@ -70,6 +71,9 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
private final HashMap<String, Long> equippedItems = new HashMap<>();
private final List<AdventureQuestData> quests = new ArrayList<>();
private final List<AdventureEventData> events = new ArrayList<>();
private final Set<PaperCard> unsupportedCards = new HashSet<>();
private final Predicate<PaperCard> isUnsupported = pc -> pc != null && pc.getRules() != null && pc.getRules().isUnsupported();
private final Predicate<PaperCard> isValid = pc -> pc != null && pc.getRules() != null && !pc.getRules().isUnsupported();
// Fantasy/Chaos mode settings.
private boolean fantasyMode = false;
@@ -130,6 +134,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
favoriteCards.clear();
AdventureEventController.clear();
AdventureQuestController.clear();
unsupportedCards.clear();
}
static public AdventurePlayer current() {
@@ -307,6 +312,10 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
return colorIdentity.toString();
}
public Collection<PaperCard> getUnsupportedCards() {
return unsupportedCards;
}
//Setters
public void setWorldPosX(float worldPosX) {
@@ -478,14 +487,24 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
}
deck = new Deck(data.readString("deckName"));
deck.getMain().addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deckCards"))));
if (data.containsKey("sideBoardCards"))
deck.getOrCreate(DeckSection.Sideboard).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards"))));
if(data.containsKey("attractionDeckCards"))
deck.getOrCreate(DeckSection.Attractions).addAll(CardPool.fromCardList(List.of((String[]) data.readObject("attractionDeckCards"))));
if(data.containsKey("contraptionDeckCards")) //TODO: Generalize this. Can't we just serialize the whole deck?
deck.getOrCreate(DeckSection.Contraptions).addAll(CardPool.fromCardList(List.of((String[]) data.readObject("contraptionDeckCards"))));
CardPool deckCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deckCards")));
deck.getMain().addAll(deckCards.getFilteredPool(isValid));
unsupportedCards.addAll(deckCards.getFilteredPool(isUnsupported).toFlatList());
if (data.containsKey("sideBoardCards")) {
CardPool sideBoardCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards")));
deck.getOrCreate(DeckSection.Sideboard).addAll(sideBoardCards.getFilteredPool(isValid));
unsupportedCards.addAll(sideBoardCards.getFilteredPool(isUnsupported).toFlatList());
}
if (data.containsKey("attractionDeckCards")) {
CardPool attractionDeckCards = CardPool.fromCardList(List.of((String[]) data.readObject("attractionDeckCards")));
deck.getOrCreate(DeckSection.Attractions).addAll(attractionDeckCards.getFilteredPool(isValid));
unsupportedCards.addAll(attractionDeckCards.getFilteredPool(isUnsupported).toFlatList());
}
if (data.containsKey("contraptionDeckCards")) {//TODO: Generalize this. Can't we just serialize the whole deck?
CardPool contraptionDeckCards = CardPool.fromCardList(List.of((String[]) data.readObject("contraptionDeckCards")));
deck.getOrCreate(DeckSection.Contraptions).addAll(contraptionDeckCards.getFilteredPool(isValid));
unsupportedCards.addAll(contraptionDeckCards.getFilteredPool(isUnsupported).toFlatList());
}
if (data.containsKey("characterFlagsKey") && data.containsKey("characterFlagsValue")) {
String[] keys = (String[]) data.readObject("characterFlagsKey");
Byte[] values = (Byte[]) data.readObject("characterFlagsValue");
@@ -536,13 +555,24 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
else {
decks.add(new Deck(data.readString("deck_name_" + i)));
}
decks.get(i).getMain().addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i))));
if (data.containsKey("sideBoardCards_" + i))
decks.get(i).getOrCreate(DeckSection.Sideboard).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i))));
if (data.containsKey("attractionDeckCards_" + i))
decks.get(i).getOrCreate(DeckSection.Attractions).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("attractionDeckCards_" + i))));
if (data.containsKey("contraptionDeckCards_" + i))
decks.get(i).getOrCreate(DeckSection.Contraptions).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("contraptionDeckCards_" + i))));
CardPool mainCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i)));
decks.get(i).getMain().addAll(mainCards.getFilteredPool(isValid));
unsupportedCards.addAll(mainCards.getFilteredPool(isUnsupported).toFlatList());
if (data.containsKey("sideBoardCards_" + i)) {
CardPool sideBoardCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i)));
decks.get(i).getOrCreate(DeckSection.Sideboard).addAll(sideBoardCards.getFilteredPool(isValid));
unsupportedCards.addAll(sideBoardCards.getFilteredPool(isUnsupported).toFlatList());
}
if (data.containsKey("attractionDeckCards_" + i)) {
CardPool attractionCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("attractionDeckCards_" + i)));
decks.get(i).getOrCreate(DeckSection.Attractions).addAll(attractionCards.getFilteredPool(isValid));
unsupportedCards.addAll(attractionCards.getFilteredPool(isUnsupported).toFlatList());
}
if (data.containsKey("contraptionDeckCards_" + i)) {
CardPool contraptionCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("contraptionDeckCards_" + i)));
decks.get(i).getOrCreate(DeckSection.Contraptions).addAll(contraptionCards.getFilteredPool(isValid));
unsupportedCards.addAll(contraptionCards.getFilteredPool(isUnsupported).toFlatList());
}
}
// In case we allow removing decks from the deck selection GUI, populate up to the minimum
for (int i = dynamicDeckCount++; i < MIN_DECK_COUNT; i++) {
@@ -557,26 +587,43 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
continue;
}
decks.set(i, new Deck(data.readString("deck_name_" + i)));
decks.get(i).getMain().addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i))));
if (data.containsKey("sideBoardCards_" + i))
decks.get(i).getOrCreate(DeckSection.Sideboard).addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i))));
CardPool mainCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("deck_" + i)));
decks.get(i).getMain().addAll(mainCards.getFilteredPool(isValid));
unsupportedCards.addAll(mainCards.getFilteredPool(isUnsupported).toFlatList());
if (data.containsKey("sideBoardCards_" + i)) {
CardPool sideBoardCards = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("sideBoardCards_" + i)));
decks.get(i).getOrCreate(DeckSection.Sideboard).addAll(sideBoardCards.getFilteredPool(isValid));
unsupportedCards.addAll(sideBoardCards.getFilteredPool(isUnsupported).toFlatList());
}
}
}
setSelectedDeckSlot(data.readInt("selectedDeckIndex"));
cards.addAll(CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("cards"))));
CardPool cardPool = CardPool.fromCardList(Lists.newArrayList((String[]) data.readObject("cards")));
cards.addAll(cardPool.getFilteredPool(isValid));
unsupportedCards.addAll(cardPool.getFilteredPool(isUnsupported).toFlatList());
if (data.containsKey("newCards")) {
InventoryItem[] items = (InventoryItem[]) data.readObject("newCards");
for (InventoryItem item : items) {
newCards.add((PaperCard) item);
if (item instanceof PaperCard pc) {
if (isUnsupported.test(pc))
unsupportedCards.add(pc);
else
newCards.add(pc);
}
}
}
if (data.containsKey("noSellCards")) {
// Legacy list of unsellable cards. Now done via CardRequest flags. Convert the corresponding cards.
PaperCard[] items = (PaperCard[]) data.readObject("noSellCards");
CardPool noSellPool = new CardPool();
noSellPool.addAllFlat(List.of(items));
for (PaperCard pc : items) {
if (isUnsupported.test(pc))
unsupportedCards.add(pc);
else
noSellPool.add(pc);
}
for (Map.Entry<PaperCard, Integer> noSellEntry : noSellPool) {
PaperCard item = noSellEntry.getKey();
if (item == null)
@@ -614,11 +661,21 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
}
if (data.containsKey("autoSellCards")) {
PaperCard[] items = (PaperCard[]) data.readObject("autoSellCards");
autoSellCards.addAllFlat(Arrays.asList(items));
for (PaperCard pc : items) {
if (isUnsupported.test(pc))
unsupportedCards.add(pc);
else
autoSellCards.add(pc);
}
}
if (data.containsKey("favoriteCards")) {
PaperCard[] items = (PaperCard[]) data.readObject("favoriteCards");
favoriteCards.addAll(Arrays.asList(items));
for (PaperCard pc : items) {
if (isUnsupported.test(pc))
unsupportedCards.add(pc);
else
favoriteCards.add(pc);
}
}
fantasyMode = data.containsKey("fantasyMode") && data.readBool("fantasyMode");
@@ -1134,7 +1191,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
}
public void equip(ItemData item) {
if (equippedItems.get(item.equipmentSlot) != null && equippedItems.get(item.equipmentSlot) == item.longID) {
Long itemID = equippedItems.get(item.equipmentSlot);
if (itemID != null && itemID.equals(item.longID)) {
item.isEquipped = false;
equippedItems.remove(item.equipmentSlot);
} else {
@@ -1186,16 +1244,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
}
public int countItem(String name) {
int count = 0;
if (!hasItem(name))
return count;
for (ItemData i : inventoryItems) {
if (i == null)
continue;
if (i.name.equals(name))
count++;
}
return count;
return (int) inventoryItems.stream().filter(Objects::nonNull).filter(i -> i.name.equals(name)).count();
}
public boolean addItem(String name) {

View File

@@ -501,9 +501,7 @@ public class AdventureDeckEditor extends FDeckEditor {
String action = localizer.getMessage("lblFromAutoSell", autoSellCount, safeToSellCount);
String prompt = String.format("%s - %s %s", card, action, localizer.getMessage("lblHowMany"));
FMenuItem moveToCatalog = new FMenuItem(action, CATALOG_ICON, new MoveQuantityPrompt(prompt, autoSellCount, amount -> {
moveCard(card, catalogPage, amount);
}));
FMenuItem moveToCatalog = new FMenuItem(action, CATALOG_ICON, new MoveQuantityPrompt(prompt, autoSellCount, amount -> moveCard(card, catalogPage, amount)));
menu.addItem(moveToCatalog);
}
@@ -658,6 +656,15 @@ public class AdventureDeckEditor extends FDeckEditor {
// if (currentEvent.registeredDeck!=null && !currentEvent.registeredDeck.isEmpty()){
// //Use this deck instead of selected deck
// }
for (TabPage<FDeckEditor> page : tabPages) {
if (page instanceof CollectionCatalogPage) {
if (!Current.player().getUnsupportedCards().isEmpty())
GuiChoose.getChoices(Forge.getLocalizer().getMessage("lblRemoveAllUnsupportedCards"),
-1, -1, Current.player().getUnsupportedCards(), result -> Current.player().getUnsupportedCards().clear());
break;
}
}
}
public void refresh() {

View File

@@ -103,7 +103,7 @@ public class Console extends Window {
case Input.Keys.V:
if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT)) {
if (Forge.getClipboard().hasContents()) {
textField.setText(Forge.getClipboard().getContents());
textField.appendText(Forge.getClipboard().getContents());
textField.setCursorPosition(Integer.MAX_VALUE);
}
}

View File

@@ -261,30 +261,35 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(false)) && !Forge.enableUIMask.equals("Art")) {
int count = 0;
PaperCard card = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(false));
File frontFace = ImageKeys.getImageFile(card.getCardImageKey());
if (frontFace != null) {
try {
Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
if (front == null) {
Forge.getAssets().manager().load(frontFace.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(frontFace.getPath());
front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
}
if (front != null) {
count += 1;
setCardImage(front);
} else {
try {
PaperCard card = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(false));
File frontFace = ImageKeys.getImageFile(card.getCardImageKey());
if (frontFace != null) {
try {
Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
if (front == null) {
Forge.getAssets().manager().load(frontFace.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(frontFace.getPath());
front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
}
if (front != null) {
count += 1;
setCardImage(front);
} else {
loaded = false;
}
} catch (Exception e) {
System.err.println("Failed to load image: " + frontFace.getPath());
loaded = false;
}
} catch (Exception e) {
System.err.println("Failed to load image: " + frontFace.getPath());
} else {
loaded = false;
}
} else {
ImageCache.getInstance().updateSynqCount(frontFace, count);
} catch (Exception e) {
System.err.println("Failed to load image: " + reward.getCard());
loaded = false;
}
ImageCache.getInstance().updateSynqCount(frontFace, count);
} else {
String imagePath = ImageUtil.getImageRelativePath(reward.getCard(), "", true, false);
File lookup = ImageKeys.hasSetLookup(imagePath) ? ImageKeys.setLookUpFile(imagePath, imagePath + "border") : null;
@@ -322,8 +327,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
}
ImageCache.getInstance().updateSynqCount(file, 1);
}
} catch (Exception e) {
}
} catch (Exception ignored) {}
}
T = renderPlaceholder(new Graphics(), reward.getCard(), false); //Now we can render the card.
setCardImage(T);
@@ -587,7 +591,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
} catch (Exception e) {
System.err.println("Failed to load image: " + backFace.getPath());
}
};
}
}
private void switchTooltip() {

View File

@@ -3544,4 +3544,5 @@ lblRepairCost=Reparaturkosten: {0} ?
lblRepair=Reparieren
lblDataMigrationMsg=Datenmigration abgeschlossen!\nBitte überprüfen Sie Ihr Inventar und Ihre Ausrüstung.\nBitte erstellen Sie an dieser Stelle eine Sicherungskopie Ihrer Spielstände, da der aktuelle Spielstand noch nicht überschrieben wird, wenn Sie im Menü „Szene“ den Punkt „Daten“ -> „Sicherungskopie“ verwenden.
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=Verwijder niet-ondersteunde kaart
lblRemoveUnsupportedCard=Verwijder niet-ondersteunde kaart
lblRemoveAllUnsupportedCards=Nicht unterstützte Karten wurden aus Ihrem Inventar entfernt.

View File

@@ -3298,4 +3298,5 @@ lblRepairCost=Repair Cost: {0} ?
lblRepair=Repair
lblDataMigrationMsg=Data Migration completed!\nPlease check your Inventory and Equipments.\nPlease make a backup of your saves at this point since the actual save is not yet overwritten by using the Data -> Backup at the Menu Scene.
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=Remove unsupported card
lblRemoveUnsupportedCard=Remove unsupported card
lblRemoveAllUnsupportedCards=Unsupported cards have been remove from your inventory.

View File

@@ -3548,4 +3548,5 @@ lblRepairCost=Costo de reparación: {0} ?
lblRepair=Reparar
lblDataMigrationMsg=¡Migración de datos completada!\nPor favor revise su inventario y equipos.\nPor favor, haz una copia de seguridad de tus partidas guardadas en este punto, ya que la partida guardada real aún no se sobrescribe al usar Datos -> Copia de seguridad en la Escena del menú.
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=Quitar tarjeta incompatible
lblRemoveUnsupportedCard=Quitar tarjeta incompatible
lblRemoveAllUnsupportedCards=Las tarjetas no compatibles se han eliminado de tu inventario.

View File

@@ -3549,4 +3549,5 @@ lblRepairCost=Coût de réparation : {0} ?
lblRepair=Réparation
lblDataMigrationMsg=Migration des données terminée!\nVeuillez vérifier votre inventaire et vos équipements.\nVeuillez effectuer une sauvegarde de vos sauvegardes à ce stade, car la sauvegarde réelle n'est pas encore écrasée en utilisant Données -> Sauvegarde dans le menu Scène.
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=Supprimer la carte non prise en charge
lblRemoveUnsupportedCard=Supprimer la carte non prise en charge
lblRemoveAllUnsupportedCards=Les cartes non prises en charge ont été supprimées de votre inventaire.

View File

@@ -3547,4 +3547,5 @@ lblRepairCost=Costo di riparazione: {0} ?
lblRepair=Riparazione
lblDataMigrationMsg=Migrazione dati completata!\nControlla il tuo inventario e le tue attrezzature.\nA questo punto, esegui un backup dei tuoi salvataggi, poiché il salvataggio effettivo non è ancora stato sovrascritto, utilizzando Dati -> Backup nel menu Scena.
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=Rimuovi la carta non supportata
lblRemoveUnsupportedCard=Rimuovi la carta non supportata
lblRemoveAllUnsupportedCards=Le carte non supportate sono state rimosse dal tuo inventario.

View File

@@ -3543,4 +3543,5 @@ lblRepairCost=修理費用: {0}?
lblRepair=修理
lblDataMigrationMsg=データ移行が完了しました!\nインベントリと装備を確認してください。\n実際の保存はまだメニューシーンの「データ」->「バックアップ」を使用して上書きされていないため、この時点で保存のバックアップを作成してください。
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=サポートされていないカードを削除する
lblRemoveUnsupportedCard=サポートされていないカードを削除する
lblRemoveAllUnsupportedCards=サポートされていないカードはインベントリから削除されました。

View File

@@ -3632,4 +3632,5 @@ lblRepairCost=Custo do reparo: {0} ?
lblRepair=Reparar
lblDataMigrationMsg=Migração de dados concluída!\nVerifique seu inventário e equipamentos.\nPor favor, faça um backup dos seus arquivos salvos neste momento, já que o arquivo salvo atual ainda não foi sobrescrito usando Dados -> Backup na Cena do Menu.
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=Remover cartão não suportado
lblRemoveUnsupportedCard=Remover cartão não suportado
lblRemoveAllUnsupportedCards=Cartas não suportadas foram removidas do seu inventário.

View File

@@ -3534,4 +3534,5 @@ lblRepairCost=维修费用:{0}
lblRepair=维修
lblDataMigrationMsg=数据迁移完成!\n请检查您的库存和设备。此时请备份您的保存内容因为尚未使用菜单场景中的数据->备份覆盖实际保存内容。
#AdventureDeckEditor.java
lblRemoveUnsupportedCard=移除不受支持的卡
lblRemoveUnsupportedCard=移除不受支持的卡
lblRemoveAllUnsupportedCards=不受支持的卡已从您的库存中移除。