Merge pull request #8755 from kevlahnota/master4

use Supplier for FModel for thread safety
This commit is contained in:
kevlahnota
2025-09-21 09:01:18 +08:00
committed by GitHub

View File

@@ -17,6 +17,8 @@
*/ */
package forge.model; package forge.model;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import forge.*; import forge.*;
import forge.CardStorageReader.ProgressObserver; import forge.CardStorageReader.ProgressObserver;
@@ -75,32 +77,81 @@ import java.util.function.Function;
public final class FModel { public final class FModel {
private FModel() { } //don't allow creating instance private FModel() { } //don't allow creating instance
private static StaticData magicDb; private static CardStorageReader reader, tokenReader, customReader, customTokenReader;
private static final Supplier<StaticData> magicDb = Suppliers.memoize(() ->
private static QuestPreferences questPreferences; new StaticData(reader, tokenReader, customReader, customTokenReader, ForgeConstants.EDITIONS_DIR,
private static ConquestPreferences conquestPreferences; ForgeConstants.USER_CUSTOM_EDITIONS_DIR, ForgeConstants.BLOCK_DATA_DIR, ForgeConstants.SETLOOKUP_DIR,
getPreferences().getPref(FPref.UI_PREFERRED_ART),
getPreferences().getPrefBoolean(FPref.UI_LOAD_UNKNOWN_CARDS),
getPreferences().getPrefBoolean(FPref.UI_LOAD_NONLEGAL_CARDS),
getPreferences().getPrefBoolean(FPref.ALLOW_CUSTOM_CARDS_IN_DECKS_CONFORMANCE),
getPreferences().getPrefBoolean(FPref.UI_SMART_CARD_ART)));
private static final Supplier<QuestPreferences> questPreferences = Suppliers.memoize(QuestPreferences::new);
private static final Supplier<ConquestPreferences> conquestPreferences = Suppliers.memoize(() -> {
final ConquestPreferences cp = new ConquestPreferences();
ConquestUtil.updateRarityFilterOdds(cp);
return cp;
});
private static ForgePreferences preferences; private static ForgePreferences preferences;
private static ForgeNetPreferences netPreferences; private static final Supplier<ForgeNetPreferences> netPreferences = Suppliers.memoize(ForgeNetPreferences::new);
private static Map<GameType, AchievementCollection> achievements; private static final Supplier<Map<GameType, AchievementCollection>> achievements = Suppliers.memoize(() -> {
final Map<GameType, AchievementCollection> a = Maps.newHashMap();
a.put(GameType.Constructed, new ConstructedAchievements());
a.put(GameType.Draft, new DraftAchievements());
a.put(GameType.Sealed, new SealedAchievements());
a.put(GameType.Quest, new QuestAchievements());
a.put(GameType.PlanarConquest, new PlanarConquestAchievements());
a.put(GameType.Puzzle, new PuzzleAchievements());
a.put(GameType.Adventure, new AdventureAchievements());
return a;
});
// Someone should take care of 2 gauntlets here // Someone should take care of 2 gauntlets here
private static TournamentData tournamentData; private static TournamentData tournamentData;
private static GauntletData gauntletData; private static GauntletData gauntletData;
private static GauntletMini gauntlet; private static final Supplier<GauntletMini> gauntletMini = Suppliers.memoize(GauntletMini::new);
private static QuestController quest; private static final Supplier<QuestController> quest = Suppliers.memoize(QuestController::new);
private static ConquestController conquest; private static final Supplier<ConquestController> conquest = Suppliers.memoize(ConquestController::new);
private static CardCollections decks; private static final Supplier<CardCollections> decks = Suppliers.memoize(CardCollections::new);
private static IStorage<CardBlock> blocks; private static final Supplier<IStorage<CardBlock>> blocks = Suppliers.memoize(() -> {
private static IStorage<CardBlock> fantasyBlocks; final IStorage<CardBlock> cb = new StorageBase<>("Block definitions", new CardBlock.Reader(ForgeConstants.BLOCK_DATA_DIR + "blocks.txt", getMagicDb().getEditions()));
private static IStorage<ThemedChaosDraft> themedChaosDrafts; // SetblockLands
private static IStorage<ConquestPlane> planes; for (final CardBlock b : cb) {
private static IStorage<QuestWorld> worlds; try {
private static GameFormat.Collection formats; getMagicDb().getBlockLands().add(b.getLandSet().getCode());
private static ItemPool<PaperCard> uniqueCardsNoAlt, allCardsNoAlt, planechaseCards, archenemyCards, } catch (Exception e) {
brawlCommander, oathbreakerCommander, tinyLeadersCommander, commanderPool, e.printStackTrace();
avatarPool, conspiracyPool, dungeonPool, attractionPool, contraptionPool; }
}
return cb;
});
private static final Supplier<IStorage<CardBlock>> fantasyBlocks = Suppliers.memoize(() -> new StorageBase<>("Custom blocks", new CardBlock.Reader(ForgeConstants.BLOCK_DATA_DIR + "fantasyblocks.txt", getMagicDb().getEditions())));
private static final Supplier<IStorage<ThemedChaosDraft>> themedChaosDrafts = Suppliers.memoize(() -> new StorageBase<>("Themed Chaos Drafts", new ThemedChaosDraft.Reader(ForgeConstants.BLOCK_DATA_DIR + "chaosdraftthemes.txt")));
private static final Supplier<IStorage<ConquestPlane>> planes = Suppliers.memoize(() -> new StorageBase<>("Conquest planes", new ConquestPlane.Reader(ForgeConstants.CONQUEST_PLANES_DIR + "planes.txt")));
private static final Supplier<IStorage<QuestWorld>> worlds = Suppliers.memoize(() -> {
final Map<String, QuestWorld> standardWorlds = new QuestWorld.Reader(ForgeConstants.QUEST_WORLD_DIR + "worlds.txt").readAll();
final Map<String, QuestWorld> customWorlds = new QuestWorld.Reader(ForgeConstants.USER_QUEST_WORLD_DIR + "customworlds.txt").readAll();
customWorlds.values().forEach(world -> world.setCustom(true));
standardWorlds.putAll(customWorlds);
final IStorage<QuestWorld> w = new StorageBase<>("Quest worlds", null, standardWorlds);
return w;
});
private static final Supplier<GameFormat.Collection> formats = Suppliers.memoize(() -> new GameFormat.Collection(new GameFormat.Reader( new File(ForgeConstants.FORMATS_DATA_DIR), new File(ForgeConstants.USER_FORMATS_DIR), preferences.getPrefBoolean(FPref.LOAD_ARCHIVED_FORMATS))));
private static final Supplier<ItemPool<PaperCard>> uniqueCardsNoAlt = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getCommonCards().getUniqueCardsNoAlt(), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> allCardsNoAlt = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> planechaseCards = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_PLANE_OR_PHENOMENON)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> archenemyCards = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_SCHEME)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> brawlCommander = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(getFormats().get("Brawl").getFilterPrinted().and(PaperCardPredicates.fromRules(CardRulesPredicates.CAN_BE_BRAWL_COMMANDER))), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> oathbreakerCommander = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(PaperCardPredicates.fromRules(CardRulesPredicates.CAN_BE_OATHBREAKER.or(CardRulesPredicates.CAN_BE_SIGNATURE_SPELL))), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> tinyLeadersCommander = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(PaperCardPredicates.fromRules(CardRulesPredicates.CAN_BE_TINY_LEADERS_COMMANDER)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> commanderPool = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(PaperCardPredicates.CAN_BE_COMMANDER), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> avatarPool = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_VANGUARD)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> conspiracyPool = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_CONSPIRACY)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> dungeonPool = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_DUNGEON)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> attractionPool = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_ATTRACTION)), PaperCard.class));
private static final Supplier<ItemPool<PaperCard>> contraptionPool = Suppliers.memoize(() -> ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_CONTRAPTION)), PaperCard.class));
public static void initialize(final IProgressBar progressBar, Function<ForgePreferences, Void> adjustPrefs) { public static void initialize(final IProgressBar progressBar, Function<ForgePreferences, Void> adjustPrefs) {
initialize(progressBar, adjustPrefs, false); initialize(progressBar, adjustPrefs, false);
@@ -126,8 +177,8 @@ public final class FModel {
throw new RuntimeException(exn); throw new RuntimeException(exn);
} }
Lang.createInstance(FModel.getPreferences().getPref(FPref.UI_LANGUAGE)); Lang.createInstance(getPreferences().getPref(FPref.UI_LANGUAGE));
Localizer.getInstance().initialize(FModel.getPreferences().getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR); Localizer.getInstance().initialize(getPreferences().getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR);
final ProgressObserver progressBarBridge = (progressBar == null) ? final ProgressObserver progressBarBridge = (progressBar == null) ?
ProgressObserver.emptyObserver : new ProgressObserver() { ProgressObserver.emptyObserver : new ProgressObserver() {
@@ -154,17 +205,17 @@ public final class FModel {
// Load card database // Load card database
// Lazy loading currently disabled // Lazy loading currently disabled
final CardStorageReader reader = new CardStorageReader(ForgeConstants.CARD_DATA_DIR, progressBarBridge, reader = new CardStorageReader(ForgeConstants.CARD_DATA_DIR, progressBarBridge,
false); false);
final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge, tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge,
false); false);
CardStorageReader customReader;
try { try {
customReader = new CardStorageReader(ForgeConstants.USER_CUSTOM_CARDS_DIR, progressBarBridge, false); customReader = new CardStorageReader(ForgeConstants.USER_CUSTOM_CARDS_DIR, progressBarBridge, false);
} catch (Exception e) { } catch (Exception e) {
customReader = null; customReader = null;
} }
CardStorageReader customTokenReader;
try { try {
customTokenReader = new CardStorageReader(ForgeConstants.USER_CUSTOM_TOKENS_DIR, progressBarBridge, false); customTokenReader = new CardStorageReader(ForgeConstants.USER_CUSTOM_TOKENS_DIR, progressBarBridge, false);
} catch (Exception e) { } catch (Exception e) {
@@ -174,15 +225,6 @@ public final class FModel {
// Do this first so PaperCards see the real preference // Do this first so PaperCards see the real preference
CardTranslation.preloadTranslation(preferences.getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR); CardTranslation.preloadTranslation(preferences.getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR);
magicDb = new StaticData(reader, tokenReader, customReader, customTokenReader, ForgeConstants.EDITIONS_DIR,
ForgeConstants.USER_CUSTOM_EDITIONS_DIR, ForgeConstants.BLOCK_DATA_DIR, ForgeConstants.SETLOOKUP_DIR,
FModel.getPreferences().getPref(FPref.UI_PREFERRED_ART),
FModel.getPreferences().getPrefBoolean(FPref.UI_LOAD_UNKNOWN_CARDS),
FModel.getPreferences().getPrefBoolean(FPref.UI_LOAD_NONLEGAL_CARDS),
FModel.getPreferences().getPrefBoolean(FPref.ALLOW_CUSTOM_CARDS_IN_DECKS_CONFORMANCE),
FModel.getPreferences().getPrefBoolean(FPref.UI_SMART_CARD_ART)
);
// Create profile dirs if they don't already exist // Create profile dirs if they don't already exist
for (final String dname : ForgeConstants.PROFILE_DIRS) { for (final String dname : ForgeConstants.PROFILE_DIRS) {
final File path = new File(dname); final File path = new File(dname);
@@ -198,18 +240,18 @@ public final class FModel {
ForgePreferences.DEV_MODE = preferences.getPrefBoolean(FPref.DEV_MODE_ENABLED); ForgePreferences.DEV_MODE = preferences.getPrefBoolean(FPref.DEV_MODE_ENABLED);
ForgePreferences.UPLOAD_DRAFT = ForgePreferences.NET_CONN; ForgePreferences.UPLOAD_DRAFT = ForgePreferences.NET_CONN;
magicDb.setStandardPredicate(getFormats().getStandard().getFilterRules()); getMagicDb().setStandardPredicate(getFormats().getStandard().getFilterRules());
magicDb.setPioneerPredicate(getFormats().getPioneer().getFilterRules()); getMagicDb().setPioneerPredicate(getFormats().getPioneer().getFilterRules());
magicDb.setModernPredicate(getFormats().getModern().getFilterRules()); getMagicDb().setModernPredicate(getFormats().getModern().getFilterRules());
magicDb.setCommanderPredicate(getFormats().get("Commander").getFilterRules()); getMagicDb().setCommanderPredicate(getFormats().get("Commander").getFilterRules());
magicDb.setOathbreakerPredicate(getFormats().get("Oathbreaker").getFilterRules()); getMagicDb().setOathbreakerPredicate(getFormats().get("Oathbreaker").getFilterRules());
magicDb.setBrawlPredicate(getFormats().get("Brawl").getFilterRules()); getMagicDb().setBrawlPredicate(getFormats().get("Brawl").getFilterRules());
magicDb.setFilteredHandsEnabled(preferences.getPrefBoolean(FPref.FILTERED_HANDS)); getMagicDb().setFilteredHandsEnabled(preferences.getPrefBoolean(FPref.FILTERED_HANDS));
try { try {
magicDb.setMulliganRule(MulliganDefs.MulliganRule.valueOf(preferences.getPref(FPref.MULLIGAN_RULE))); getMagicDb().setMulliganRule(MulliganDefs.MulliganRule.valueOf(preferences.getPref(FPref.MULLIGAN_RULE)));
} catch(Exception e) { } catch(Exception e) {
magicDb.setMulliganRule(MulliganDefs.MulliganRule.London); getMagicDb().setMulliganRule(MulliganDefs.MulliganRule.London);
} }
Spell.setPerformanceMode(preferences.getPrefBoolean(FPref.PERFORMANCE_MODE)); Spell.setPerformanceMode(preferences.getPrefBoolean(FPref.PERFORMANCE_MODE));
@@ -224,38 +266,16 @@ public final class FModel {
// Preload AI profiles // Preload AI profiles
AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR); AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR);
AiProfileUtil.setAiSideboardingMode(AiProfileUtil.AISideboardingMode.normalizedValueOf(FModel.getPreferences().getPref(FPref.MATCH_AI_SIDEBOARDING_MODE))); AiProfileUtil.setAiSideboardingMode(AiProfileUtil.AISideboardingMode.normalizedValueOf(getPreferences().getPref(FPref.MATCH_AI_SIDEBOARDING_MODE)));
// Generate Deck Gen matrix // Generate Deck Gen matrix
if(FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_CARDBASED)) { if(getPreferences().getPrefBoolean(FPref.DECKGEN_CARDBASED)) {
boolean commanderDeckGenMatrixLoaded=CardRelationMatrixGenerator.initialize(); boolean commanderDeckGenMatrixLoaded=CardRelationMatrixGenerator.initialize();
deckGenMatrixLoaded=CardArchetypeLDAGenerator.initialize(); deckGenMatrixLoaded=CardArchetypeLDAGenerator.initialize();
if(!commanderDeckGenMatrixLoaded){ if(!commanderDeckGenMatrixLoaded){
deckGenMatrixLoaded=false; deckGenMatrixLoaded=false;
} }
} }
if (GuiBase.getInterface().isLibgdxPort() && GuiBase.getDeviceRAM() < 5000)
return; // Don't preload ItemPool on mobile port with less than 5GB RAM
// Common ItemPool to preload
getAllCardsNoAlt();
getArchenemyCards();
getPlanechaseCards();
getAttractionPool();
getContraptionPool();
if (GuiBase.getInterface().isLibgdxPort()) {
// Preload mobile Itempool
getUniqueCardsNoAlt();
} else {
// Preload Desktop Itempool
getCommanderPool();
getOathbreakerCommander();
getBrawlCommander();
getTinyLeadersCommander();
getAvatarPool();
getConspiracyPool();
}
} }
private static boolean deckGenMatrixLoaded = false; private static boolean deckGenMatrixLoaded = false;
@@ -265,103 +285,63 @@ public final class FModel {
} }
public static QuestController getQuest() { public static QuestController getQuest() {
if (quest == null) return quest.get();
quest = new QuestController();
return quest;
} }
public static ConquestController getConquest() { public static ConquestController getConquest() {
if (conquest == null) return conquest.get();
conquest = new ConquestController();
return conquest;
} }
public static ItemPool<PaperCard> getUniqueCardsNoAlt() { public static ItemPool<PaperCard> getUniqueCardsNoAlt() {
if (uniqueCardsNoAlt == null) return uniqueCardsNoAlt.get();
uniqueCardsNoAlt = ItemPool.createFrom(getMagicDb().getCommonCards().getUniqueCardsNoAlt(), PaperCard.class);
return uniqueCardsNoAlt;
} }
public static ItemPool<PaperCard> getAllCardsNoAlt() { public static ItemPool<PaperCard> getAllCardsNoAlt() {
if (allCardsNoAlt == null) return allCardsNoAlt.get();
allCardsNoAlt = ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(), PaperCard.class);
return allCardsNoAlt;
} }
public static ItemPool<PaperCard> getArchenemyCards() { public static ItemPool<PaperCard> getArchenemyCards() {
if (archenemyCards == null) return archenemyCards.get();
archenemyCards = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_SCHEME)), PaperCard.class);
return archenemyCards;
} }
public static ItemPool<PaperCard> getPlanechaseCards() { public static ItemPool<PaperCard> getPlanechaseCards() {
if (planechaseCards == null) return planechaseCards.get();
planechaseCards = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(CardRulesPredicates.IS_PLANE_OR_PHENOMENON)), PaperCard.class);
return planechaseCards;
} }
public static ItemPool<PaperCard> getBrawlCommander() { public static ItemPool<PaperCard> getBrawlCommander() {
if (brawlCommander == null) { return brawlCommander.get();
brawlCommander = ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(
FModel.getFormats().get("Brawl").getFilterPrinted()
.and(PaperCardPredicates.fromRules(CardRulesPredicates.CAN_BE_BRAWL_COMMANDER))), PaperCard.class);
}
return brawlCommander;
} }
public static ItemPool<PaperCard> getOathbreakerCommander() { public static ItemPool<PaperCard> getOathbreakerCommander() {
if (oathbreakerCommander == null) return oathbreakerCommander.get();
oathbreakerCommander = ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(PaperCardPredicates.fromRules(
CardRulesPredicates.CAN_BE_OATHBREAKER.or(CardRulesPredicates.CAN_BE_SIGNATURE_SPELL))), PaperCard.class);
return oathbreakerCommander;
} }
public static ItemPool<PaperCard> getTinyLeadersCommander() { public static ItemPool<PaperCard> getTinyLeadersCommander() {
if (tinyLeadersCommander == null) return tinyLeadersCommander.get();
tinyLeadersCommander = ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(PaperCardPredicates.fromRules(
CardRulesPredicates.CAN_BE_TINY_LEADERS_COMMANDER)), PaperCard.class);
return tinyLeadersCommander;
} }
public static ItemPool<PaperCard> getCommanderPool() { public static ItemPool<PaperCard> getCommanderPool() {
if (commanderPool == null) return commanderPool.get();
commanderPool = ItemPool.createFrom(getMagicDb().getCommonCards().getAllCardsNoAlt(PaperCardPredicates.CAN_BE_COMMANDER), PaperCard.class);
return commanderPool;
} }
public static ItemPool<PaperCard> getAvatarPool() { public static ItemPool<PaperCard> getAvatarPool() {
if (avatarPool == null) return avatarPool.get();
avatarPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(
CardRulesPredicates.IS_VANGUARD)), PaperCard.class);
return avatarPool;
} }
public static ItemPool<PaperCard> getConspiracyPool() { public static ItemPool<PaperCard> getConspiracyPool() {
if (conspiracyPool == null) return conspiracyPool.get();
conspiracyPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(
CardRulesPredicates.IS_CONSPIRACY)), PaperCard.class);
return conspiracyPool;
} }
public static ItemPool<PaperCard> getDungeonPool() { public static ItemPool<PaperCard> getDungeonPool() {
if (dungeonPool == null) return dungeonPool.get();
dungeonPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(
CardRulesPredicates.IS_DUNGEON)), PaperCard.class);
return dungeonPool;
} }
public static ItemPool<PaperCard> getAttractionPool() { public static ItemPool<PaperCard> getAttractionPool() {
if (attractionPool == null) return attractionPool.get();
attractionPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(
CardRulesPredicates.IS_ATTRACTION)), PaperCard.class);
return attractionPool;
} }
public static ItemPool<PaperCard> getContraptionPool() { public static ItemPool<PaperCard> getContraptionPool() {
if (contraptionPool == null) return contraptionPool.get();
contraptionPool = ItemPool.createFrom(getMagicDb().getVariantCards().getAllCards(PaperCardPredicates.fromRules(
CardRulesPredicates.IS_CONTRAPTION)), PaperCard.class);
return contraptionPool;
} }
private static boolean keywordsLoaded = false; private static boolean keywordsLoaded = false;
@@ -396,67 +376,36 @@ public final class FModel {
} }
public static StaticData getMagicDb() { public static StaticData getMagicDb() {
return magicDb; return magicDb.get();
} }
public static ForgePreferences getPreferences() { public static ForgePreferences getPreferences() {
return preferences; return preferences;
} }
public static ForgeNetPreferences getNetPreferences() { public static ForgeNetPreferences getNetPreferences() {
if (netPreferences == null) return netPreferences.get();
netPreferences = new ForgeNetPreferences();
return netPreferences;
} }
public static AchievementCollection getAchievements(GameType gameType) { public static AchievementCollection getAchievements(GameType gameType) {
if (achievements == null) {
achievements = Maps.newHashMap();
achievements.put(GameType.Constructed, new ConstructedAchievements());
achievements.put(GameType.Draft, new DraftAchievements());
achievements.put(GameType.Sealed, new SealedAchievements());
achievements.put(GameType.Quest, new QuestAchievements());
achievements.put(GameType.PlanarConquest, new PlanarConquestAchievements());
achievements.put(GameType.Puzzle, new PuzzleAchievements());
achievements.put(GameType.Adventure, new AdventureAchievements());
}
// Translate gameType to appropriate type if needed // Translate gameType to appropriate type if needed
return switch (gameType) { return switch (gameType) {
case Constructed, Draft, Sealed, Quest, PlanarConquest, Puzzle, Adventure -> achievements.get(gameType); case Constructed, Draft, Sealed, Quest, PlanarConquest, Puzzle, Adventure -> achievements.get().get(gameType);
case AdventureEvent -> achievements.get(GameType.Adventure); case AdventureEvent -> achievements.get().get(GameType.Adventure);
case QuestDraft -> achievements.get(GameType.Quest); case QuestDraft -> achievements.get().get(GameType.Quest);
default -> achievements.get(GameType.Constructed); default -> achievements.get().get(GameType.Constructed);
}; };
} }
public static IStorage<CardBlock> getBlocks() { public static IStorage<CardBlock> getBlocks() {
if (blocks == null) { return blocks.get();
blocks = new StorageBase<>("Block definitions", new CardBlock.Reader(ForgeConstants.BLOCK_DATA_DIR + "blocks.txt", magicDb.getEditions()));
// SetblockLands
for (final CardBlock b : blocks) {
try {
magicDb.getBlockLands().add(b.getLandSet().getCode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
return blocks;
} }
public static QuestPreferences getQuestPreferences() { public static QuestPreferences getQuestPreferences() {
if (questPreferences == null) return questPreferences.get();
questPreferences = new QuestPreferences();
return questPreferences;
} }
public static ConquestPreferences getConquestPreferences() { public static ConquestPreferences getConquestPreferences() {
if (conquestPreferences == null) { return conquestPreferences.get();
conquestPreferences = new ConquestPreferences();
// initialize on first call...
ConquestUtil.updateRarityFilterOdds(conquestPreferences);
}
return conquestPreferences;
} }
public static GauntletData getGauntletData() { public static GauntletData getGauntletData() {
@@ -468,56 +417,34 @@ public final class FModel {
} }
public static GauntletMini getGauntletMini() { public static GauntletMini getGauntletMini() {
if (gauntlet == null) { return gauntletMini.get();
gauntlet = new GauntletMini();
}
return gauntlet;
} }
public static CardCollections getDecks() { public static CardCollections getDecks() {
if (decks == null) return decks.get();
decks = new CardCollections();
return decks;
} }
public static IStorage<ConquestPlane> getPlanes() { public static IStorage<ConquestPlane> getPlanes() {
if (planes == null) return planes.get();
planes = new StorageBase<>("Conquest planes", new ConquestPlane.Reader(ForgeConstants.CONQUEST_PLANES_DIR + "planes.txt"));
return planes;
} }
public static IStorage<QuestWorld> getWorlds() { public static IStorage<QuestWorld> getWorlds() {
if (worlds == null) { return worlds.get();
Map<String, QuestWorld> standardWorlds = new QuestWorld.Reader(ForgeConstants.QUEST_WORLD_DIR + "worlds.txt").readAll();
Map<String, QuestWorld> customWorlds = new QuestWorld.Reader(ForgeConstants.USER_QUEST_WORLD_DIR + "customworlds.txt").readAll();
customWorlds.values().forEach(world -> world.setCustom(true));
standardWorlds.putAll(customWorlds);
worlds = new StorageBase<>("Quest worlds", null, standardWorlds);
}
return worlds;
} }
public static GameFormat.Collection getFormats() { public static GameFormat.Collection getFormats() {
if (formats == null) { return formats.get();
formats = new GameFormat.Collection(new GameFormat.Reader( new File(ForgeConstants.FORMATS_DATA_DIR),
new File(ForgeConstants.USER_FORMATS_DIR), preferences.getPrefBoolean(FPref.LOAD_ARCHIVED_FORMATS)));
}
return formats;
} }
public static IStorage<CardBlock> getFantasyBlocks() { public static IStorage<CardBlock> getFantasyBlocks() {
if (fantasyBlocks == null) return fantasyBlocks.get();
fantasyBlocks = new StorageBase<>("Custom blocks", new CardBlock.Reader(ForgeConstants.BLOCK_DATA_DIR + "fantasyblocks.txt", magicDb.getEditions()));
return fantasyBlocks;
} }
public static IStorage<ThemedChaosDraft> getThemedChaosDrafts() { public static IStorage<ThemedChaosDraft> getThemedChaosDrafts() {
if (themedChaosDrafts == null) return themedChaosDrafts.get();
themedChaosDrafts = new StorageBase<>("Themed Chaos Drafts", new ThemedChaosDraft.Reader(ForgeConstants.BLOCK_DATA_DIR + "chaosdraftthemes.txt"));
return themedChaosDrafts;
} }
public static TournamentData getTournamentData() { return tournamentData; } public static TournamentData getTournamentData() { return tournamentData; }
public static void setTournamentData(TournamentData tournamentData) { FModel.tournamentData = tournamentData; } public static void setTournamentData(TournamentData tournamentData0) { tournamentData = tournamentData0; }
} }